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