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