• 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_url.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 node::url::URL;
24 using node::url::URL_FLAGS_FAILED;
25 using v8::Array;
26 using v8::ArrayBufferView;
27 using v8::Context;
28 using v8::EscapableHandleScope;
29 using v8::Function;
30 using v8::FunctionCallbackInfo;
31 using v8::FunctionTemplate;
32 using v8::HandleScope;
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::Number;
41 using v8::Object;
42 using v8::PrimitiveArray;
43 using v8::Promise;
44 using v8::ScriptCompiler;
45 using v8::ScriptOrigin;
46 using v8::ScriptOrModule;
47 using v8::String;
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)52 ModuleWrap::ModuleWrap(Environment* env,
53                        Local<Object> object,
54                        Local<Module> module,
55                        Local<String> url)
56   : BaseObject(env, object),
57     module_(env->isolate(), module),
58     id_(env->get_next_module_id()) {
59   env->id_to_module_map.emplace(id_, this);
60 
61   Local<Value> undefined = Undefined(env->isolate());
62   object->SetInternalField(kURLSlot, url);
63   object->SetInternalField(kSyntheticEvaluationStepsSlot, undefined);
64   object->SetInternalField(kContextObjectSlot, undefined);
65 }
66 
~ModuleWrap()67 ModuleWrap::~ModuleWrap() {
68   HandleScope scope(env()->isolate());
69   Local<Module> module = module_.Get(env()->isolate());
70   env()->id_to_module_map.erase(id_);
71   auto range = env()->hash_to_module_map.equal_range(module->GetIdentityHash());
72   for (auto it = range.first; it != range.second; ++it) {
73     if (it->second == this) {
74       env()->hash_to_module_map.erase(it);
75       break;
76     }
77   }
78 }
79 
context() const80 Local<Context> ModuleWrap::context() const {
81   Local<Value> obj = object()->GetInternalField(kContextObjectSlot);
82   if (obj.IsEmpty()) return {};
83   return obj.As<Object>()->CreationContext();
84 }
85 
GetFromModule(Environment * env,Local<Module> module)86 ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
87                                       Local<Module> module) {
88   auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash());
89   for (auto it = range.first; it != range.second; ++it) {
90     if (it->second->module_ == module) {
91       return it->second;
92     }
93   }
94   return nullptr;
95 }
96 
GetFromID(Environment * env,uint32_t id)97 ModuleWrap* ModuleWrap::GetFromID(Environment* env, uint32_t id) {
98   auto module_wrap_it = env->id_to_module_map.find(id);
99   if (module_wrap_it == env->id_to_module_map.end()) {
100     return nullptr;
101   }
102   return module_wrap_it->second;
103 }
104 
105 // new ModuleWrap(url, context, source, lineOffset, columnOffset)
106 // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
New(const FunctionCallbackInfo<Value> & args)107 void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
108   CHECK(args.IsConstructCall());
109   CHECK_GE(args.Length(), 3);
110 
111   Environment* env = Environment::GetCurrent(args);
112   Isolate* isolate = env->isolate();
113 
114   Local<Object> that = args.This();
115 
116   CHECK(args[0]->IsString());
117   Local<String> url = args[0].As<String>();
118 
119   Local<Context> context;
120   ContextifyContext* contextify_context = nullptr;
121   if (args[1]->IsUndefined()) {
122     context = that->CreationContext();
123   } else {
124     CHECK(args[1]->IsObject());
125     contextify_context = ContextifyContext::ContextFromContextifiedSandbox(
126         env, args[1].As<Object>());
127     CHECK_NOT_NULL(contextify_context);
128     context = contextify_context->context();
129   }
130 
131   Local<Integer> line_offset;
132   Local<Integer> column_offset;
133 
134   bool synthetic = args[2]->IsArray();
135   if (synthetic) {
136     // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
137     CHECK(args[3]->IsFunction());
138   } else {
139     // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
140     CHECK(args[2]->IsString());
141     CHECK(args[3]->IsNumber());
142     line_offset = args[3].As<Integer>();
143     CHECK(args[4]->IsNumber());
144     column_offset = args[4].As<Integer>();
145   }
146 
147   Local<PrimitiveArray> host_defined_options =
148       PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
149   host_defined_options->Set(isolate, HostDefinedOptions::kType,
150                             Number::New(isolate, ScriptType::kModule));
151 
152   ShouldNotAbortOnUncaughtScope no_abort_scope(env);
153   TryCatchScope try_catch(env);
154 
155   Local<Module> module;
156 
157   {
158     Context::Scope context_scope(context);
159     if (synthetic) {
160       CHECK(args[2]->IsArray());
161       Local<Array> export_names_arr = args[2].As<Array>();
162 
163       uint32_t len = export_names_arr->Length();
164       std::vector<Local<String>> export_names(len);
165       for (uint32_t i = 0; i < len; i++) {
166         Local<Value> export_name_val =
167             export_names_arr->Get(context, i).ToLocalChecked();
168         CHECK(export_name_val->IsString());
169         export_names[i] = export_name_val.As<String>();
170       }
171 
172       module = Module::CreateSyntheticModule(isolate, url, export_names,
173         SyntheticModuleEvaluationStepsCallback);
174     } else {
175       ScriptCompiler::CachedData* cached_data = nullptr;
176       if (!args[5]->IsUndefined()) {
177         CHECK(args[5]->IsArrayBufferView());
178         Local<ArrayBufferView> cached_data_buf = args[5].As<ArrayBufferView>();
179         uint8_t* data = static_cast<uint8_t*>(
180             cached_data_buf->Buffer()->GetBackingStore()->Data());
181         cached_data =
182             new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(),
183                                            cached_data_buf->ByteLength());
184       }
185 
186       Local<String> source_text = args[2].As<String>();
187       ScriptOrigin origin(url,
188                           line_offset,                      // line offset
189                           column_offset,                    // column offset
190                           True(isolate),                    // is cross origin
191                           Local<Integer>(),                 // script id
192                           Local<Value>(),                   // source map URL
193                           False(isolate),                   // is opaque (?)
194                           False(isolate),                   // is WASM
195                           True(isolate),                    // 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 CreationContext() 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 
Link(const FunctionCallbackInfo<Value> & args)252 void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
253   Environment* env = Environment::GetCurrent(args);
254   Isolate* isolate = args.GetIsolate();
255 
256   CHECK_EQ(args.Length(), 1);
257   CHECK(args[0]->IsFunction());
258 
259   Local<Object> that = args.This();
260 
261   ModuleWrap* obj;
262   ASSIGN_OR_RETURN_UNWRAP(&obj, that);
263 
264   if (obj->linked_)
265     return;
266   obj->linked_ = true;
267 
268   Local<Function> resolver_arg = args[0].As<Function>();
269 
270   Local<Context> mod_context = obj->context();
271   Local<Module> module = obj->module_.Get(isolate);
272 
273   const int module_requests_length = module->GetModuleRequestsLength();
274   MaybeStackBuffer<Local<Value>, 16> promises(module_requests_length);
275 
276   // call the dependency resolve callbacks
277   for (int i = 0; i < module_requests_length; i++) {
278     Local<String> specifier = module->GetModuleRequest(i);
279     Utf8Value specifier_utf8(env->isolate(), specifier);
280     std::string specifier_std(*specifier_utf8, specifier_utf8.length());
281 
282     Local<Value> argv[] = {
283       specifier
284     };
285 
286     MaybeLocal<Value> maybe_resolve_return_value =
287         resolver_arg->Call(mod_context, that, arraysize(argv), argv);
288     if (maybe_resolve_return_value.IsEmpty()) {
289       return;
290     }
291     Local<Value> resolve_return_value =
292         maybe_resolve_return_value.ToLocalChecked();
293     if (!resolve_return_value->IsPromise()) {
294       THROW_ERR_VM_MODULE_LINK_FAILURE(
295           env, "request for '%s' did not return promise", specifier_std);
296       return;
297     }
298     Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
299     obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_promise);
300 
301     promises[i] = resolve_promise;
302   }
303 
304   args.GetReturnValue().Set(
305       Array::New(isolate, promises.out(), promises.length()));
306 }
307 
Instantiate(const FunctionCallbackInfo<Value> & args)308 void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
309   Environment* env = Environment::GetCurrent(args);
310   Isolate* isolate = args.GetIsolate();
311   ModuleWrap* obj;
312   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
313   Local<Context> context = obj->context();
314   Local<Module> module = obj->module_.Get(isolate);
315   TryCatchScope try_catch(env);
316   USE(module->InstantiateModule(context, ResolveCallback));
317 
318   // clear resolve cache on instantiate
319   obj->resolve_cache_.clear();
320 
321   if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
322     CHECK(!try_catch.Message().IsEmpty());
323     CHECK(!try_catch.Exception().IsEmpty());
324     AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
325                         ErrorHandlingMode::MODULE_ERROR);
326     try_catch.ReThrow();
327     return;
328   }
329 }
330 
Evaluate(const FunctionCallbackInfo<Value> & args)331 void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) {
332   Environment* env = Environment::GetCurrent(args);
333   Isolate* isolate = env->isolate();
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 
339   ContextifyContext* contextify_context = obj->contextify_context_;
340   std::shared_ptr<MicrotaskQueue> microtask_queue;
341   if (contextify_context != nullptr)
342       microtask_queue = contextify_context->microtask_queue();
343 
344   // module.evaluate(timeout, breakOnSigint)
345   CHECK_EQ(args.Length(), 2);
346 
347   CHECK(args[0]->IsNumber());
348   int64_t timeout = args[0]->IntegerValue(env->context()).FromJust();
349 
350   CHECK(args[1]->IsBoolean());
351   bool break_on_sigint = args[1]->IsTrue();
352 
353   ShouldNotAbortOnUncaughtScope no_abort_scope(env);
354   TryCatchScope try_catch(env);
355   Isolate::SafeForTerminationScope safe_for_termination(env->isolate());
356 
357   bool timed_out = false;
358   bool received_signal = false;
359   MaybeLocal<Value> result;
360   auto run = [&]() {
361     MaybeLocal<Value> result = module->Evaluate(context);
362     if (!result.IsEmpty() && microtask_queue)
363       microtask_queue->PerformCheckpoint(isolate);
364     return result;
365   };
366   if (break_on_sigint && timeout != -1) {
367     Watchdog wd(isolate, timeout, &timed_out);
368     SigintWatchdog swd(isolate, &received_signal);
369     result = run();
370   } else if (break_on_sigint) {
371     SigintWatchdog swd(isolate, &received_signal);
372     result = run();
373   } else if (timeout != -1) {
374     Watchdog wd(isolate, timeout, &timed_out);
375     result = run();
376   } else {
377     result = run();
378   }
379 
380   if (result.IsEmpty()) {
381     CHECK(try_catch.HasCaught());
382   }
383 
384   // Convert the termination exception into a regular exception.
385   if (timed_out || received_signal) {
386     if (!env->is_main_thread() && env->is_stopping())
387       return;
388     env->isolate()->CancelTerminateExecution();
389     // It is possible that execution was terminated by another timeout in
390     // which this timeout is nested, so check whether one of the watchdogs
391     // from this invocation is responsible for termination.
392     if (timed_out) {
393       THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, timeout);
394     } else if (received_signal) {
395       THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(env);
396     }
397   }
398 
399   if (try_catch.HasCaught()) {
400     if (!try_catch.HasTerminated())
401       try_catch.ReThrow();
402     return;
403   }
404 
405   // If TLA is enabled, `result` is the evaluation's promise.
406   // Otherwise, `result` is the last evaluated value of the module,
407   // which could be a promise, which would result in it being incorrectly
408   // unwrapped when the higher level code awaits the evaluation.
409   if (env->isolate_data()->options()->experimental_top_level_await) {
410     args.GetReturnValue().Set(result.ToLocalChecked());
411   }
412 }
413 
GetNamespace(const FunctionCallbackInfo<Value> & args)414 void ModuleWrap::GetNamespace(const FunctionCallbackInfo<Value>& args) {
415   Environment* env = Environment::GetCurrent(args);
416   Isolate* isolate = args.GetIsolate();
417   ModuleWrap* obj;
418   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
419 
420   Local<Module> module = obj->module_.Get(isolate);
421 
422   switch (module->GetStatus()) {
423     case v8::Module::Status::kUninstantiated:
424     case v8::Module::Status::kInstantiating:
425       return env->ThrowError(
426           "cannot get namespace, module has not been instantiated");
427     case v8::Module::Status::kInstantiated:
428     case v8::Module::Status::kEvaluating:
429     case v8::Module::Status::kEvaluated:
430     case v8::Module::Status::kErrored:
431       break;
432     default:
433       UNREACHABLE();
434   }
435 
436   Local<Value> result = module->GetModuleNamespace();
437   args.GetReturnValue().Set(result);
438 }
439 
GetStatus(const FunctionCallbackInfo<Value> & args)440 void ModuleWrap::GetStatus(const FunctionCallbackInfo<Value>& args) {
441   Isolate* isolate = args.GetIsolate();
442   ModuleWrap* obj;
443   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
444 
445   Local<Module> module = obj->module_.Get(isolate);
446 
447   args.GetReturnValue().Set(module->GetStatus());
448 }
449 
GetStaticDependencySpecifiers(const FunctionCallbackInfo<Value> & args)450 void ModuleWrap::GetStaticDependencySpecifiers(
451     const FunctionCallbackInfo<Value>& args) {
452   Environment* env = Environment::GetCurrent(args);
453   ModuleWrap* obj;
454   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
455 
456   Local<Module> module = obj->module_.Get(env->isolate());
457 
458   int count = module->GetModuleRequestsLength();
459 
460   MaybeStackBuffer<Local<Value>, 16> specifiers(count);
461 
462   for (int i = 0; i < count; i++)
463     specifiers[i] = module->GetModuleRequest(i);
464 
465   args.GetReturnValue().Set(
466       Array::New(env->isolate(), specifiers.out(), count));
467 }
468 
GetError(const FunctionCallbackInfo<Value> & args)469 void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
470   Isolate* isolate = args.GetIsolate();
471   ModuleWrap* obj;
472   ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
473 
474   Local<Module> module = obj->module_.Get(isolate);
475   args.GetReturnValue().Set(module->GetException());
476 }
477 
ResolveCallback(Local<Context> context,Local<String> specifier,Local<Module> referrer)478 MaybeLocal<Module> ModuleWrap::ResolveCallback(Local<Context> context,
479                                                Local<String> specifier,
480                                                Local<Module> referrer) {
481   Environment* env = Environment::GetCurrent(context);
482   if (env == nullptr) {
483     Isolate* isolate = context->GetIsolate();
484     THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
485     return MaybeLocal<Module>();
486   }
487 
488   Isolate* isolate = env->isolate();
489 
490   Utf8Value specifier_utf8(isolate, specifier);
491   std::string specifier_std(*specifier_utf8, specifier_utf8.length());
492 
493   ModuleWrap* dependent = GetFromModule(env, referrer);
494   if (dependent == nullptr) {
495     THROW_ERR_VM_MODULE_LINK_FAILURE(
496         env, "request for '%s' is from invalid module", specifier_std);
497     return MaybeLocal<Module>();
498   }
499 
500   if (dependent->resolve_cache_.count(specifier_std) != 1) {
501     THROW_ERR_VM_MODULE_LINK_FAILURE(
502         env, "request for '%s' is not in cache", specifier_std);
503     return MaybeLocal<Module>();
504   }
505 
506   Local<Promise> resolve_promise =
507       dependent->resolve_cache_[specifier_std].Get(isolate);
508 
509   if (resolve_promise->State() != Promise::kFulfilled) {
510     THROW_ERR_VM_MODULE_LINK_FAILURE(
511         env, "request for '%s' is not yet fulfilled", specifier_std);
512     return MaybeLocal<Module>();
513   }
514 
515   Local<Object> module_object = resolve_promise->Result().As<Object>();
516   if (module_object.IsEmpty() || !module_object->IsObject()) {
517     THROW_ERR_VM_MODULE_LINK_FAILURE(
518         env, "request for '%s' did not return an object", specifier_std);
519     return MaybeLocal<Module>();
520   }
521 
522   ModuleWrap* module;
523   ASSIGN_OR_RETURN_UNWRAP(&module, module_object, MaybeLocal<Module>());
524   return module->module_.Get(isolate);
525 }
526 
ImportModuleDynamically(Local<Context> context,Local<ScriptOrModule> referrer,Local<String> specifier)527 static MaybeLocal<Promise> ImportModuleDynamically(
528     Local<Context> context,
529     Local<ScriptOrModule> referrer,
530     Local<String> specifier) {
531   Isolate* iso = context->GetIsolate();
532   Environment* env = Environment::GetCurrent(context);
533   if (env == nullptr) {
534     THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(iso);
535     return MaybeLocal<Promise>();
536   }
537 
538   EscapableHandleScope handle_scope(iso);
539 
540   Local<Function> import_callback =
541     env->host_import_module_dynamically_callback();
542 
543   Local<PrimitiveArray> options = referrer->GetHostDefinedOptions();
544   if (options->Length() != HostDefinedOptions::kLength) {
545     Local<Promise::Resolver> resolver;
546     if (!Promise::Resolver::New(context).ToLocal(&resolver)) return {};
547     resolver
548         ->Reject(context,
549                  v8::Exception::TypeError(FIXED_ONE_BYTE_STRING(
550                      context->GetIsolate(), "Invalid host defined options")))
551         .ToChecked();
552     return handle_scope.Escape(resolver->GetPromise());
553   }
554 
555   Local<Value> object;
556 
557   int type = options->Get(iso, HostDefinedOptions::kType)
558                  .As<Number>()
559                  ->Int32Value(context)
560                  .ToChecked();
561   uint32_t id = options->Get(iso, HostDefinedOptions::kID)
562                     .As<Number>()
563                     ->Uint32Value(context)
564                     .ToChecked();
565   if (type == ScriptType::kScript) {
566     contextify::ContextifyScript* wrap = env->id_to_script_map.find(id)->second;
567     object = wrap->object();
568   } else if (type == ScriptType::kModule) {
569     ModuleWrap* wrap = ModuleWrap::GetFromID(env, id);
570     object = wrap->object();
571   } else if (type == ScriptType::kFunction) {
572     auto it = env->id_to_function_map.find(id);
573     CHECK_NE(it, env->id_to_function_map.end());
574     object = it->second->object();
575   } else {
576     UNREACHABLE();
577   }
578 
579   Local<Value> import_args[] = {
580     object,
581     Local<Value>(specifier),
582   };
583 
584   Local<Value> result;
585   if (import_callback->Call(
586         context,
587         Undefined(iso),
588         arraysize(import_args),
589         import_args).ToLocal(&result)) {
590     CHECK(result->IsPromise());
591     return handle_scope.Escape(result.As<Promise>());
592   }
593 
594   return MaybeLocal<Promise>();
595 }
596 
SetImportModuleDynamicallyCallback(const FunctionCallbackInfo<Value> & args)597 void ModuleWrap::SetImportModuleDynamicallyCallback(
598     const FunctionCallbackInfo<Value>& args) {
599   Isolate* iso = args.GetIsolate();
600   Environment* env = Environment::GetCurrent(args);
601   HandleScope handle_scope(iso);
602 
603   CHECK_EQ(args.Length(), 1);
604   CHECK(args[0]->IsFunction());
605   Local<Function> import_callback = args[0].As<Function>();
606   env->set_host_import_module_dynamically_callback(import_callback);
607 
608   iso->SetHostImportModuleDynamicallyCallback(ImportModuleDynamically);
609 }
610 
HostInitializeImportMetaObjectCallback(Local<Context> context,Local<Module> module,Local<Object> meta)611 void ModuleWrap::HostInitializeImportMetaObjectCallback(
612     Local<Context> context, Local<Module> module, Local<Object> meta) {
613   Environment* env = Environment::GetCurrent(context);
614   if (env == nullptr)
615     return;
616   ModuleWrap* module_wrap = GetFromModule(env, module);
617 
618   if (module_wrap == nullptr) {
619     return;
620   }
621 
622   Local<Object> wrap = module_wrap->object();
623   Local<Function> callback =
624       env->host_initialize_import_meta_object_callback();
625   Local<Value> args[] = { wrap, meta };
626   TryCatchScope try_catch(env);
627   USE(callback->Call(
628         context, Undefined(env->isolate()), arraysize(args), args));
629   if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
630     try_catch.ReThrow();
631   }
632 }
633 
SetInitializeImportMetaObjectCallback(const FunctionCallbackInfo<Value> & args)634 void ModuleWrap::SetInitializeImportMetaObjectCallback(
635     const FunctionCallbackInfo<Value>& args) {
636   Environment* env = Environment::GetCurrent(args);
637   Isolate* isolate = env->isolate();
638 
639   CHECK_EQ(args.Length(), 1);
640   CHECK(args[0]->IsFunction());
641   Local<Function> import_meta_callback = args[0].As<Function>();
642   env->set_host_initialize_import_meta_object_callback(import_meta_callback);
643 
644   isolate->SetHostInitializeImportMetaObjectCallback(
645       HostInitializeImportMetaObjectCallback);
646 }
647 
SyntheticModuleEvaluationStepsCallback(Local<Context> context,Local<Module> module)648 MaybeLocal<Value> ModuleWrap::SyntheticModuleEvaluationStepsCallback(
649     Local<Context> context, Local<Module> module) {
650   Environment* env = Environment::GetCurrent(context);
651   Isolate* isolate = env->isolate();
652 
653   ModuleWrap* obj = GetFromModule(env, module);
654 
655   TryCatchScope try_catch(env);
656   Local<Function> synthetic_evaluation_steps =
657       obj->object()->GetInternalField(kSyntheticEvaluationStepsSlot)
658           .As<Function>();
659   obj->object()->SetInternalField(
660       kSyntheticEvaluationStepsSlot, Undefined(isolate));
661   MaybeLocal<Value> ret = synthetic_evaluation_steps->Call(context,
662       obj->object(), 0, nullptr);
663   if (ret.IsEmpty()) {
664     CHECK(try_catch.HasCaught());
665   }
666   if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
667     CHECK(!try_catch.Message().IsEmpty());
668     CHECK(!try_catch.Exception().IsEmpty());
669     try_catch.ReThrow();
670     return MaybeLocal<Value>();
671   }
672 
673   Local<Promise::Resolver> resolver;
674   if (!Promise::Resolver::New(context).ToLocal(&resolver)) {
675     return MaybeLocal<Value>();
676   }
677 
678   resolver->Resolve(context, Undefined(isolate)).ToChecked();
679   return resolver->GetPromise();
680 }
681 
SetSyntheticExport(const FunctionCallbackInfo<Value> & args)682 void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo<Value>& args) {
683   Isolate* isolate = args.GetIsolate();
684   Local<Object> that = args.This();
685 
686   ModuleWrap* obj;
687   ASSIGN_OR_RETURN_UNWRAP(&obj, that);
688 
689   CHECK(obj->synthetic_);
690 
691   CHECK_EQ(args.Length(), 2);
692 
693   CHECK(args[0]->IsString());
694   Local<String> export_name = args[0].As<String>();
695 
696   Local<Value> export_value = args[1];
697 
698   Local<Module> module = obj->module_.Get(isolate);
699   USE(module->SetSyntheticModuleExport(isolate, export_name, export_value));
700 }
701 
CreateCachedData(const FunctionCallbackInfo<Value> & args)702 void ModuleWrap::CreateCachedData(const FunctionCallbackInfo<Value>& args) {
703   Isolate* isolate = args.GetIsolate();
704   Local<Object> that = args.This();
705 
706   ModuleWrap* obj;
707   ASSIGN_OR_RETURN_UNWRAP(&obj, that);
708 
709   CHECK(!obj->synthetic_);
710 
711   Local<Module> module = obj->module_.Get(isolate);
712 
713   CHECK_LT(module->GetStatus(), v8::Module::Status::kEvaluating);
714 
715   Local<UnboundModuleScript> unbound_module_script =
716       module->GetUnboundModuleScript();
717   std::unique_ptr<ScriptCompiler::CachedData> cached_data(
718       ScriptCompiler::CreateCodeCache(unbound_module_script));
719   Environment* env = Environment::GetCurrent(args);
720   if (!cached_data) {
721     args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked());
722   } else {
723     MaybeLocal<Object> buf =
724         Buffer::Copy(env,
725                      reinterpret_cast<const char*>(cached_data->data),
726                      cached_data->length);
727     args.GetReturnValue().Set(buf.ToLocalChecked());
728   }
729 }
730 
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)731 void ModuleWrap::Initialize(Local<Object> target,
732                             Local<Value> unused,
733                             Local<Context> context,
734                             void* priv) {
735   Environment* env = Environment::GetCurrent(context);
736 
737   Local<FunctionTemplate> tpl = env->NewFunctionTemplate(New);
738   tpl->InstanceTemplate()->SetInternalFieldCount(
739       ModuleWrap::kInternalFieldCount);
740   tpl->Inherit(BaseObject::GetConstructorTemplate(env));
741 
742   env->SetProtoMethod(tpl, "link", Link);
743   env->SetProtoMethod(tpl, "instantiate", Instantiate);
744   env->SetProtoMethod(tpl, "evaluate", Evaluate);
745   env->SetProtoMethod(tpl, "setExport", SetSyntheticExport);
746   env->SetProtoMethodNoSideEffect(tpl, "createCachedData", CreateCachedData);
747   env->SetProtoMethodNoSideEffect(tpl, "getNamespace", GetNamespace);
748   env->SetProtoMethodNoSideEffect(tpl, "getStatus", GetStatus);
749   env->SetProtoMethodNoSideEffect(tpl, "getError", GetError);
750   env->SetProtoMethodNoSideEffect(tpl, "getStaticDependencySpecifiers",
751                                   GetStaticDependencySpecifiers);
752 
753   env->SetConstructorFunction(target, "ModuleWrap", tpl);
754 
755   env->SetMethod(target,
756                  "setImportModuleDynamicallyCallback",
757                  SetImportModuleDynamicallyCallback);
758   env->SetMethod(target,
759                  "setInitializeImportMetaObjectCallback",
760                  SetInitializeImportMetaObjectCallback);
761 
762 #define V(name)                                                                \
763     target->Set(context,                                                       \
764       FIXED_ONE_BYTE_STRING(env->isolate(), #name),                            \
765       Integer::New(env->isolate(), Module::Status::name))                      \
766         .FromJust()
767     V(kUninstantiated);
768     V(kInstantiating);
769     V(kInstantiated);
770     V(kEvaluating);
771     V(kEvaluated);
772     V(kErrored);
773 #undef V
774 }
775 
776 }  // namespace loader
777 }  // namespace node
778 
779 NODE_MODULE_CONTEXT_AWARE_INTERNAL(module_wrap,
780                                    node::loader::ModuleWrap::Initialize)
781