• 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_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