• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_internals.h"
8 #include "node_process-inl.h"
9 #include "node_watchdog.h"
10 #include "util-inl.h"
11 
12 #include <sys/stat.h>  // S_IFDIR
13 
14 #include <algorithm>
15 
16 namespace node {
17 namespace loader {
18 
19 using errors::TryCatchScope;
20 
21 using node::contextify::ContextifyContext;
22 using v8::Array;
23 using v8::ArrayBufferView;
24 using v8::Context;
25 using v8::EscapableHandleScope;
26 using v8::FixedArray;
27 using v8::Function;
28 using v8::FunctionCallbackInfo;
29 using v8::FunctionTemplate;
30 using v8::HandleScope;
31 using v8::Int32;
32 using v8::Integer;
33 using v8::IntegrityLevel;
34 using v8::Isolate;
35 using v8::Local;
36 using v8::MaybeLocal;
37 using v8::MicrotaskQueue;
38 using v8::Module;
39 using v8::ModuleRequest;
40 using v8::Number;
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::UnboundModuleScript;
48 using v8::Undefined;
49 using v8::Value;
50 
ModuleWrap(Environment * env,Local<Object> object,Local<Module> module,Local<String> url)51 ModuleWrap::ModuleWrap(Environment* env,
52                        Local<Object> object,
53                        Local<Module> module,
54                        Local<String> url)
55   : BaseObject(env, object),
56     module_(env->isolate(), module),
57     id_(env->get_next_module_id()) {
58   env->id_to_module_map.emplace(id_, this);
59 
60   Local<Value> undefined = Undefined(env->isolate());
61   object->SetInternalField(kURLSlot, url);
62   object->SetInternalField(kSyntheticEvaluationStepsSlot, undefined);
63   object->SetInternalField(kContextObjectSlot, undefined);
64 }
65 
~ModuleWrap()66 ModuleWrap::~ModuleWrap() {
67   HandleScope scope(env()->isolate());
68   Local<Module> module = module_.Get(env()->isolate());
69   env()->id_to_module_map.erase(id_);
70   auto range = env()->hash_to_module_map.equal_range(module->GetIdentityHash());
71   for (auto it = range.first; it != range.second; ++it) {
72     if (it->second == this) {
73       env()->hash_to_module_map.erase(it);
74       break;
75     }
76   }
77 }
78 
context() const79 Local<Context> ModuleWrap::context() const {
80   Local<Value> obj = object()->GetInternalField(kContextObjectSlot);
81   if (obj.IsEmpty()) return {};
82   return obj.As<Object>()->GetCreationContext().ToLocalChecked();
83 }
84 
GetFromModule(Environment * env,Local<Module> module)85 ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
86                                       Local<Module> module) {
87   auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash());
88   for (auto it = range.first; it != range.second; ++it) {
89     if (it->second->module_ == module) {
90       return it->second;
91     }
92   }
93   return nullptr;
94 }
95 
GetFromID(Environment * env,uint32_t id)96 ModuleWrap* ModuleWrap::GetFromID(Environment* env, uint32_t id) {
97   auto module_wrap_it = env->id_to_module_map.find(id);
98   if (module_wrap_it == env->id_to_module_map.end()) {
99     return nullptr;
100   }
101   return module_wrap_it->second;
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   host_defined_options->Set(isolate, HostDefinedOptions::kType,
149                             Number::New(isolate, ScriptType::kModule));
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   ModuleWrap* obj = new ModuleWrap(env, that, module, url);
230 
231   if (synthetic) {
232     obj->synthetic_ = true;
233     obj->object()->SetInternalField(kSyntheticEvaluationStepsSlot, args[3]);
234   }
235 
236   // Use the extras object as an object whose GetCreationContext() will be the
237   // original `context`, since the `Context` itself strictly speaking cannot
238   // be stored in an internal field.
239   obj->object()->SetInternalField(kContextObjectSlot,
240       context->GetExtrasBindingObject());
241   obj->contextify_context_ = contextify_context;
242 
243   env->hash_to_module_map.emplace(module->GetIdentityHash(), obj);
244 
245   host_defined_options->Set(isolate, HostDefinedOptions::kID,
246                             Number::New(isolate, obj->id()));
247 
248   that->SetIntegrityLevel(context, IntegrityLevel::kFrozen);
249   args.GetReturnValue().Set(that);
250 }
251 
createImportAssertionContainer(Environment * env,Isolate * isolate,Local<FixedArray> raw_assertions)252 static Local<Object> createImportAssertionContainer(Environment* env,
253   Isolate* isolate, Local<FixedArray> raw_assertions) {
254   Local<Object> assertions =
255         Object::New(isolate, v8::Null(env->isolate()), nullptr, nullptr, 0);
256   for (int i = 0; i < raw_assertions->Length(); i += 3) {
257       assertions
258           ->Set(env->context(),
259                 raw_assertions->Get(env->context(), i).As<String>(),
260                 raw_assertions->Get(env->context(), i + 1).As<Value>())
261           .ToChecked();
262   }
263 
264   return assertions;
265 }
266 
Link(const FunctionCallbackInfo<Value> & args)267 void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
268   Environment* env = Environment::GetCurrent(args);
269   Isolate* isolate = args.GetIsolate();
270 
271   CHECK_EQ(args.Length(), 1);
272   CHECK(args[0]->IsFunction());
273 
274   Local<Object> that = args.This();
275 
276   ModuleWrap* obj;
277   ASSIGN_OR_RETURN_UNWRAP(&obj, that);
278 
279   if (obj->linked_)
280     return;
281   obj->linked_ = true;
282 
283   Local<Function> resolver_arg = args[0].As<Function>();
284 
285   Local<Context> mod_context = obj->context();
286   Local<Module> module = obj->module_.Get(isolate);
287 
288   Local<FixedArray> module_requests = module->GetModuleRequests();
289   const int module_requests_length = module_requests->Length();
290   MaybeStackBuffer<Local<Value>, 16> promises(module_requests_length);
291 
292   // call the dependency resolve callbacks
293   for (int i = 0; i < module_requests_length; i++) {
294     Local<ModuleRequest> module_request =
295       module_requests->Get(env->context(), i).As<ModuleRequest>();
296     Local<String> specifier = module_request->GetSpecifier();
297     Utf8Value specifier_utf8(env->isolate(), specifier);
298     std::string specifier_std(*specifier_utf8, specifier_utf8.length());
299 
300     Local<FixedArray> raw_assertions = module_request->GetImportAssertions();
301     Local<Object> assertions =
302       createImportAssertionContainer(env, isolate, raw_assertions);
303 
304     Local<Value> argv[] = {
305         specifier,
306         assertions,
307     };
308 
309     MaybeLocal<Value> maybe_resolve_return_value =
310         resolver_arg->Call(mod_context, that, arraysize(argv), argv);
311     if (maybe_resolve_return_value.IsEmpty()) {
312       return;
313     }
314     Local<Value> resolve_return_value =
315         maybe_resolve_return_value.ToLocalChecked();
316     if (!resolve_return_value->IsPromise()) {
317       THROW_ERR_VM_MODULE_LINK_FAILURE(
318           env, "request for '%s' did not return promise", specifier_std);
319       return;
320     }
321     Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
322     obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_promise);
323 
324     promises[i] = resolve_promise;
325   }
326 
327   args.GetReturnValue().Set(
328       Array::New(isolate, promises.out(), promises.length()));
329 }
330 
Instantiate(const FunctionCallbackInfo<Value> & args)331 void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
332   Environment* env = Environment::GetCurrent(args);
333   Isolate* isolate = args.GetIsolate();
334   ModuleWrap* obj;
335   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
336   Local<Context> context = obj->context();
337   Local<Module> module = obj->module_.Get(isolate);
338   TryCatchScope try_catch(env);
339   USE(module->InstantiateModule(context, ResolveModuleCallback));
340 
341   // clear resolve cache on instantiate
342   obj->resolve_cache_.clear();
343 
344   if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
345     CHECK(!try_catch.Message().IsEmpty());
346     CHECK(!try_catch.Exception().IsEmpty());
347     AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
348                         ErrorHandlingMode::MODULE_ERROR);
349     try_catch.ReThrow();
350     return;
351   }
352 }
353 
Evaluate(const FunctionCallbackInfo<Value> & args)354 void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) {
355   Environment* env = Environment::GetCurrent(args);
356   Isolate* isolate = env->isolate();
357   ModuleWrap* obj;
358   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
359   Local<Context> context = obj->context();
360   Local<Module> module = obj->module_.Get(isolate);
361 
362   ContextifyContext* contextify_context = obj->contextify_context_;
363   std::shared_ptr<MicrotaskQueue> microtask_queue;
364   if (contextify_context != nullptr)
365       microtask_queue = contextify_context->microtask_queue();
366 
367   // module.evaluate(timeout, breakOnSigint)
368   CHECK_EQ(args.Length(), 2);
369 
370   CHECK(args[0]->IsNumber());
371   int64_t timeout = args[0]->IntegerValue(env->context()).FromJust();
372 
373   CHECK(args[1]->IsBoolean());
374   bool break_on_sigint = args[1]->IsTrue();
375 
376   ShouldNotAbortOnUncaughtScope no_abort_scope(env);
377   TryCatchScope try_catch(env);
378   Isolate::SafeForTerminationScope safe_for_termination(env->isolate());
379 
380   bool timed_out = false;
381   bool received_signal = false;
382   MaybeLocal<Value> result;
383   auto run = [&]() {
384     MaybeLocal<Value> result = module->Evaluate(context);
385     if (!result.IsEmpty() && microtask_queue)
386       microtask_queue->PerformCheckpoint(isolate);
387     return result;
388   };
389   if (break_on_sigint && timeout != -1) {
390     Watchdog wd(isolate, timeout, &timed_out);
391     SigintWatchdog swd(isolate, &received_signal);
392     result = run();
393   } else if (break_on_sigint) {
394     SigintWatchdog swd(isolate, &received_signal);
395     result = run();
396   } else if (timeout != -1) {
397     Watchdog wd(isolate, timeout, &timed_out);
398     result = run();
399   } else {
400     result = run();
401   }
402 
403   if (result.IsEmpty()) {
404     CHECK(try_catch.HasCaught());
405   }
406 
407   // Convert the termination exception into a regular exception.
408   if (timed_out || received_signal) {
409     if (!env->is_main_thread() && env->is_stopping())
410       return;
411     env->isolate()->CancelTerminateExecution();
412     // It is possible that execution was terminated by another timeout in
413     // which this timeout is nested, so check whether one of the watchdogs
414     // from this invocation is responsible for termination.
415     if (timed_out) {
416       THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, timeout);
417     } else if (received_signal) {
418       THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(env);
419     }
420   }
421 
422   if (try_catch.HasCaught()) {
423     if (!try_catch.HasTerminated())
424       try_catch.ReThrow();
425     return;
426   }
427 
428   args.GetReturnValue().Set(result.ToLocalChecked());
429 }
430 
GetNamespace(const FunctionCallbackInfo<Value> & args)431 void ModuleWrap::GetNamespace(const FunctionCallbackInfo<Value>& args) {
432   Environment* env = Environment::GetCurrent(args);
433   Isolate* isolate = args.GetIsolate();
434   ModuleWrap* obj;
435   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
436 
437   Local<Module> module = obj->module_.Get(isolate);
438 
439   switch (module->GetStatus()) {
440     case v8::Module::Status::kUninstantiated:
441     case v8::Module::Status::kInstantiating:
442       return env->ThrowError(
443           "cannot get namespace, module has not been instantiated");
444     case v8::Module::Status::kInstantiated:
445     case v8::Module::Status::kEvaluating:
446     case v8::Module::Status::kEvaluated:
447     case v8::Module::Status::kErrored:
448       break;
449     default:
450       UNREACHABLE();
451   }
452 
453   Local<Value> result = module->GetModuleNamespace();
454   args.GetReturnValue().Set(result);
455 }
456 
GetStatus(const FunctionCallbackInfo<Value> & args)457 void ModuleWrap::GetStatus(const FunctionCallbackInfo<Value>& args) {
458   Isolate* isolate = args.GetIsolate();
459   ModuleWrap* obj;
460   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
461 
462   Local<Module> module = obj->module_.Get(isolate);
463 
464   args.GetReturnValue().Set(module->GetStatus());
465 }
466 
GetStaticDependencySpecifiers(const FunctionCallbackInfo<Value> & args)467 void ModuleWrap::GetStaticDependencySpecifiers(
468     const FunctionCallbackInfo<Value>& args) {
469   Environment* env = Environment::GetCurrent(args);
470   ModuleWrap* obj;
471   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
472 
473   Local<Module> module = obj->module_.Get(env->isolate());
474 
475   Local<FixedArray> module_requests = module->GetModuleRequests();
476   int count = module_requests->Length();
477 
478   MaybeStackBuffer<Local<Value>, 16> specifiers(count);
479 
480   for (int i = 0; i < count; i++) {
481     Local<ModuleRequest> module_request =
482       module_requests->Get(env->context(), i).As<ModuleRequest>();
483     specifiers[i] = module_request->GetSpecifier();
484   }
485 
486   args.GetReturnValue().Set(
487       Array::New(env->isolate(), specifiers.out(), count));
488 }
489 
GetError(const FunctionCallbackInfo<Value> & args)490 void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
491   Isolate* isolate = args.GetIsolate();
492   ModuleWrap* obj;
493   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
494 
495   Local<Module> module = obj->module_.Get(isolate);
496   args.GetReturnValue().Set(module->GetException());
497 }
498 
ResolveModuleCallback(Local<Context> context,Local<String> specifier,Local<FixedArray> import_assertions,Local<Module> referrer)499 MaybeLocal<Module> ModuleWrap::ResolveModuleCallback(
500     Local<Context> context,
501     Local<String> specifier,
502     Local<FixedArray> import_assertions,
503     Local<Module> referrer) {
504   Environment* env = Environment::GetCurrent(context);
505   if (env == nullptr) {
506     Isolate* isolate = context->GetIsolate();
507     THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
508     return MaybeLocal<Module>();
509   }
510 
511   Isolate* isolate = env->isolate();
512 
513   Utf8Value specifier_utf8(isolate, specifier);
514   std::string specifier_std(*specifier_utf8, specifier_utf8.length());
515 
516   ModuleWrap* dependent = GetFromModule(env, referrer);
517   if (dependent == nullptr) {
518     THROW_ERR_VM_MODULE_LINK_FAILURE(
519         env, "request for '%s' is from invalid module", specifier_std);
520     return MaybeLocal<Module>();
521   }
522 
523   if (dependent->resolve_cache_.count(specifier_std) != 1) {
524     THROW_ERR_VM_MODULE_LINK_FAILURE(
525         env, "request for '%s' is not in cache", specifier_std);
526     return MaybeLocal<Module>();
527   }
528 
529   Local<Promise> resolve_promise =
530       dependent->resolve_cache_[specifier_std].Get(isolate);
531 
532   if (resolve_promise->State() != Promise::kFulfilled) {
533     THROW_ERR_VM_MODULE_LINK_FAILURE(
534         env, "request for '%s' is not yet fulfilled", specifier_std);
535     return MaybeLocal<Module>();
536   }
537 
538   Local<Object> module_object = resolve_promise->Result().As<Object>();
539   if (module_object.IsEmpty() || !module_object->IsObject()) {
540     THROW_ERR_VM_MODULE_LINK_FAILURE(
541         env, "request for '%s' did not return an object", specifier_std);
542     return MaybeLocal<Module>();
543   }
544 
545   ModuleWrap* module;
546   ASSIGN_OR_RETURN_UNWRAP(&module, module_object, MaybeLocal<Module>());
547   return module->module_.Get(isolate);
548 }
549 
ImportModuleDynamically(Local<Context> context,Local<v8::Data> host_defined_options,Local<Value> resource_name,Local<String> specifier,Local<FixedArray> import_assertions)550 static MaybeLocal<Promise> ImportModuleDynamically(
551     Local<Context> context,
552     Local<v8::Data> host_defined_options,
553     Local<Value> resource_name,
554     Local<String> specifier,
555     Local<FixedArray> import_assertions) {
556   Isolate* isolate = context->GetIsolate();
557   Environment* env = Environment::GetCurrent(context);
558   if (env == nullptr) {
559     THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
560     return MaybeLocal<Promise>();
561   }
562 
563   EscapableHandleScope handle_scope(isolate);
564 
565   Local<Function> import_callback =
566     env->host_import_module_dynamically_callback();
567 
568   Local<FixedArray> options = host_defined_options.As<FixedArray>();
569   if (options->Length() != HostDefinedOptions::kLength) {
570     Local<Promise::Resolver> resolver;
571     if (!Promise::Resolver::New(context).ToLocal(&resolver)) return {};
572     resolver
573         ->Reject(context,
574                  v8::Exception::TypeError(FIXED_ONE_BYTE_STRING(
575                      context->GetIsolate(), "Invalid host defined options")))
576         .ToChecked();
577     return handle_scope.Escape(resolver->GetPromise());
578   }
579 
580   Local<Value> object;
581 
582   int type = options->Get(context, HostDefinedOptions::kType)
583                  .As<Number>()
584                  ->Int32Value(context)
585                  .ToChecked();
586   uint32_t id = options->Get(context, HostDefinedOptions::kID)
587                     .As<Number>()
588                     ->Uint32Value(context)
589                     .ToChecked();
590   if (type == ScriptType::kScript) {
591     contextify::ContextifyScript* wrap = env->id_to_script_map.find(id)->second;
592     object = wrap->object();
593   } else if (type == ScriptType::kModule) {
594     ModuleWrap* wrap = ModuleWrap::GetFromID(env, id);
595     object = wrap->object();
596   } else if (type == ScriptType::kFunction) {
597     auto it = env->id_to_function_map.find(id);
598     CHECK_NE(it, env->id_to_function_map.end());
599     object = it->second->object();
600   } else {
601     UNREACHABLE();
602   }
603 
604   Local<Object> assertions =
605     createImportAssertionContainer(env, isolate, import_assertions);
606 
607   Local<Value> import_args[] = {
608     object,
609     Local<Value>(specifier),
610     assertions,
611   };
612 
613   Local<Value> result;
614   if (import_callback->Call(
615         context,
616         Undefined(isolate),
617         arraysize(import_args),
618         import_args).ToLocal(&result)) {
619     CHECK(result->IsPromise());
620     return handle_scope.Escape(result.As<Promise>());
621   }
622 
623   return MaybeLocal<Promise>();
624 }
625 
SetImportModuleDynamicallyCallback(const FunctionCallbackInfo<Value> & args)626 void ModuleWrap::SetImportModuleDynamicallyCallback(
627     const FunctionCallbackInfo<Value>& args) {
628   Isolate* isolate = args.GetIsolate();
629   Environment* env = Environment::GetCurrent(args);
630   HandleScope handle_scope(isolate);
631 
632   CHECK_EQ(args.Length(), 1);
633   CHECK(args[0]->IsFunction());
634   Local<Function> import_callback = args[0].As<Function>();
635   env->set_host_import_module_dynamically_callback(import_callback);
636 
637   isolate->SetHostImportModuleDynamicallyCallback(ImportModuleDynamically);
638 }
639 
HostInitializeImportMetaObjectCallback(Local<Context> context,Local<Module> module,Local<Object> meta)640 void ModuleWrap::HostInitializeImportMetaObjectCallback(
641     Local<Context> context, Local<Module> module, Local<Object> meta) {
642   Environment* env = Environment::GetCurrent(context);
643   if (env == nullptr)
644     return;
645   ModuleWrap* module_wrap = GetFromModule(env, module);
646 
647   if (module_wrap == nullptr) {
648     return;
649   }
650 
651   Local<Object> wrap = module_wrap->object();
652   Local<Function> callback =
653       env->host_initialize_import_meta_object_callback();
654   Local<Value> args[] = { wrap, meta };
655   TryCatchScope try_catch(env);
656   USE(callback->Call(
657         context, Undefined(env->isolate()), arraysize(args), args));
658   if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
659     try_catch.ReThrow();
660   }
661 }
662 
SetInitializeImportMetaObjectCallback(const FunctionCallbackInfo<Value> & args)663 void ModuleWrap::SetInitializeImportMetaObjectCallback(
664     const FunctionCallbackInfo<Value>& args) {
665   Environment* env = Environment::GetCurrent(args);
666   Isolate* isolate = env->isolate();
667 
668   CHECK_EQ(args.Length(), 1);
669   CHECK(args[0]->IsFunction());
670   Local<Function> import_meta_callback = args[0].As<Function>();
671   env->set_host_initialize_import_meta_object_callback(import_meta_callback);
672 
673   isolate->SetHostInitializeImportMetaObjectCallback(
674       HostInitializeImportMetaObjectCallback);
675 }
676 
SyntheticModuleEvaluationStepsCallback(Local<Context> context,Local<Module> module)677 MaybeLocal<Value> ModuleWrap::SyntheticModuleEvaluationStepsCallback(
678     Local<Context> context, Local<Module> module) {
679   Environment* env = Environment::GetCurrent(context);
680   Isolate* isolate = env->isolate();
681 
682   ModuleWrap* obj = GetFromModule(env, module);
683 
684   TryCatchScope try_catch(env);
685   Local<Function> synthetic_evaluation_steps =
686       obj->object()->GetInternalField(kSyntheticEvaluationStepsSlot)
687           .As<Function>();
688   obj->object()->SetInternalField(
689       kSyntheticEvaluationStepsSlot, Undefined(isolate));
690   MaybeLocal<Value> ret = synthetic_evaluation_steps->Call(context,
691       obj->object(), 0, nullptr);
692   if (ret.IsEmpty()) {
693     CHECK(try_catch.HasCaught());
694   }
695   if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
696     CHECK(!try_catch.Message().IsEmpty());
697     CHECK(!try_catch.Exception().IsEmpty());
698     try_catch.ReThrow();
699     return MaybeLocal<Value>();
700   }
701 
702   Local<Promise::Resolver> resolver;
703   if (!Promise::Resolver::New(context).ToLocal(&resolver)) {
704     return MaybeLocal<Value>();
705   }
706 
707   resolver->Resolve(context, Undefined(isolate)).ToChecked();
708   return resolver->GetPromise();
709 }
710 
SetSyntheticExport(const FunctionCallbackInfo<Value> & args)711 void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo<Value>& args) {
712   Isolate* isolate = args.GetIsolate();
713   Local<Object> that = args.This();
714 
715   ModuleWrap* obj;
716   ASSIGN_OR_RETURN_UNWRAP(&obj, that);
717 
718   CHECK(obj->synthetic_);
719 
720   CHECK_EQ(args.Length(), 2);
721 
722   CHECK(args[0]->IsString());
723   Local<String> export_name = args[0].As<String>();
724 
725   Local<Value> export_value = args[1];
726 
727   Local<Module> module = obj->module_.Get(isolate);
728   USE(module->SetSyntheticModuleExport(isolate, export_name, export_value));
729 }
730 
CreateCachedData(const FunctionCallbackInfo<Value> & args)731 void ModuleWrap::CreateCachedData(const FunctionCallbackInfo<Value>& args) {
732   Isolate* isolate = args.GetIsolate();
733   Local<Object> that = args.This();
734 
735   ModuleWrap* obj;
736   ASSIGN_OR_RETURN_UNWRAP(&obj, that);
737 
738   CHECK(!obj->synthetic_);
739 
740   Local<Module> module = obj->module_.Get(isolate);
741 
742   CHECK_LT(module->GetStatus(), v8::Module::Status::kEvaluating);
743 
744   Local<UnboundModuleScript> unbound_module_script =
745       module->GetUnboundModuleScript();
746   std::unique_ptr<ScriptCompiler::CachedData> cached_data(
747       ScriptCompiler::CreateCodeCache(unbound_module_script));
748   Environment* env = Environment::GetCurrent(args);
749   if (!cached_data) {
750     args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked());
751   } else {
752     MaybeLocal<Object> buf =
753         Buffer::Copy(env,
754                      reinterpret_cast<const char*>(cached_data->data),
755                      cached_data->length);
756     args.GetReturnValue().Set(buf.ToLocalChecked());
757   }
758 }
759 
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)760 void ModuleWrap::Initialize(Local<Object> target,
761                             Local<Value> unused,
762                             Local<Context> context,
763                             void* priv) {
764   Environment* env = Environment::GetCurrent(context);
765   Isolate* isolate = env->isolate();
766 
767   Local<FunctionTemplate> tpl = NewFunctionTemplate(isolate, New);
768   tpl->InstanceTemplate()->SetInternalFieldCount(
769       ModuleWrap::kInternalFieldCount);
770   tpl->Inherit(BaseObject::GetConstructorTemplate(env));
771 
772   SetProtoMethod(isolate, tpl, "link", Link);
773   SetProtoMethod(isolate, tpl, "instantiate", Instantiate);
774   SetProtoMethod(isolate, tpl, "evaluate", Evaluate);
775   SetProtoMethod(isolate, tpl, "setExport", SetSyntheticExport);
776   SetProtoMethodNoSideEffect(
777       isolate, tpl, "createCachedData", CreateCachedData);
778   SetProtoMethodNoSideEffect(isolate, tpl, "getNamespace", GetNamespace);
779   SetProtoMethodNoSideEffect(isolate, tpl, "getStatus", GetStatus);
780   SetProtoMethodNoSideEffect(isolate, tpl, "getError", GetError);
781   SetProtoMethodNoSideEffect(isolate,
782                              tpl,
783                              "getStaticDependencySpecifiers",
784                              GetStaticDependencySpecifiers);
785 
786   SetConstructorFunction(context, target, "ModuleWrap", tpl);
787 
788   SetMethod(context,
789             target,
790             "setImportModuleDynamicallyCallback",
791             SetImportModuleDynamicallyCallback);
792   SetMethod(context,
793             target,
794             "setInitializeImportMetaObjectCallback",
795             SetInitializeImportMetaObjectCallback);
796 
797 #define V(name)                                                                \
798     target->Set(context,                                                       \
799       FIXED_ONE_BYTE_STRING(env->isolate(), #name),                            \
800       Integer::New(env->isolate(), Module::Status::name))                      \
801         .FromJust()
802     V(kUninstantiated);
803     V(kInstantiating);
804     V(kInstantiated);
805     V(kEvaluating);
806     V(kEvaluated);
807     V(kErrored);
808 #undef V
809 }
810 
811 }  // namespace loader
812 }  // namespace node
813 
814 NODE_BINDING_CONTEXT_AWARE_INTERNAL(module_wrap,
815                                     node::loader::ModuleWrap::Initialize)
816