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