@@ -46,7 +46,6 @@ using v8::Message;
4646using v8::MicrotaskQueue;
4747using v8::Module;
4848using v8::ModuleImportPhase;
49- using v8::ModuleRequest;
5049using v8::Name;
5150using v8::Nothing;
5251using v8::Null;
@@ -63,6 +62,12 @@ using v8::UnboundModuleScript;
6362using v8::Undefined;
6463using v8::Value;
6564
65+ void ModuleRequest::MemoryInfo (MemoryTracker* tracker) const {
66+ tracker->TrackField (" specifier" , specifier);
67+ tracker->TrackField (" import_attributes" , import_attributes);
68+ tracker->TrackField (" phase" , static_cast <int >(phase));
69+ }
70+
6671ModuleWrap::ModuleWrap (Realm* realm,
6772 Local<Object> object,
6873 Local<Module> module ,
@@ -455,15 +460,36 @@ static Local<Object> createImportAttributesContainer(
455460 return attributes;
456461}
457462
463+ static std::vector<std::pair<std::string, std::string>>
464+ createImportAttributesPairs (Local<Context> context,
465+ Isolate* isolate,
466+ Local<FixedArray> raw_attributes,
467+ const int elements_per_attribute) {
468+ CHECK_EQ (raw_attributes->Length () % elements_per_attribute, 0 );
469+ size_t num_attributes = raw_attributes->Length () / elements_per_attribute;
470+ std::vector<std::pair<std::string, std::string>> attributes;
471+ attributes.reserve (num_attributes);
472+
473+ for (int i = 0 ; i < raw_attributes->Length (); i += elements_per_attribute) {
474+ Utf8Value key_utf8 (isolate, raw_attributes->Get (context, i).As <String>());
475+ Utf8Value value_utf8 (isolate,
476+ raw_attributes->Get (context, i + 1 ).As <String>());
477+
478+ attributes.emplace_back (key_utf8.ToString (), value_utf8.ToString ());
479+ }
480+
481+ return attributes;
482+ }
483+
458484static Local<Array> createModuleRequestsContainer (
459485 Realm* realm, Isolate* isolate, Local<FixedArray> raw_requests) {
460486 EscapableHandleScope scope (isolate);
461487 Local<Context> context = realm->context ();
462488 LocalVector<Value> requests (isolate, raw_requests->Length ());
463489
464490 for (int i = 0 ; i < raw_requests->Length (); i++) {
465- Local<ModuleRequest> module_request =
466- raw_requests->Get (realm->context (), i).As <ModuleRequest>();
491+ Local<v8:: ModuleRequest> module_request =
492+ raw_requests->Get (realm->context (), i).As <v8:: ModuleRequest>();
467493
468494 Local<String> specifier = module_request->GetSpecifier ();
469495
@@ -496,6 +522,32 @@ static Local<Array> createModuleRequestsContainer(
496522 return scope.Escape (Array::New (isolate, requests.data (), requests.size ()));
497523}
498524
525+ static std::vector<ModuleRequest> V8ModuleRequestsToPrimitive (
526+ Local<Context> context, Local<FixedArray> v8_requests) {
527+ Isolate* isolate = context->GetIsolate ();
528+ std::vector<ModuleRequest> requests;
529+ requests.reserve (v8_requests->Length ());
530+
531+ for (int i = 0 ; i < v8_requests->Length (); i++) {
532+ Local<v8::ModuleRequest> v8_module_request =
533+ v8_requests->Get (context, i).As <v8::ModuleRequest>();
534+
535+ Utf8Value specifier_utf8 (isolate, v8_module_request->GetSpecifier ());
536+ Local<FixedArray> v8_attributes = v8_module_request->GetImportAttributes ();
537+
538+ auto import_attributes =
539+ createImportAttributesPairs (context, isolate, v8_attributes, 3 );
540+ auto phase = to_phase_constant (v8_module_request->GetPhase ());
541+ requests.emplace_back (ModuleRequest{
542+ specifier_utf8.ToString (),
543+ import_attributes,
544+ phase,
545+ });
546+ }
547+
548+ return requests;
549+ }
550+
499551void ModuleWrap::GetModuleRequests (const FunctionCallbackInfo<Value>& args) {
500552 Realm* realm = Realm::GetCurrent (args);
501553 Isolate* isolate = args.GetIsolate ();
@@ -509,7 +561,7 @@ void ModuleWrap::GetModuleRequests(const FunctionCallbackInfo<Value>& args) {
509561 realm, isolate, module ->GetModuleRequests ()));
510562}
511563
512- // moduleWrap.link(specifiers, moduleWraps)
564+ // moduleWrap.link(moduleWraps)
513565void ModuleWrap::Link (const FunctionCallbackInfo<Value>& args) {
514566 Realm* realm = Realm::GetCurrent (args);
515567 Isolate* isolate = args.GetIsolate ();
@@ -518,33 +570,29 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
518570 ModuleWrap* dependent;
519571 ASSIGN_OR_RETURN_UNWRAP (&dependent, args.This ());
520572
521- CHECK_EQ (args.Length (), 2 );
573+ CHECK_EQ (args.Length (), 1 );
522574
523- Local<Array> specifiers = args[0 ].As <Array>();
524- Local<Array> modules = args[1 ].As <Array>();
525- CHECK_EQ (specifiers->Length (), modules->Length ());
575+ Local<FixedArray> requests =
576+ dependent->module_ .Get (isolate)->GetModuleRequests ();
577+ Local<Array> modules = args[0 ].As <Array>();
578+ CHECK_EQ (modules->Length (), static_cast <uint32_t >(requests->Length ()));
526579
527- std::vector<Global<Value>> specifiers_buffer;
528- if (FromV8Array (context, specifiers, &specifiers_buffer).IsNothing ()) {
529- return ;
530- }
531580 std::vector<Global<Value>> modules_buffer;
532581 if (FromV8Array (context, modules, &modules_buffer).IsNothing ()) {
533582 return ;
534583 }
535584
536- for (uint32_t i = 0 ; i < specifiers->Length (); i++) {
537- Local<String> specifier_str =
538- specifiers_buffer[i].Get (isolate).As <String>();
585+ std::vector<ModuleRequest> module_requests =
586+ V8ModuleRequestsToPrimitive (context, requests);
587+
588+ for (uint32_t i = 0 ; i < module_requests.size (); i++) {
539589 Local<Object> module_object = modules_buffer[i].Get (isolate).As <Object>();
540590
541591 CHECK (
542592 realm->isolate_data ()->module_wrap_constructor_template ()->HasInstance (
543593 module_object));
544594
545- Utf8Value specifier (isolate, specifier_str);
546- dependent->resolve_cache_ [specifier.ToString ()].Reset (isolate,
547- module_object);
595+ dependent->resolve_cache_ [module_requests[i]].Reset (isolate, module_object);
548596 }
549597}
550598
@@ -934,14 +982,18 @@ MaybeLocal<Module> ModuleWrap::ResolveModuleCallback(
934982 return MaybeLocal<Module>();
935983 }
936984
937- if (dependent->resolve_cache_ .count (specifier_std) != 1 ) {
985+ ModuleRequest request{
986+ specifier_std,
987+ createImportAttributesPairs (context, isolate, import_attributes, 3 ),
988+ kEvaluationPhase // ResolveModuleCallback for kEvaluationPhase only
989+ };
990+ if (dependent->resolve_cache_ .count (request) != 1 ) {
938991 THROW_ERR_VM_MODULE_LINK_FAILURE (
939992 env, " request for '%s' is not in cache" , specifier_std);
940993 return MaybeLocal<Module>();
941994 }
942995
943- Local<Object> module_object =
944- dependent->resolve_cache_ [specifier_std].Get (isolate);
996+ Local<Object> module_object = dependent->resolve_cache_ [request].Get (isolate);
945997 if (module_object.IsEmpty () || !module_object->IsObject ()) {
946998 THROW_ERR_VM_MODULE_LINK_FAILURE (
947999 env, " request for '%s' did not return an object" , specifier_std);
@@ -975,14 +1027,18 @@ MaybeLocal<Object> ModuleWrap::ResolveSourceCallback(
9751027 return MaybeLocal<Object>();
9761028 }
9771029
978- if (dependent->resolve_cache_ .count (specifier_std) != 1 ) {
1030+ ModuleRequest request{
1031+ specifier_std,
1032+ createImportAttributesPairs (context, isolate, import_attributes, 3 ),
1033+ kSourcePhase // ResolveSourceCallback for kSourcePhase only
1034+ };
1035+ if (dependent->resolve_cache_ .count (request) != 1 ) {
9791036 THROW_ERR_VM_MODULE_LINK_FAILURE (
9801037 env, " request for '%s' is not in cache" , specifier_std);
9811038 return MaybeLocal<Object>();
9821039 }
9831040
984- Local<Object> module_object =
985- dependent->resolve_cache_ [specifier_std].Get (isolate);
1041+ Local<Object> module_object = dependent->resolve_cache_ [request].Get (isolate);
9861042 if (module_object.IsEmpty () || !module_object->IsObject ()) {
9871043 THROW_ERR_VM_MODULE_LINK_FAILURE (
9881044 env, " request for '%s' did not return an object" , specifier_std);
0 commit comments