1 #include "module_wrap.h"
2
3 #include "env.h"
4 #include "memory_tracker-inl.h"
5 #include "node_contextify.h"
6 #include "node_errors.h"
7 #include "node_external_reference.h"
8 #include "node_internals.h"
9 #include "node_process-inl.h"
10 #include "node_watchdog.h"
11 #include "util-inl.h"
12
13 #include <sys/stat.h> // S_IFDIR
14
15 #include <algorithm>
16
17 namespace node {
18 namespace loader {
19
20 using errors::TryCatchScope;
21
22 using node::contextify::ContextifyContext;
23 using v8::Array;
24 using v8::ArrayBufferView;
25 using v8::Context;
26 using v8::EscapableHandleScope;
27 using v8::FixedArray;
28 using v8::Function;
29 using v8::FunctionCallbackInfo;
30 using v8::FunctionTemplate;
31 using v8::HandleScope;
32 using v8::Int32;
33 using v8::Integer;
34 using v8::IntegrityLevel;
35 using v8::Isolate;
36 using v8::Local;
37 using v8::MaybeLocal;
38 using v8::MicrotaskQueue;
39 using v8::Module;
40 using v8::ModuleRequest;
41 using v8::Object;
42 using v8::PrimitiveArray;
43 using v8::Promise;
44 using v8::ScriptCompiler;
45 using v8::ScriptOrigin;
46 using v8::String;
47 using v8::Symbol;
48 using v8::UnboundModuleScript;
49 using v8::Undefined;
50 using v8::Value;
51
ModuleWrap(Environment * env,Local<Object> object,Local<Module> module,Local<String> url,Local<Object> context_object,Local<Value> synthetic_evaluation_step)52 ModuleWrap::ModuleWrap(Environment* env,
53 Local<Object> object,
54 Local<Module> module,
55 Local<String> url,
56 Local<Object> context_object,
57 Local<Value> synthetic_evaluation_step)
58 : BaseObject(env, object),
59 module_(env->isolate(), module),
60 module_hash_(module->GetIdentityHash()) {
61 object->SetInternalFieldForNodeCore(kModuleSlot, module);
62 object->SetInternalField(kURLSlot, url);
63 object->SetInternalField(kSyntheticEvaluationStepsSlot,
64 synthetic_evaluation_step);
65 object->SetInternalField(kContextObjectSlot, context_object);
66
67 if (!synthetic_evaluation_step->IsUndefined()) {
68 synthetic_ = true;
69 }
70 MakeWeak();
71 module_.SetWeak();
72 }
73
~ModuleWrap()74 ModuleWrap::~ModuleWrap() {
75 HandleScope scope(env()->isolate());
76 auto range = env()->hash_to_module_map.equal_range(module_hash_);
77 for (auto it = range.first; it != range.second; ++it) {
78 if (it->second == this) {
79 env()->hash_to_module_map.erase(it);
80 break;
81 }
82 }
83 }
84
context() const85 Local<Context> ModuleWrap::context() const {
86 Local<Value> obj = object()->GetInternalField(kContextObjectSlot).As<Value>();
87 // If this fails, there is likely a bug e.g. ModuleWrap::context() is accessed
88 // before the ModuleWrap constructor completes.
89 CHECK(obj->IsObject());
90 return obj.As<Object>()->GetCreationContext().ToLocalChecked();
91 }
92
GetFromModule(Environment * env,Local<Module> module)93 ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
94 Local<Module> module) {
95 auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash());
96 for (auto it = range.first; it != range.second; ++it) {
97 if (it->second->module_ == module) {
98 return it->second;
99 }
100 }
101 return nullptr;
102 }
103
104 // new ModuleWrap(url, context, source, lineOffset, columnOffset)
105 // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
New(const FunctionCallbackInfo<Value> & args)106 void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
107 CHECK(args.IsConstructCall());
108 CHECK_GE(args.Length(), 3);
109
110 Environment* env = Environment::GetCurrent(args);
111 Isolate* isolate = env->isolate();
112
113 Local<Object> that = args.This();
114
115 CHECK(args[0]->IsString());
116 Local<String> url = args[0].As<String>();
117
118 Local<Context> context;
119 ContextifyContext* contextify_context = nullptr;
120 if (args[1]->IsUndefined()) {
121 context = that->GetCreationContext().ToLocalChecked();
122 } else {
123 CHECK(args[1]->IsObject());
124 contextify_context = ContextifyContext::ContextFromContextifiedSandbox(
125 env, args[1].As<Object>());
126 CHECK_NOT_NULL(contextify_context);
127 context = contextify_context->context();
128 }
129
130 int line_offset = 0;
131 int column_offset = 0;
132
133 bool synthetic = args[2]->IsArray();
134 if (synthetic) {
135 // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
136 CHECK(args[3]->IsFunction());
137 } else {
138 // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
139 CHECK(args[2]->IsString());
140 CHECK(args[3]->IsNumber());
141 line_offset = args[3].As<Int32>()->Value();
142 CHECK(args[4]->IsNumber());
143 column_offset = args[4].As<Int32>()->Value();
144 }
145
146 Local<PrimitiveArray> host_defined_options =
147 PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
148 Local<Symbol> id_symbol = Symbol::New(isolate, url);
149 host_defined_options->Set(isolate, HostDefinedOptions::kID, id_symbol);
150
151 ShouldNotAbortOnUncaughtScope no_abort_scope(env);
152 TryCatchScope try_catch(env);
153
154 Local<Module> module;
155
156 {
157 Context::Scope context_scope(context);
158 if (synthetic) {
159 CHECK(args[2]->IsArray());
160 Local<Array> export_names_arr = args[2].As<Array>();
161
162 uint32_t len = export_names_arr->Length();
163 std::vector<Local<String>> export_names(len);
164 for (uint32_t i = 0; i < len; i++) {
165 Local<Value> export_name_val =
166 export_names_arr->Get(context, i).ToLocalChecked();
167 CHECK(export_name_val->IsString());
168 export_names[i] = export_name_val.As<String>();
169 }
170
171 module = Module::CreateSyntheticModule(isolate, url, export_names,
172 SyntheticModuleEvaluationStepsCallback);
173 } else {
174 ScriptCompiler::CachedData* cached_data = nullptr;
175 if (!args[5]->IsUndefined()) {
176 CHECK(args[5]->IsArrayBufferView());
177 Local<ArrayBufferView> cached_data_buf = args[5].As<ArrayBufferView>();
178 uint8_t* data =
179 static_cast<uint8_t*>(cached_data_buf->Buffer()->Data());
180 cached_data =
181 new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(),
182 cached_data_buf->ByteLength());
183 }
184
185 Local<String> source_text = args[2].As<String>();
186 ScriptOrigin origin(isolate,
187 url,
188 line_offset,
189 column_offset,
190 true, // is cross origin
191 -1, // script id
192 Local<Value>(), // source map URL
193 false, // is opaque (?)
194 false, // is WASM
195 true, // is ES Module
196 host_defined_options);
197 ScriptCompiler::Source source(source_text, origin, cached_data);
198 ScriptCompiler::CompileOptions options;
199 if (source.GetCachedData() == nullptr) {
200 options = ScriptCompiler::kNoCompileOptions;
201 } else {
202 options = ScriptCompiler::kConsumeCodeCache;
203 }
204 if (!ScriptCompiler::CompileModule(isolate, &source, options)
205 .ToLocal(&module)) {
206 if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
207 CHECK(!try_catch.Message().IsEmpty());
208 CHECK(!try_catch.Exception().IsEmpty());
209 AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
210 ErrorHandlingMode::MODULE_ERROR);
211 try_catch.ReThrow();
212 }
213 return;
214 }
215 if (options == ScriptCompiler::kConsumeCodeCache &&
216 source.GetCachedData()->rejected) {
217 THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED(
218 env, "cachedData buffer was rejected");
219 try_catch.ReThrow();
220 return;
221 }
222 }
223 }
224
225 if (!that->Set(context, env->url_string(), url).FromMaybe(false)) {
226 return;
227 }
228
229 if (that->SetPrivate(context, env->host_defined_option_symbol(), id_symbol)
230 .IsNothing()) {
231 return;
232 }
233
234 // Use the extras object as an object whose GetCreationContext() will be the
235 // original `context`, since the `Context` itself strictly speaking cannot
236 // be stored in an internal field.
237 Local<Object> context_object = context->GetExtrasBindingObject();
238 Local<Value> synthetic_evaluation_step =
239 synthetic ? args[3] : Undefined(env->isolate()).As<v8::Value>();
240
241 ModuleWrap* obj = new ModuleWrap(
242 env, that, module, url, context_object, synthetic_evaluation_step);
243
244 obj->contextify_context_ = contextify_context;
245
246 env->hash_to_module_map.emplace(module->GetIdentityHash(), obj);
247
248 that->SetIntegrityLevel(context, IntegrityLevel::kFrozen);
249 args.GetReturnValue().Set(that);
250 }
251
createImportAttributesContainer(Environment * env,Isolate * isolate,Local<FixedArray> raw_attributes,const int elements_per_attribute)252 static Local<Object> createImportAttributesContainer(
253 Environment* env,
254 Isolate* isolate,
255 Local<FixedArray> raw_attributes,
256 const int elements_per_attribute) {
257 CHECK_EQ(raw_attributes->Length() % elements_per_attribute, 0);
258 Local<Object> attributes =
259 Object::New(isolate, v8::Null(env->isolate()), nullptr, nullptr, 0);
260 for (int i = 0; i < raw_attributes->Length(); i += elements_per_attribute) {
261 attributes
262 ->Set(env->context(),
263 raw_attributes->Get(env->context(), i).As<String>(),
264 raw_attributes->Get(env->context(), i + 1).As<Value>())
265 .ToChecked();
266 }
267
268 return attributes;
269 }
270
Link(const FunctionCallbackInfo<Value> & args)271 void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
272 Environment* env = Environment::GetCurrent(args);
273 Isolate* isolate = args.GetIsolate();
274
275 CHECK_EQ(args.Length(), 1);
276 CHECK(args[0]->IsFunction());
277
278 Local<Object> that = args.This();
279
280 ModuleWrap* obj;
281 ASSIGN_OR_RETURN_UNWRAP(&obj, that);
282
283 if (obj->linked_)
284 return;
285 obj->linked_ = true;
286
287 Local<Function> resolver_arg = args[0].As<Function>();
288
289 Local<Context> mod_context = obj->context();
290 Local<Module> module = obj->module_.Get(isolate);
291
292 Local<FixedArray> module_requests = module->GetModuleRequests();
293 const int module_requests_length = module_requests->Length();
294 MaybeStackBuffer<Local<Value>, 16> promises(module_requests_length);
295
296 // call the dependency resolve callbacks
297 for (int i = 0; i < module_requests_length; i++) {
298 Local<ModuleRequest> module_request =
299 module_requests->Get(env->context(), i).As<ModuleRequest>();
300 Local<String> specifier = module_request->GetSpecifier();
301 Utf8Value specifier_utf8(env->isolate(), specifier);
302 std::string specifier_std(*specifier_utf8, specifier_utf8.length());
303
304 Local<FixedArray> raw_attributes = module_request->GetImportAssertions();
305 Local<Object> attributes =
306 createImportAttributesContainer(env, isolate, raw_attributes, 3);
307
308 Local<Value> argv[] = {
309 specifier,
310 attributes,
311 };
312
313 MaybeLocal<Value> maybe_resolve_return_value =
314 resolver_arg->Call(mod_context, that, arraysize(argv), argv);
315 if (maybe_resolve_return_value.IsEmpty()) {
316 return;
317 }
318 Local<Value> resolve_return_value =
319 maybe_resolve_return_value.ToLocalChecked();
320 if (!resolve_return_value->IsPromise()) {
321 THROW_ERR_VM_MODULE_LINK_FAILURE(
322 env, "request for '%s' did not return promise", specifier_std);
323 return;
324 }
325 Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
326 obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_promise);
327
328 promises[i] = resolve_promise;
329 }
330
331 args.GetReturnValue().Set(
332 Array::New(isolate, promises.out(), promises.length()));
333 }
334
Instantiate(const FunctionCallbackInfo<Value> & args)335 void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
336 Environment* env = Environment::GetCurrent(args);
337 Isolate* isolate = args.GetIsolate();
338 ModuleWrap* obj;
339 ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
340 Local<Context> context = obj->context();
341 Local<Module> module = obj->module_.Get(isolate);
342 TryCatchScope try_catch(env);
343 USE(module->InstantiateModule(context, ResolveModuleCallback));
344
345 // clear resolve cache on instantiate
346 obj->resolve_cache_.clear();
347
348 if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
349 CHECK(!try_catch.Message().IsEmpty());
350 CHECK(!try_catch.Exception().IsEmpty());
351 AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
352 ErrorHandlingMode::MODULE_ERROR);
353 try_catch.ReThrow();
354 return;
355 }
356 }
357
Evaluate(const FunctionCallbackInfo<Value> & args)358 void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) {
359 Environment* env = Environment::GetCurrent(args);
360 Isolate* isolate = env->isolate();
361 ModuleWrap* obj;
362 ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
363 Local<Context> context = obj->context();
364 Local<Module> module = obj->module_.Get(isolate);
365
366 ContextifyContext* contextify_context = obj->contextify_context_;
367 std::shared_ptr<MicrotaskQueue> microtask_queue;
368 if (contextify_context != nullptr)
369 microtask_queue = contextify_context->microtask_queue();
370
371 // module.evaluate(timeout, breakOnSigint)
372 CHECK_EQ(args.Length(), 2);
373
374 CHECK(args[0]->IsNumber());
375 int64_t timeout = args[0]->IntegerValue(env->context()).FromJust();
376
377 CHECK(args[1]->IsBoolean());
378 bool break_on_sigint = args[1]->IsTrue();
379
380 ShouldNotAbortOnUncaughtScope no_abort_scope(env);
381 TryCatchScope try_catch(env);
382 Isolate::SafeForTerminationScope safe_for_termination(env->isolate());
383
384 bool timed_out = false;
385 bool received_signal = false;
386 MaybeLocal<Value> result;
387 auto run = [&]() {
388 MaybeLocal<Value> result = module->Evaluate(context);
389 if (!result.IsEmpty() && microtask_queue)
390 microtask_queue->PerformCheckpoint(isolate);
391 return result;
392 };
393 if (break_on_sigint && timeout != -1) {
394 Watchdog wd(isolate, timeout, &timed_out);
395 SigintWatchdog swd(isolate, &received_signal);
396 result = run();
397 } else if (break_on_sigint) {
398 SigintWatchdog swd(isolate, &received_signal);
399 result = run();
400 } else if (timeout != -1) {
401 Watchdog wd(isolate, timeout, &timed_out);
402 result = run();
403 } else {
404 result = run();
405 }
406
407 if (result.IsEmpty()) {
408 CHECK(try_catch.HasCaught());
409 }
410
411 // Convert the termination exception into a regular exception.
412 if (timed_out || received_signal) {
413 if (!env->is_main_thread() && env->is_stopping())
414 return;
415 env->isolate()->CancelTerminateExecution();
416 // It is possible that execution was terminated by another timeout in
417 // which this timeout is nested, so check whether one of the watchdogs
418 // from this invocation is responsible for termination.
419 if (timed_out) {
420 THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, timeout);
421 } else if (received_signal) {
422 THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(env);
423 }
424 }
425
426 if (try_catch.HasCaught()) {
427 if (!try_catch.HasTerminated())
428 try_catch.ReThrow();
429 return;
430 }
431
432 args.GetReturnValue().Set(result.ToLocalChecked());
433 }
434
GetNamespace(const FunctionCallbackInfo<Value> & args)435 void ModuleWrap::GetNamespace(const FunctionCallbackInfo<Value>& args) {
436 Environment* env = Environment::GetCurrent(args);
437 Isolate* isolate = args.GetIsolate();
438 ModuleWrap* obj;
439 ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
440
441 Local<Module> module = obj->module_.Get(isolate);
442
443 switch (module->GetStatus()) {
444 case v8::Module::Status::kUninstantiated:
445 case v8::Module::Status::kInstantiating:
446 return env->ThrowError(
447 "cannot get namespace, module has not been instantiated");
448 case v8::Module::Status::kInstantiated:
449 case v8::Module::Status::kEvaluating:
450 case v8::Module::Status::kEvaluated:
451 case v8::Module::Status::kErrored:
452 break;
453 default:
454 UNREACHABLE();
455 }
456
457 Local<Value> result = module->GetModuleNamespace();
458 args.GetReturnValue().Set(result);
459 }
460
GetStatus(const FunctionCallbackInfo<Value> & args)461 void ModuleWrap::GetStatus(const FunctionCallbackInfo<Value>& args) {
462 Isolate* isolate = args.GetIsolate();
463 ModuleWrap* obj;
464 ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
465
466 Local<Module> module = obj->module_.Get(isolate);
467
468 args.GetReturnValue().Set(module->GetStatus());
469 }
470
GetStaticDependencySpecifiers(const FunctionCallbackInfo<Value> & args)471 void ModuleWrap::GetStaticDependencySpecifiers(
472 const FunctionCallbackInfo<Value>& args) {
473 Environment* env = Environment::GetCurrent(args);
474 ModuleWrap* obj;
475 ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
476
477 Local<Module> module = obj->module_.Get(env->isolate());
478
479 Local<FixedArray> module_requests = module->GetModuleRequests();
480 int count = module_requests->Length();
481
482 MaybeStackBuffer<Local<Value>, 16> specifiers(count);
483
484 for (int i = 0; i < count; i++) {
485 Local<ModuleRequest> module_request =
486 module_requests->Get(env->context(), i).As<ModuleRequest>();
487 specifiers[i] = module_request->GetSpecifier();
488 }
489
490 args.GetReturnValue().Set(
491 Array::New(env->isolate(), specifiers.out(), count));
492 }
493
GetError(const FunctionCallbackInfo<Value> & args)494 void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
495 Isolate* isolate = args.GetIsolate();
496 ModuleWrap* obj;
497 ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
498
499 Local<Module> module = obj->module_.Get(isolate);
500 args.GetReturnValue().Set(module->GetException());
501 }
502
ResolveModuleCallback(Local<Context> context,Local<String> specifier,Local<FixedArray> import_attributes,Local<Module> referrer)503 MaybeLocal<Module> ModuleWrap::ResolveModuleCallback(
504 Local<Context> context,
505 Local<String> specifier,
506 Local<FixedArray> import_attributes,
507 Local<Module> referrer) {
508 Environment* env = Environment::GetCurrent(context);
509 if (env == nullptr) {
510 Isolate* isolate = context->GetIsolate();
511 THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
512 return MaybeLocal<Module>();
513 }
514
515 Isolate* isolate = env->isolate();
516
517 Utf8Value specifier_utf8(isolate, specifier);
518 std::string specifier_std(*specifier_utf8, specifier_utf8.length());
519
520 ModuleWrap* dependent = GetFromModule(env, referrer);
521 if (dependent == nullptr) {
522 THROW_ERR_VM_MODULE_LINK_FAILURE(
523 env, "request for '%s' is from invalid module", specifier_std);
524 return MaybeLocal<Module>();
525 }
526
527 if (dependent->resolve_cache_.count(specifier_std) != 1) {
528 THROW_ERR_VM_MODULE_LINK_FAILURE(
529 env, "request for '%s' is not in cache", specifier_std);
530 return MaybeLocal<Module>();
531 }
532
533 Local<Promise> resolve_promise =
534 dependent->resolve_cache_[specifier_std].Get(isolate);
535
536 if (resolve_promise->State() != Promise::kFulfilled) {
537 THROW_ERR_VM_MODULE_LINK_FAILURE(
538 env, "request for '%s' is not yet fulfilled", specifier_std);
539 return MaybeLocal<Module>();
540 }
541
542 Local<Object> module_object = resolve_promise->Result().As<Object>();
543 if (module_object.IsEmpty() || !module_object->IsObject()) {
544 THROW_ERR_VM_MODULE_LINK_FAILURE(
545 env, "request for '%s' did not return an object", specifier_std);
546 return MaybeLocal<Module>();
547 }
548
549 ModuleWrap* module;
550 ASSIGN_OR_RETURN_UNWRAP(&module, module_object, MaybeLocal<Module>());
551 return module->module_.Get(isolate);
552 }
553
ImportModuleDynamically(Local<Context> context,Local<v8::Data> host_defined_options,Local<Value> resource_name,Local<String> specifier,Local<FixedArray> import_attributes)554 static MaybeLocal<Promise> ImportModuleDynamically(
555 Local<Context> context,
556 Local<v8::Data> host_defined_options,
557 Local<Value> resource_name,
558 Local<String> specifier,
559 Local<FixedArray> import_attributes) {
560 Isolate* isolate = context->GetIsolate();
561 Environment* env = Environment::GetCurrent(context);
562 if (env == nullptr) {
563 THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
564 return MaybeLocal<Promise>();
565 }
566
567 EscapableHandleScope handle_scope(isolate);
568
569 Local<Function> import_callback =
570 env->host_import_module_dynamically_callback();
571
572 Local<FixedArray> options = host_defined_options.As<FixedArray>();
573 if (options->Length() != HostDefinedOptions::kLength) {
574 Local<Promise::Resolver> resolver;
575 if (!Promise::Resolver::New(context).ToLocal(&resolver)) return {};
576 resolver
577 ->Reject(context,
578 v8::Exception::TypeError(FIXED_ONE_BYTE_STRING(
579 context->GetIsolate(), "Invalid host defined options")))
580 .ToChecked();
581 return handle_scope.Escape(resolver->GetPromise());
582 }
583
584 Local<Value> object;
585
586 Local<Symbol> id =
587 options->Get(context, HostDefinedOptions::kID).As<Symbol>();
588
589 Local<Object> attributes =
590 createImportAttributesContainer(env, isolate, import_attributes, 2);
591
592 Local<Value> import_args[] = {
593 id,
594 Local<Value>(specifier),
595 attributes,
596 };
597
598 Local<Value> result;
599 if (import_callback->Call(
600 context,
601 Undefined(isolate),
602 arraysize(import_args),
603 import_args).ToLocal(&result)) {
604 CHECK(result->IsPromise());
605 return handle_scope.Escape(result.As<Promise>());
606 }
607
608 return MaybeLocal<Promise>();
609 }
610
SetImportModuleDynamicallyCallback(const FunctionCallbackInfo<Value> & args)611 void ModuleWrap::SetImportModuleDynamicallyCallback(
612 const FunctionCallbackInfo<Value>& args) {
613 Isolate* isolate = args.GetIsolate();
614 Environment* env = Environment::GetCurrent(args);
615 HandleScope handle_scope(isolate);
616
617 CHECK_EQ(args.Length(), 1);
618 CHECK(args[0]->IsFunction());
619 Local<Function> import_callback = args[0].As<Function>();
620 env->set_host_import_module_dynamically_callback(import_callback);
621
622 isolate->SetHostImportModuleDynamicallyCallback(ImportModuleDynamically);
623 }
624
HostInitializeImportMetaObjectCallback(Local<Context> context,Local<Module> module,Local<Object> meta)625 void ModuleWrap::HostInitializeImportMetaObjectCallback(
626 Local<Context> context, Local<Module> module, Local<Object> meta) {
627 Environment* env = Environment::GetCurrent(context);
628 if (env == nullptr)
629 return;
630 ModuleWrap* module_wrap = GetFromModule(env, module);
631
632 if (module_wrap == nullptr) {
633 return;
634 }
635
636 Local<Object> wrap = module_wrap->object();
637 Local<Function> callback =
638 env->host_initialize_import_meta_object_callback();
639 Local<Value> id;
640 if (!wrap->GetPrivate(context, env->host_defined_option_symbol())
641 .ToLocal(&id)) {
642 return;
643 }
644 DCHECK(id->IsSymbol());
645 Local<Value> args[] = {id, meta};
646 TryCatchScope try_catch(env);
647 USE(callback->Call(
648 context, Undefined(env->isolate()), arraysize(args), args));
649 if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
650 try_catch.ReThrow();
651 }
652 }
653
SetInitializeImportMetaObjectCallback(const FunctionCallbackInfo<Value> & args)654 void ModuleWrap::SetInitializeImportMetaObjectCallback(
655 const FunctionCallbackInfo<Value>& args) {
656 Environment* env = Environment::GetCurrent(args);
657 Isolate* isolate = env->isolate();
658
659 CHECK_EQ(args.Length(), 1);
660 CHECK(args[0]->IsFunction());
661 Local<Function> import_meta_callback = args[0].As<Function>();
662 env->set_host_initialize_import_meta_object_callback(import_meta_callback);
663
664 isolate->SetHostInitializeImportMetaObjectCallback(
665 HostInitializeImportMetaObjectCallback);
666 }
667
SyntheticModuleEvaluationStepsCallback(Local<Context> context,Local<Module> module)668 MaybeLocal<Value> ModuleWrap::SyntheticModuleEvaluationStepsCallback(
669 Local<Context> context, Local<Module> module) {
670 Environment* env = Environment::GetCurrent(context);
671 Isolate* isolate = env->isolate();
672
673 ModuleWrap* obj = GetFromModule(env, module);
674
675 TryCatchScope try_catch(env);
676 Local<Function> synthetic_evaluation_steps =
677 obj->object()
678 ->GetInternalField(kSyntheticEvaluationStepsSlot)
679 .As<Value>()
680 .As<Function>();
681 obj->object()->SetInternalField(
682 kSyntheticEvaluationStepsSlot, Undefined(isolate));
683 MaybeLocal<Value> ret = synthetic_evaluation_steps->Call(context,
684 obj->object(), 0, nullptr);
685 if (ret.IsEmpty()) {
686 CHECK(try_catch.HasCaught());
687 }
688 if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
689 CHECK(!try_catch.Message().IsEmpty());
690 CHECK(!try_catch.Exception().IsEmpty());
691 try_catch.ReThrow();
692 return MaybeLocal<Value>();
693 }
694
695 Local<Promise::Resolver> resolver;
696 if (!Promise::Resolver::New(context).ToLocal(&resolver)) {
697 return MaybeLocal<Value>();
698 }
699
700 resolver->Resolve(context, Undefined(isolate)).ToChecked();
701 return resolver->GetPromise();
702 }
703
SetSyntheticExport(const FunctionCallbackInfo<Value> & args)704 void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo<Value>& args) {
705 Isolate* isolate = args.GetIsolate();
706 Local<Object> that = args.This();
707
708 ModuleWrap* obj;
709 ASSIGN_OR_RETURN_UNWRAP(&obj, that);
710
711 CHECK(obj->synthetic_);
712
713 CHECK_EQ(args.Length(), 2);
714
715 CHECK(args[0]->IsString());
716 Local<String> export_name = args[0].As<String>();
717
718 Local<Value> export_value = args[1];
719
720 Local<Module> module = obj->module_.Get(isolate);
721 USE(module->SetSyntheticModuleExport(isolate, export_name, export_value));
722 }
723
CreateCachedData(const FunctionCallbackInfo<Value> & args)724 void ModuleWrap::CreateCachedData(const FunctionCallbackInfo<Value>& args) {
725 Isolate* isolate = args.GetIsolate();
726 Local<Object> that = args.This();
727
728 ModuleWrap* obj;
729 ASSIGN_OR_RETURN_UNWRAP(&obj, that);
730
731 CHECK(!obj->synthetic_);
732
733 Local<Module> module = obj->module_.Get(isolate);
734
735 CHECK_LT(module->GetStatus(), v8::Module::Status::kEvaluating);
736
737 Local<UnboundModuleScript> unbound_module_script =
738 module->GetUnboundModuleScript();
739 std::unique_ptr<ScriptCompiler::CachedData> cached_data(
740 ScriptCompiler::CreateCodeCache(unbound_module_script));
741 Environment* env = Environment::GetCurrent(args);
742 if (!cached_data) {
743 args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked());
744 } else {
745 MaybeLocal<Object> buf =
746 Buffer::Copy(env,
747 reinterpret_cast<const char*>(cached_data->data),
748 cached_data->length);
749 args.GetReturnValue().Set(buf.ToLocalChecked());
750 }
751 }
752
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)753 void ModuleWrap::Initialize(Local<Object> target,
754 Local<Value> unused,
755 Local<Context> context,
756 void* priv) {
757 Environment* env = Environment::GetCurrent(context);
758 Isolate* isolate = env->isolate();
759
760 Local<FunctionTemplate> tpl = NewFunctionTemplate(isolate, New);
761 tpl->InstanceTemplate()->SetInternalFieldCount(
762 ModuleWrap::kInternalFieldCount);
763 tpl->Inherit(BaseObject::GetConstructorTemplate(env));
764
765 SetProtoMethod(isolate, tpl, "link", Link);
766 SetProtoMethod(isolate, tpl, "instantiate", Instantiate);
767 SetProtoMethod(isolate, tpl, "evaluate", Evaluate);
768 SetProtoMethod(isolate, tpl, "setExport", SetSyntheticExport);
769 SetProtoMethodNoSideEffect(
770 isolate, tpl, "createCachedData", CreateCachedData);
771 SetProtoMethodNoSideEffect(isolate, tpl, "getNamespace", GetNamespace);
772 SetProtoMethodNoSideEffect(isolate, tpl, "getStatus", GetStatus);
773 SetProtoMethodNoSideEffect(isolate, tpl, "getError", GetError);
774 SetProtoMethodNoSideEffect(isolate,
775 tpl,
776 "getStaticDependencySpecifiers",
777 GetStaticDependencySpecifiers);
778
779 SetConstructorFunction(context, target, "ModuleWrap", tpl);
780
781 SetMethod(context,
782 target,
783 "setImportModuleDynamicallyCallback",
784 SetImportModuleDynamicallyCallback);
785 SetMethod(context,
786 target,
787 "setInitializeImportMetaObjectCallback",
788 SetInitializeImportMetaObjectCallback);
789
790 #define V(name) \
791 target->Set(context, \
792 FIXED_ONE_BYTE_STRING(env->isolate(), #name), \
793 Integer::New(env->isolate(), Module::Status::name)) \
794 .FromJust()
795 V(kUninstantiated);
796 V(kInstantiating);
797 V(kInstantiated);
798 V(kEvaluating);
799 V(kEvaluated);
800 V(kErrored);
801 #undef V
802 }
803
RegisterExternalReferences(ExternalReferenceRegistry * registry)804 void ModuleWrap::RegisterExternalReferences(
805 ExternalReferenceRegistry* registry) {
806 registry->Register(New);
807
808 registry->Register(Link);
809 registry->Register(Instantiate);
810 registry->Register(Evaluate);
811 registry->Register(SetSyntheticExport);
812 registry->Register(CreateCachedData);
813 registry->Register(GetNamespace);
814 registry->Register(GetStatus);
815 registry->Register(GetError);
816 registry->Register(GetStaticDependencySpecifiers);
817
818 registry->Register(SetImportModuleDynamicallyCallback);
819 registry->Register(SetInitializeImportMetaObjectCallback);
820 }
821 } // namespace loader
822 } // namespace node
823
824 NODE_BINDING_CONTEXT_AWARE_INTERNAL(module_wrap,
825 node::loader::ModuleWrap::Initialize)
826 NODE_BINDING_EXTERNAL_REFERENCE(
827 module_wrap, node::loader::ModuleWrap::RegisterExternalReferences)
828