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