@@ -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,66 @@ using v8::UnboundModuleScript;
6362using v8::Undefined;
6463using v8::Value;
6564
65+ ModulePhase to_phase_constant (ModuleImportPhase phase) {
66+ switch (phase) {
67+ case ModuleImportPhase::kEvaluation :
68+ return kEvaluationPhase ;
69+ case ModuleImportPhase::kSource :
70+ return kSourcePhase ;
71+ }
72+ UNREACHABLE ();
73+ }
74+
75+ void ModuleRequest::MemoryInfo (MemoryTracker* tracker) const {
76+ tracker->TrackField (" specifier" , specifier);
77+ tracker->TrackField (" import_attributes" , import_attributes);
78+ tracker->TrackField (" phase" , static_cast <int >(phase));
79+ }
80+
81+ template <int elements_per_attribute>
82+ ModuleRequest ModuleRequest::From (Local<Context> context,
83+ Local<String> specifier,
84+ Local<FixedArray> import_attributes,
85+ ModulePhase phase) {
86+ CHECK_EQ (import_attributes->Length () % elements_per_attribute, 0 );
87+ Isolate* isolate = context->GetIsolate ();
88+ std::size_t h1 = specifier->GetIdentityHash ();
89+ size_t num_attributes = import_attributes->Length () / elements_per_attribute;
90+ std::vector<std::pair<std::string, std::string>> attributes;
91+ attributes.reserve (num_attributes);
92+
93+ std::size_t h2 = 0 ;
94+
95+ for (int i = 0 ; i < import_attributes->Length ();
96+ i += elements_per_attribute) {
97+ Local<String> v8_key = import_attributes->Get (context, i).As <String>();
98+ Local<String> v8_value =
99+ import_attributes->Get (context, i + 1 ).As <String>();
100+ Utf8Value key_utf8 (isolate, v8_key);
101+ Utf8Value value_utf8 (isolate, v8_value);
102+
103+ attributes.emplace_back (key_utf8.ToString (), value_utf8.ToString ());
104+ h2 ^= v8_key->GetIdentityHash ();
105+ h2 ^= v8_value->GetIdentityHash ();
106+ }
107+
108+ std::size_t h3 = std::hash<int >{}(static_cast <int >(phase));
109+ // Combine the hashes using a simple XOR and bit shift to reduce
110+ // collisions.
111+ std::size_t hash = h1 ^ (h2 << 1 ) ^ (h3 << 2 );
112+
113+ Utf8Value utf8_specifier (isolate, specifier);
114+ return ModuleRequest{utf8_specifier.ToString (), attributes, phase, hash};
115+ }
116+
117+ ModuleRequest ModuleRequest::From (Local<Context> context,
118+ Local<v8::ModuleRequest> v8_request) {
119+ return From (context,
120+ v8_request->GetSpecifier (),
121+ v8_request->GetImportAttributes (),
122+ to_phase_constant (v8_request->GetPhase ()));
123+ }
124+
66125ModuleWrap::ModuleWrap (Realm* realm,
67126 Local<Object> object,
68127 Local<Module> module ,
@@ -422,16 +481,6 @@ MaybeLocal<Module> ModuleWrap::CompileSourceTextModule(
422481 return scope.Escape (module );
423482}
424483
425- ModulePhase to_phase_constant (ModuleImportPhase phase) {
426- switch (phase) {
427- case ModuleImportPhase::kEvaluation :
428- return kEvaluationPhase ;
429- case ModuleImportPhase::kSource :
430- return kSourcePhase ;
431- }
432- UNREACHABLE ();
433- }
434-
435484static Local<Object> createImportAttributesContainer (
436485 Realm* realm,
437486 Isolate* isolate,
@@ -462,8 +511,8 @@ static Local<Array> createModuleRequestsContainer(
462511 LocalVector<Value> requests (isolate, raw_requests->Length ());
463512
464513 for (int i = 0 ; i < raw_requests->Length (); i++) {
465- Local<ModuleRequest> module_request =
466- raw_requests->Get (realm->context (), i).As <ModuleRequest>();
514+ Local<v8:: ModuleRequest> module_request =
515+ raw_requests->Get (realm->context (), i).As <v8:: ModuleRequest>();
467516
468517 Local<String> specifier = module_request->GetSpecifier ();
469518
@@ -509,7 +558,7 @@ void ModuleWrap::GetModuleRequests(const FunctionCallbackInfo<Value>& args) {
509558 realm, isolate, module ->GetModuleRequests ()));
510559}
511560
512- // moduleWrap.link(specifiers, moduleWraps)
561+ // moduleWrap.link(moduleWraps)
513562void ModuleWrap::Link (const FunctionCallbackInfo<Value>& args) {
514563 Realm* realm = Realm::GetCurrent (args);
515564 Isolate* isolate = args.GetIsolate ();
@@ -518,33 +567,28 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
518567 ModuleWrap* dependent;
519568 ASSIGN_OR_RETURN_UNWRAP (&dependent, args.This ());
520569
521- CHECK_EQ (args.Length (), 2 );
570+ CHECK_EQ (args.Length (), 1 );
522571
523- Local<Array> specifiers = args[0 ].As <Array>();
524- Local<Array> modules = args[1 ].As <Array>();
525- CHECK_EQ (specifiers->Length (), modules->Length ());
572+ Local<FixedArray> requests =
573+ dependent->module_ .Get (isolate)->GetModuleRequests ();
574+ Local<Array> modules = args[0 ].As <Array>();
575+ CHECK_EQ (modules->Length (), static_cast <uint32_t >(requests->Length ()));
526576
527- std::vector<Global<Value>> specifiers_buffer;
528- if (FromV8Array (context, specifiers, &specifiers_buffer).IsNothing ()) {
529- return ;
530- }
531577 std::vector<Global<Value>> modules_buffer;
532578 if (FromV8Array (context, modules, &modules_buffer).IsNothing ()) {
533579 return ;
534580 }
535581
536- for (uint32_t i = 0 ; i < specifiers->Length (); i++) {
537- Local<String> specifier_str =
538- specifiers_buffer[i].Get (isolate).As <String>();
582+ for (uint32_t i = 0 ; i < modules_buffer.size (); i++) {
539583 Local<Object> module_object = modules_buffer[i].Get (isolate).As <Object>();
540584
541585 CHECK (
542586 realm->isolate_data ()->module_wrap_constructor_template ()->HasInstance (
543587 module_object));
544588
545- Utf8Value specifier (isolate, specifier_str);
546- dependent-> resolve_cache_ [specifier. ToString ()]. Reset (isolate,
547- module_object);
589+ ModuleRequest module_request = ModuleRequest::From (
590+ context, requests-> Get (context, i). As <v8::ModuleRequest>());
591+ dependent-> resolve_cache_ [module_request]. Reset (isolate, module_object);
548592 }
549593}
550594
@@ -924,27 +968,28 @@ MaybeLocal<Module> ModuleWrap::ResolveModuleCallback(
924968 return MaybeLocal<Module>();
925969 }
926970
927- Utf8Value specifier_utf8 (isolate, specifier);
928- std::string specifier_std (*specifier_utf8, specifier_utf8.length ());
971+ // ResolveModuleCallback for kEvaluationPhase only.
972+ const ModulePhase phase = ModulePhase::kEvaluationPhase ;
973+ ModuleRequest request =
974+ ModuleRequest::From (context, specifier, import_attributes, phase);
929975
930976 ModuleWrap* dependent = GetFromModule (env, referrer);
931977 if (dependent == nullptr ) {
932978 THROW_ERR_VM_MODULE_LINK_FAILURE (
933- env, " request for '%s' is from invalid module" , specifier_std );
979+ env, " request for '%s' is from invalid module" , request. specifier );
934980 return MaybeLocal<Module>();
935981 }
936982
937- if (dependent->resolve_cache_ .count (specifier_std ) != 1 ) {
983+ if (dependent->resolve_cache_ .count (request ) != 1 ) {
938984 THROW_ERR_VM_MODULE_LINK_FAILURE (
939- env, " request for '%s' is not in cache" , specifier_std );
985+ env, " request for '%s' is not in cache" , request. specifier );
940986 return MaybeLocal<Module>();
941987 }
942988
943- Local<Object> module_object =
944- dependent->resolve_cache_ [specifier_std].Get (isolate);
989+ Local<Object> module_object = dependent->resolve_cache_ [request].Get (isolate);
945990 if (module_object.IsEmpty () || !module_object->IsObject ()) {
946991 THROW_ERR_VM_MODULE_LINK_FAILURE (
947- env, " request for '%s' did not return an object" , specifier_std );
992+ env, " request for '%s' did not return an object" , request. specifier );
948993 return MaybeLocal<Module>();
949994 }
950995
@@ -965,27 +1010,28 @@ MaybeLocal<Object> ModuleWrap::ResolveSourceCallback(
9651010 return MaybeLocal<Object>();
9661011 }
9671012
968- Utf8Value specifier_utf8 (isolate, specifier);
969- std::string specifier_std (*specifier_utf8, specifier_utf8.length ());
1013+ // ResolveSourceCallback for kSourcePhase only.
1014+ const ModulePhase phase = ModulePhase::kSourcePhase ;
1015+ ModuleRequest request =
1016+ ModuleRequest::From (context, specifier, import_attributes, phase);
9701017
9711018 ModuleWrap* dependent = GetFromModule (env, referrer);
9721019 if (dependent == nullptr ) {
9731020 THROW_ERR_VM_MODULE_LINK_FAILURE (
974- env, " request for '%s' is from invalid module" , specifier_std );
1021+ env, " request for '%s' is from invalid module" , request. specifier );
9751022 return MaybeLocal<Object>();
9761023 }
9771024
978- if (dependent->resolve_cache_ .count (specifier_std ) != 1 ) {
1025+ if (dependent->resolve_cache_ .count (request ) != 1 ) {
9791026 THROW_ERR_VM_MODULE_LINK_FAILURE (
980- env, " request for '%s' is not in cache" , specifier_std );
1027+ env, " request for '%s' is not in cache" , request. specifier );
9811028 return MaybeLocal<Object>();
9821029 }
9831030
984- Local<Object> module_object =
985- dependent->resolve_cache_ [specifier_std].Get (isolate);
1031+ Local<Object> module_object = dependent->resolve_cache_ [request].Get (isolate);
9861032 if (module_object.IsEmpty () || !module_object->IsObject ()) {
9871033 THROW_ERR_VM_MODULE_LINK_FAILURE (
988- env, " request for '%s' did not return an object" , specifier_std );
1034+ env, " request for '%s' did not return an object" , request. specifier );
9891035 return MaybeLocal<Object>();
9901036 }
9911037
0 commit comments