@@ -133,12 +133,23 @@ ModuleWrap::ModuleWrap(Realm* realm,
133
133
object->SetInternalField (kSyntheticEvaluationStepsSlot ,
134
134
synthetic_evaluation_step);
135
135
object->SetInternalField (kContextObjectSlot , context_object);
136
+ object->SetInternalField (kLinkedRequestsSlot ,
137
+ v8::Undefined (realm->isolate ()));
136
138
137
139
if (!synthetic_evaluation_step->IsUndefined ()) {
138
140
synthetic_ = true ;
139
141
}
140
142
MakeWeak ();
141
143
module_.SetWeak ();
144
+
145
+ HandleScope scope (realm->isolate ());
146
+ Local<Context> context = realm->context ();
147
+ Local<FixedArray> requests = module ->GetModuleRequests ();
148
+ for (int i = 0 ; i < requests->Length (); i++) {
149
+ ModuleCacheKey module_cache_key = ModuleCacheKey::From (
150
+ context, requests->Get (context, i).As <ModuleRequest>());
151
+ resolve_cache_[module_cache_key] = i;
152
+ }
142
153
}
143
154
144
155
ModuleWrap::~ModuleWrap () {
@@ -159,6 +170,30 @@ Local<Context> ModuleWrap::context() const {
159
170
return obj.As <Object>()->GetCreationContextChecked ();
160
171
}
161
172
173
+ ModuleWrap* ModuleWrap::GetLinkedRequest (uint32_t index) {
174
+ DCHECK (IsLinked ());
175
+ Isolate* isolate = env ()->isolate ();
176
+ EscapableHandleScope scope (isolate);
177
+ Local<Data> linked_requests_data =
178
+ object ()->GetInternalField (kLinkedRequestsSlot );
179
+ DCHECK (linked_requests_data->IsValue () &&
180
+ linked_requests_data.As <Value>()->IsArray ());
181
+ Local<Array> requests = linked_requests_data.As <Array>();
182
+
183
+ CHECK_LT (index, requests->Length ());
184
+
185
+ Local<Value> module_value;
186
+ if (!requests->Get (context (), index).ToLocal (&module_value)) {
187
+ return nullptr ;
188
+ }
189
+ CHECK (module_value->IsObject ());
190
+ Local<Object> module_object = module_value.As <Object>();
191
+
192
+ ModuleWrap* module_wrap;
193
+ ASSIGN_OR_RETURN_UNWRAP (&module_wrap, module_object, nullptr );
194
+ return module_wrap;
195
+ }
196
+
162
197
ModuleWrap* ModuleWrap::GetFromModule (Environment* env,
163
198
Local<Module> module ) {
164
199
auto range = env->hash_to_module_map .equal_range (module ->GetIdentityHash ());
@@ -571,34 +606,28 @@ void ModuleWrap::GetModuleRequests(const FunctionCallbackInfo<Value>& args) {
571
606
void ModuleWrap::Link (const FunctionCallbackInfo<Value>& args) {
572
607
Realm* realm = Realm::GetCurrent (args);
573
608
Isolate* isolate = args.GetIsolate ();
574
- Local<Context> context = realm->context ();
575
609
576
610
ModuleWrap* dependent;
577
611
ASSIGN_OR_RETURN_UNWRAP (&dependent, args.This ());
578
612
579
613
CHECK_EQ (args.Length (), 1 );
580
614
615
+ Local<Data> linked_requests =
616
+ args.This ()->GetInternalField (kLinkedRequestsSlot );
617
+ if (linked_requests->IsValue () &&
618
+ !linked_requests.As <Value>()->IsUndefined ()) {
619
+ // If the module is already linked, we should not link it again.
620
+ THROW_ERR_VM_MODULE_LINK_FAILURE (realm->env (), " module is already linked" );
621
+ return ;
622
+ }
623
+
581
624
Local<FixedArray> requests =
582
625
dependent->module_ .Get (isolate)->GetModuleRequests ();
583
626
Local<Array> modules = args[0 ].As <Array>();
584
627
CHECK_EQ (modules->Length (), static_cast <uint32_t >(requests->Length ()));
585
628
586
- std::vector<Global<Value>> modules_buffer;
587
- if (FromV8Array (context, modules, &modules_buffer).IsNothing ()) {
588
- return ;
589
- }
590
-
591
- for (uint32_t i = 0 ; i < modules_buffer.size (); i++) {
592
- Local<Object> module_object = modules_buffer[i].Get (isolate).As <Object>();
593
-
594
- CHECK (
595
- realm->isolate_data ()->module_wrap_constructor_template ()->HasInstance (
596
- module_object));
597
-
598
- ModuleCacheKey module_cache_key = ModuleCacheKey::From (
599
- context, requests->Get (context, i).As <ModuleRequest>());
600
- dependent->resolve_cache_ [module_cache_key].Reset (isolate, module_object);
601
- }
629
+ args.This ()->SetInternalField (kLinkedRequestsSlot , modules);
630
+ dependent->linked_ = true ;
602
631
}
603
632
604
633
void ModuleWrap::Instantiate (const FunctionCallbackInfo<Value>& args) {
@@ -612,9 +641,6 @@ void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
612
641
USE (module ->InstantiateModule (
613
642
context, ResolveModuleCallback, ResolveSourceCallback));
614
643
615
- // clear resolve cache on instantiate
616
- obj->resolve_cache_ .clear ();
617
-
618
644
if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
619
645
CHECK (!try_catch.Message ().IsEmpty ());
620
646
CHECK (!try_catch.Exception ().IsEmpty ());
@@ -722,9 +748,6 @@ void ModuleWrap::InstantiateSync(const FunctionCallbackInfo<Value>& args) {
722
748
USE (module ->InstantiateModule (
723
749
context, ResolveModuleCallback, ResolveSourceCallback));
724
750
725
- // clear resolve cache on instantiate
726
- obj->resolve_cache_ .clear ();
727
-
728
751
if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
729
752
CHECK (!try_catch.Message ().IsEmpty ());
730
753
CHECK (!try_catch.Exception ().IsEmpty ());
@@ -965,48 +988,51 @@ void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
965
988
args.GetReturnValue ().Set (module ->GetException ());
966
989
}
967
990
991
+ // static
968
992
MaybeLocal<Module> ModuleWrap::ResolveModuleCallback (
969
993
Local<Context> context,
970
994
Local<String> specifier,
971
995
Local<FixedArray> import_attributes,
972
996
Local<Module> referrer) {
973
- Isolate* isolate = context->GetIsolate ();
974
- Environment* env = Environment::GetCurrent (context);
975
- if (env == nullptr ) {
976
- THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE (isolate);
977
- return MaybeLocal<Module>();
978
- }
979
-
980
- ModuleCacheKey cache_key =
981
- ModuleCacheKey::From (context, specifier, import_attributes);
982
-
983
- ModuleWrap* dependent = GetFromModule (env, referrer);
984
- if (dependent == nullptr ) {
985
- THROW_ERR_VM_MODULE_LINK_FAILURE (
986
- env, " request for '%s' is from invalid module" , cache_key.specifier );
987
- return MaybeLocal<Module>();
997
+ ModuleWrap* resolved_module;
998
+ if (!ResolveModule (context, specifier, import_attributes, referrer)
999
+ .To (&resolved_module)) {
1000
+ return {};
988
1001
}
1002
+ DCHECK_NOT_NULL (resolved_module);
1003
+ return resolved_module->module_ .Get (context->GetIsolate ());
1004
+ }
989
1005
990
- if (dependent->resolve_cache_ .count (cache_key) != 1 ) {
991
- THROW_ERR_VM_MODULE_LINK_FAILURE (
992
- env, " request for '%s' is not in cache" , cache_key.specifier );
993
- return MaybeLocal<Module>();
1006
+ // static
1007
+ MaybeLocal<Object> ModuleWrap::ResolveSourceCallback (
1008
+ Local<Context> context,
1009
+ Local<String> specifier,
1010
+ Local<FixedArray> import_attributes,
1011
+ Local<Module> referrer) {
1012
+ ModuleWrap* resolved_module;
1013
+ if (!ResolveModule (context, specifier, import_attributes, referrer)
1014
+ .To (&resolved_module)) {
1015
+ return {};
994
1016
}
1017
+ DCHECK_NOT_NULL (resolved_module);
995
1018
996
- Local<Object> module_object =
997
- dependent->resolve_cache_ [cache_key].Get (isolate);
998
- if (module_object.IsEmpty () || !module_object->IsObject ()) {
999
- THROW_ERR_VM_MODULE_LINK_FAILURE (
1000
- env, " request for '%s' did not return an object" , cache_key.specifier );
1001
- return MaybeLocal<Module>();
1019
+ Local<Value> module_source_object =
1020
+ resolved_module->object ()
1021
+ ->GetInternalField (ModuleWrap::kModuleSourceObjectSlot )
1022
+ .As <Value>();
1023
+ if (module_source_object->IsUndefined ()) {
1024
+ Local<String> url = resolved_module->object ()
1025
+ ->GetInternalField (ModuleWrap::kURLSlot )
1026
+ .As <String>();
1027
+ THROW_ERR_SOURCE_PHASE_NOT_DEFINED (context->GetIsolate (), url);
1028
+ return {};
1002
1029
}
1003
-
1004
- ModuleWrap* module ;
1005
- ASSIGN_OR_RETURN_UNWRAP (&module , module_object, MaybeLocal<Module>());
1006
- return module ->module_ .Get (isolate);
1030
+ CHECK (module_source_object->IsObject ());
1031
+ return module_source_object.As <Object>();
1007
1032
}
1008
1033
1009
- MaybeLocal<Object> ModuleWrap::ResolveSourceCallback (
1034
+ // static
1035
+ Maybe<ModuleWrap*> ModuleWrap::ResolveModule (
1010
1036
Local<Context> context,
1011
1037
Local<String> specifier,
1012
1038
Local<FixedArray> import_attributes,
@@ -1015,46 +1041,38 @@ MaybeLocal<Object> ModuleWrap::ResolveSourceCallback(
1015
1041
Environment* env = Environment::GetCurrent (context);
1016
1042
if (env == nullptr ) {
1017
1043
THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE (isolate);
1018
- return MaybeLocal<Object >();
1044
+ return Nothing<ModuleWrap* >();
1019
1045
}
1046
+ // Check that the referrer is not yet been instantiated.
1047
+ DCHECK (referrer->GetStatus () <= Module::kInstantiated );
1020
1048
1021
1049
ModuleCacheKey cache_key =
1022
1050
ModuleCacheKey::From (context, specifier, import_attributes);
1023
1051
1024
- ModuleWrap* dependent = GetFromModule (env, referrer);
1052
+ ModuleWrap* dependent = ModuleWrap:: GetFromModule (env, referrer);
1025
1053
if (dependent == nullptr ) {
1026
1054
THROW_ERR_VM_MODULE_LINK_FAILURE (
1027
1055
env, " request for '%s' is from invalid module" , cache_key.specifier );
1028
- return MaybeLocal<Object >();
1056
+ return Nothing<ModuleWrap* >();
1029
1057
}
1030
-
1031
- if (dependent->resolve_cache_ .count (cache_key) != 1 ) {
1058
+ if (!dependent->IsLinked ()) {
1032
1059
THROW_ERR_VM_MODULE_LINK_FAILURE (
1033
- env, " request for '%s' is not in cache" , cache_key.specifier );
1034
- return MaybeLocal<Object>();
1060
+ env,
1061
+ " request for '%s' is from a module not been linked" ,
1062
+ cache_key.specifier );
1063
+ return Nothing<ModuleWrap*>();
1035
1064
}
1036
1065
1037
- Local<Object> module_object =
1038
- dependent->resolve_cache_ [cache_key].Get (isolate);
1039
- if (module_object.IsEmpty () || !module_object->IsObject ()) {
1066
+ auto it = dependent->resolve_cache_ .find (cache_key);
1067
+ if (it == dependent->resolve_cache_ .end ()) {
1040
1068
THROW_ERR_VM_MODULE_LINK_FAILURE (
1041
- env, " request for '%s' did not return an object " , cache_key.specifier );
1042
- return MaybeLocal<Object >();
1069
+ env, " request for '%s' is not in cache " , cache_key.specifier );
1070
+ return Nothing<ModuleWrap* >();
1043
1071
}
1044
1072
1045
- ModuleWrap* module ;
1046
- ASSIGN_OR_RETURN_UNWRAP (&module , module_object, MaybeLocal<Object>());
1047
-
1048
- Local<Value> module_source_object =
1049
- module ->object ()->GetInternalField (kModuleSourceObjectSlot ).As <Value>();
1050
- if (module_source_object->IsUndefined ()) {
1051
- Local<String> url =
1052
- module ->object ()->GetInternalField (kURLSlot ).As <String>();
1053
- THROW_ERR_SOURCE_PHASE_NOT_DEFINED (isolate, url);
1054
- return MaybeLocal<Object>();
1055
- }
1056
- CHECK (module_source_object->IsObject ());
1057
- return module_source_object.As <Object>();
1073
+ ModuleWrap* module_wrap = dependent->GetLinkedRequest (it->second );
1074
+ CHECK_NOT_NULL (module_wrap);
1075
+ return Just (module_wrap);
1058
1076
}
1059
1077
1060
1078
static MaybeLocal<Promise> ImportModuleDynamicallyWithPhase (
0 commit comments