@@ -63,6 +63,51 @@ using v8::UnboundModuleScript;
63
63
using v8::Undefined;
64
64
using v8::Value;
65
65
66
+ void ModuleCacheKey::MemoryInfo (MemoryTracker* tracker) const {
67
+ tracker->TrackField (" specifier" , specifier);
68
+ tracker->TrackField (" import_attributes" , import_attributes);
69
+ }
70
+
71
+ template <int elements_per_attribute>
72
+ ModuleCacheKey ModuleCacheKey::From (Local<Context> context,
73
+ Local<String> specifier,
74
+ Local<FixedArray> import_attributes) {
75
+ CHECK_EQ (import_attributes->Length () % elements_per_attribute, 0 );
76
+ Isolate* isolate = context->GetIsolate ();
77
+ std::size_t h1 = specifier->GetIdentityHash ();
78
+ size_t num_attributes = import_attributes->Length () / elements_per_attribute;
79
+ ImportAttributeVector attributes;
80
+ attributes.reserve (num_attributes);
81
+
82
+ std::size_t h2 = 0 ;
83
+
84
+ for (int i = 0 ; i < import_attributes->Length ();
85
+ i += elements_per_attribute) {
86
+ Local<String> v8_key = import_attributes->Get (context, i).As <String>();
87
+ Local<String> v8_value =
88
+ import_attributes->Get (context, i + 1 ).As <String>();
89
+ Utf8Value key_utf8 (isolate, v8_key);
90
+ Utf8Value value_utf8 (isolate, v8_value);
91
+
92
+ attributes.emplace_back (key_utf8.ToString (), value_utf8.ToString ());
93
+ h2 ^= v8_key->GetIdentityHash ();
94
+ h2 ^= v8_value->GetIdentityHash ();
95
+ }
96
+
97
+ // Combine the hashes using a simple XOR and bit shift to reduce
98
+ // collisions. Note that the hash does not guarantee uniqueness.
99
+ std::size_t hash = h1 ^ (h2 << 1 );
100
+
101
+ Utf8Value utf8_specifier (isolate, specifier);
102
+ return ModuleCacheKey{utf8_specifier.ToString (), attributes, hash};
103
+ }
104
+
105
+ ModuleCacheKey ModuleCacheKey::From (Local<Context> context,
106
+ Local<ModuleRequest> v8_request) {
107
+ return From (
108
+ context, v8_request->GetSpecifier (), v8_request->GetImportAttributes ());
109
+ }
110
+
66
111
ModuleWrap::ModuleWrap (Realm* realm,
67
112
Local<Object> object,
68
113
Local<Module> module ,
@@ -509,7 +554,7 @@ void ModuleWrap::GetModuleRequests(const FunctionCallbackInfo<Value>& args) {
509
554
realm, isolate, module ->GetModuleRequests ()));
510
555
}
511
556
512
- // moduleWrap.link(specifiers, moduleWraps)
557
+ // moduleWrap.link(moduleWraps)
513
558
void ModuleWrap::Link (const FunctionCallbackInfo<Value>& args) {
514
559
Realm* realm = Realm::GetCurrent (args);
515
560
Isolate* isolate = args.GetIsolate ();
@@ -518,33 +563,28 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
518
563
ModuleWrap* dependent;
519
564
ASSIGN_OR_RETURN_UNWRAP (&dependent, args.This ());
520
565
521
- CHECK_EQ (args.Length (), 2 );
566
+ CHECK_EQ (args.Length (), 1 );
522
567
523
- Local<Array> specifiers = args[0 ].As <Array>();
524
- Local<Array> modules = args[1 ].As <Array>();
525
- CHECK_EQ (specifiers->Length (), modules->Length ());
568
+ Local<FixedArray> requests =
569
+ dependent->module_ .Get (isolate)->GetModuleRequests ();
570
+ Local<Array> modules = args[0 ].As <Array>();
571
+ CHECK_EQ (modules->Length (), static_cast <uint32_t >(requests->Length ()));
526
572
527
- std::vector<Global<Value>> specifiers_buffer;
528
- if (FromV8Array (context, specifiers, &specifiers_buffer).IsNothing ()) {
529
- return ;
530
- }
531
573
std::vector<Global<Value>> modules_buffer;
532
574
if (FromV8Array (context, modules, &modules_buffer).IsNothing ()) {
533
575
return ;
534
576
}
535
577
536
- for (uint32_t i = 0 ; i < specifiers->Length (); i++) {
537
- Local<String> specifier_str =
538
- specifiers_buffer[i].Get (isolate).As <String>();
578
+ for (uint32_t i = 0 ; i < modules_buffer.size (); i++) {
539
579
Local<Object> module_object = modules_buffer[i].Get (isolate).As <Object>();
540
580
541
581
CHECK (
542
582
realm->isolate_data ()->module_wrap_constructor_template ()->HasInstance (
543
583
module_object));
544
584
545
- Utf8Value specifier (isolate, specifier_str);
546
- dependent-> resolve_cache_ [specifier. ToString ()]. Reset (isolate,
547
- module_object);
585
+ ModuleCacheKey module_cache_key = ModuleCacheKey::From (
586
+ context, requests-> Get (context, i). As <ModuleRequest>());
587
+ dependent-> resolve_cache_ [module_cache_key]. Reset (isolate, module_object);
548
588
}
549
589
}
550
590
@@ -924,27 +964,27 @@ MaybeLocal<Module> ModuleWrap::ResolveModuleCallback(
924
964
return MaybeLocal<Module>();
925
965
}
926
966
927
- Utf8Value specifier_utf8 (isolate, specifier);
928
- std::string specifier_std (*specifier_utf8, specifier_utf8. length () );
967
+ ModuleCacheKey cache_key =
968
+ ModuleCacheKey::From (context, specifier, import_attributes );
929
969
930
970
ModuleWrap* dependent = GetFromModule (env, referrer);
931
971
if (dependent == nullptr ) {
932
972
THROW_ERR_VM_MODULE_LINK_FAILURE (
933
- env, " request for '%s' is from invalid module" , specifier_std );
973
+ env, " request for '%s' is from invalid module" , cache_key. specifier );
934
974
return MaybeLocal<Module>();
935
975
}
936
976
937
- if (dependent->resolve_cache_ .count (specifier_std ) != 1 ) {
977
+ if (dependent->resolve_cache_ .count (cache_key ) != 1 ) {
938
978
THROW_ERR_VM_MODULE_LINK_FAILURE (
939
- env, " request for '%s' is not in cache" , specifier_std );
979
+ env, " request for '%s' is not in cache" , cache_key. specifier );
940
980
return MaybeLocal<Module>();
941
981
}
942
982
943
983
Local<Object> module_object =
944
- dependent->resolve_cache_ [specifier_std ].Get (isolate);
984
+ dependent->resolve_cache_ [cache_key ].Get (isolate);
945
985
if (module_object.IsEmpty () || !module_object->IsObject ()) {
946
986
THROW_ERR_VM_MODULE_LINK_FAILURE (
947
- env, " request for '%s' did not return an object" , specifier_std );
987
+ env, " request for '%s' did not return an object" , cache_key. specifier );
948
988
return MaybeLocal<Module>();
949
989
}
950
990
@@ -965,27 +1005,27 @@ MaybeLocal<Object> ModuleWrap::ResolveSourceCallback(
965
1005
return MaybeLocal<Object>();
966
1006
}
967
1007
968
- Utf8Value specifier_utf8 (isolate, specifier);
969
- std::string specifier_std (*specifier_utf8, specifier_utf8. length () );
1008
+ ModuleCacheKey cache_key =
1009
+ ModuleCacheKey::From (context, specifier, import_attributes );
970
1010
971
1011
ModuleWrap* dependent = GetFromModule (env, referrer);
972
1012
if (dependent == nullptr ) {
973
1013
THROW_ERR_VM_MODULE_LINK_FAILURE (
974
- env, " request for '%s' is from invalid module" , specifier_std );
1014
+ env, " request for '%s' is from invalid module" , cache_key. specifier );
975
1015
return MaybeLocal<Object>();
976
1016
}
977
1017
978
- if (dependent->resolve_cache_ .count (specifier_std ) != 1 ) {
1018
+ if (dependent->resolve_cache_ .count (cache_key ) != 1 ) {
979
1019
THROW_ERR_VM_MODULE_LINK_FAILURE (
980
- env, " request for '%s' is not in cache" , specifier_std );
1020
+ env, " request for '%s' is not in cache" , cache_key. specifier );
981
1021
return MaybeLocal<Object>();
982
1022
}
983
1023
984
1024
Local<Object> module_object =
985
- dependent->resolve_cache_ [specifier_std ].Get (isolate);
1025
+ dependent->resolve_cache_ [cache_key ].Get (isolate);
986
1026
if (module_object.IsEmpty () || !module_object->IsObject ()) {
987
1027
THROW_ERR_VM_MODULE_LINK_FAILURE (
988
- env, " request for '%s' did not return an object" , specifier_std );
1028
+ env, " request for '%s' did not return an object" , cache_key. specifier );
989
1029
return MaybeLocal<Object>();
990
1030
}
991
1031
0 commit comments