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