xref: /third_party/node/src/module_wrap.cc (revision 1cb0ef41)
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
17namespace node {
18namespace loader {
19
20using errors::TryCatchScope;
21
22using node::contextify::ContextifyContext;
23using v8::Array;
24using v8::ArrayBufferView;
25using v8::Context;
26using v8::EscapableHandleScope;
27using v8::FixedArray;
28using v8::Function;
29using v8::FunctionCallbackInfo;
30using v8::FunctionTemplate;
31using v8::HandleScope;
32using v8::Int32;
33using v8::Integer;
34using v8::IntegrityLevel;
35using v8::Isolate;
36using v8::Local;
37using v8::MaybeLocal;
38using v8::MicrotaskQueue;
39using v8::Module;
40using v8::ModuleRequest;
41using v8::Object;
42using v8::PrimitiveArray;
43using v8::Promise;
44using v8::ScriptCompiler;
45using v8::ScriptOrigin;
46using v8::String;
47using v8::Symbol;
48using v8::UnboundModuleScript;
49using v8::Undefined;
50using v8::Value;
51
52ModuleWrap::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->SetInternalField(kModuleSlot, module.As<Value>());
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
74ModuleWrap::~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
85Local<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
93ModuleWrap* 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)
106void 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
252static 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
271void 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
335void 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
358void 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
435void 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
461void 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
471void 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
494void 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
503MaybeLocal<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
554static 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
611void 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
625void 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
654void 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
668MaybeLocal<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
704void 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
724void 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
753void 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
804void 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
824NODE_BINDING_CONTEXT_AWARE_INTERNAL(module_wrap,
825                                    node::loader::ModuleWrap::Initialize)
826NODE_BINDING_EXTERNAL_REFERENCE(
827    module_wrap, node::loader::ModuleWrap::RegisterExternalReferences)
828