@@ -115,6 +115,140 @@ ModuleCacheKey ModuleCacheKey::From(Local<Context> context,
115115      context, v8_request->GetSpecifier (), v8_request->GetImportAttributes ());
116116}
117117
118+ //  static
119+ thread_local  ModuleInstantiationContext*
120+     ModuleInstantiationContext::thread_local_context_;
121+ 
122+ //  static
123+ MaybeLocal<Module> ModuleInstantiationContext::ResolveModuleCallback (
124+     Local<Context> context,
125+     Local<String> specifier,
126+     Local<FixedArray> import_attributes,
127+     Local<Module> referrer) {
128+   CHECK_NOT_NULL (thread_local_context_);
129+   ModuleWrap* resolved_module;
130+   if  (!thread_local_context_
131+            ->ResolveModule (context, specifier, import_attributes, referrer)
132+            .To (&resolved_module)) {
133+     return  {};
134+   }
135+   DCHECK_NOT_NULL (resolved_module);
136+   return  resolved_module->module ();
137+ }
138+ 
139+ //  static
140+ MaybeLocal<Object> ModuleInstantiationContext::ResolveSourceCallback (
141+     Local<Context> context,
142+     Local<String> specifier,
143+     Local<FixedArray> import_attributes,
144+     Local<Module> referrer) {
145+   CHECK_NOT_NULL (thread_local_context_);
146+   ModuleWrap* resolved_module;
147+   if  (!thread_local_context_
148+            ->ResolveModule (context, specifier, import_attributes, referrer)
149+            .To (&resolved_module)) {
150+     return  {};
151+   }
152+   DCHECK_NOT_NULL (resolved_module);
153+ 
154+   Local<Value> module_source_object =
155+       resolved_module->object ()
156+           ->GetInternalField (ModuleWrap::kModuleSourceObjectSlot )
157+           .As <Value>();
158+   if  (module_source_object->IsUndefined ()) {
159+     Local<String> url = resolved_module->object ()
160+                             ->GetInternalField (ModuleWrap::kURLSlot )
161+                             .As <String>();
162+     THROW_ERR_SOURCE_PHASE_NOT_DEFINED (context->GetIsolate (), url);
163+     return  {};
164+   }
165+   CHECK (module_source_object->IsObject ());
166+   return  module_source_object.As <Object>();
167+ }
168+ 
169+ ModuleInstantiationContext::ModuleInstantiationContext () {
170+   //  Only one ModuleInstantiationContext can exist per thread at a time.
171+   CHECK_NULL (thread_local_context_);
172+   thread_local_context_ = this ;
173+ }
174+ 
175+ ModuleInstantiationContext::~ModuleInstantiationContext () {
176+   //  Ensure that the thread-local context is this context.
177+   CHECK_EQ (thread_local_context_, this );
178+   thread_local_context_ = nullptr ;
179+ }
180+ 
181+ Maybe<ModuleWrap*> ModuleInstantiationContext::ResolveModule (
182+     Local<Context> context,
183+     Local<String> specifier,
184+     Local<FixedArray> import_attributes,
185+     Local<Module> referrer) {
186+   Isolate* isolate = context->GetIsolate ();
187+   Environment* env = Environment::GetCurrent (context);
188+   if  (env == nullptr ) {
189+     THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE (isolate);
190+     return  Nothing<ModuleWrap*>();
191+   }
192+   //  Check that the referrer is not yet been instantiated.
193+   DCHECK (referrer->GetStatus () <= Module::kInstantiated );
194+ 
195+   ModuleCacheKey cache_key =
196+       ModuleCacheKey::From (context, specifier, import_attributes);
197+ 
198+   ModuleWrap* dependent = ModuleWrap::GetFromModule (env, referrer);
199+   if  (dependent == nullptr ) {
200+     THROW_ERR_VM_MODULE_LINK_FAILURE (
201+         env, " request for '%s' is from invalid module" specifier );
202+     return  Nothing<ModuleWrap*>();
203+   }
204+   if  (!dependent->IsLinked ()) {
205+     THROW_ERR_VM_MODULE_LINK_FAILURE (
206+         env,
207+         " request for '%s' is from a module not been linked" 
208+         cache_key.specifier );
209+     return  Nothing<ModuleWrap*>();
210+   }
211+ 
212+   ResolveCache& resolve_cache = GetModuleResolveCache (env, dependent);
213+   if  (resolve_cache.count (cache_key) != 1 ) {
214+     THROW_ERR_VM_MODULE_LINK_FAILURE (
215+         env, " request for '%s' is not in cache" specifier );
216+     return  Nothing<ModuleWrap*>();
217+   }
218+ 
219+   ModuleWrap* module_wrap =
220+       dependent->GetLinkedRequest (resolve_cache[cache_key]);
221+   CHECK_NOT_NULL (module_wrap);
222+   return  Just (module_wrap);
223+ }
224+ 
225+ ModuleInstantiationContext::ResolveCache&
226+ ModuleInstantiationContext::GetModuleResolveCache (Environment* env,
227+                                                   ModuleWrap* module_wrap) {
228+   CHECK (module_wrap->IsLinked ());
229+ 
230+   auto  it = module_instance_graph_.find (module_wrap);
231+   if  (it != module_instance_graph_.end ()) {
232+     return  it->second ;
233+   }
234+ 
235+   Isolate* isolate = env->isolate ();
236+   HandleScope scope (isolate);
237+   Local<Context> context = env->context ();
238+ 
239+   Local<FixedArray> requests = module_wrap->module ()->GetModuleRequests ();
240+ 
241+   ResolveCache& resolve_cache = module_instance_graph_[module_wrap];
242+ 
243+   for  (int  i = 0 ; i < requests->Length (); i++) {
244+     ModuleCacheKey module_cache_key = ModuleCacheKey::From (
245+         context, requests->Get (context, i).As <ModuleRequest>());
246+     resolve_cache[module_cache_key] = i;
247+   }
248+ 
249+   return  resolve_cache;
250+ }
251+ 
118252ModuleWrap::ModuleWrap (Realm* realm,
119253                       Local<Object> object,
120254                       Local<Module> module ,
@@ -133,6 +267,8 @@ ModuleWrap::ModuleWrap(Realm* realm,
133267  object->SetInternalField (kSyntheticEvaluationStepsSlot ,
134268                           synthetic_evaluation_step);
135269  object->SetInternalField (kContextObjectSlot , context_object);
270+   object->SetInternalField (kLinkedRequestsSlot ,
271+                            v8::Undefined (realm->isolate ()));
136272
137273  if  (!synthetic_evaluation_step->IsUndefined ()) {
138274    synthetic_ = true ;
@@ -159,6 +295,34 @@ Local<Context> ModuleWrap::context() const {
159295  return  obj.As <Object>()->GetCreationContextChecked ();
160296}
161297
298+ Local<Module> ModuleWrap::module () {
299+   return  module_.Get (env ()->isolate ());
300+ }
301+ 
302+ ModuleWrap* ModuleWrap::GetLinkedRequest (uint32_t  index) {
303+   DCHECK (IsLinked ());
304+   Isolate* isolate = env ()->isolate ();
305+   EscapableHandleScope scope (isolate);
306+   Local<Data> linked_requests_data =
307+       object ()->GetInternalField (kLinkedRequestsSlot );
308+   DCHECK (linked_requests_data->IsValue () &&
309+          linked_requests_data.As <Value>()->IsArray ());
310+   Local<Array> requests = linked_requests_data.As <Array>();
311+ 
312+   CHECK_LT (index, requests->Length ());
313+ 
314+   Local<Value> module_value;
315+   if  (!requests->Get (context (), index).ToLocal (&module_value)) {
316+     return  nullptr ;
317+   }
318+   CHECK (module_value->IsObject ());
319+   Local<Object> module_object = module_value.As <Object>();
320+ 
321+   ModuleWrap* module_wrap;
322+   ASSIGN_OR_RETURN_UNWRAP (&module_wrap, module_object, nullptr );
323+   return  module_wrap;
324+ }
325+ 
162326ModuleWrap* ModuleWrap::GetFromModule (Environment* env,
163327                                      Local<Module> module ) {
164328  auto  range = env->hash_to_module_map .equal_range (module ->GetIdentityHash ());
@@ -571,34 +735,28 @@ void ModuleWrap::GetModuleRequests(const FunctionCallbackInfo<Value>& args) {
571735void  ModuleWrap::Link (const  FunctionCallbackInfo<Value>& args) {
572736  Realm* realm = Realm::GetCurrent (args);
573737  Isolate* isolate = args.GetIsolate ();
574-   Local<Context> context = realm->context ();
575738
576739  ModuleWrap* dependent;
577740  ASSIGN_OR_RETURN_UNWRAP (&dependent, args.This ());
578741
579742  CHECK_EQ (args.Length (), 1 );
580743
744+   Local<Data> linked_requests =
745+       args.This ()->GetInternalField (kLinkedRequestsSlot );
746+   if  (linked_requests->IsValue () &&
747+       !linked_requests.As <Value>()->IsUndefined ()) {
748+     //  If the module is already linked, we should not link it again.
749+     THROW_ERR_VM_MODULE_LINK_FAILURE (realm->env (), " module is already linked" 
750+     return ;
751+   }
752+ 
581753  Local<FixedArray> requests =
582754      dependent->module_ .Get (isolate)->GetModuleRequests ();
583755  Local<Array> modules = args[0 ].As <Array>();
584756  CHECK_EQ (modules->Length (), static_cast <uint32_t >(requests->Length ()));
585757
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-   }
758+   args.This ()->SetInternalField (kLinkedRequestsSlot , modules);
759+   dependent->linked_  = true ;
602760}
603761
604762void  ModuleWrap::Instantiate (const  FunctionCallbackInfo<Value>& args) {
@@ -609,11 +767,16 @@ void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
609767  Local<Context> context = obj->context ();
610768  Local<Module> module  = obj->module_ .Get (isolate);
611769  TryCatchScope try_catch (realm->env ());
612-   USE (module ->InstantiateModule (
613-       context, ResolveModuleCallback, ResolveSourceCallback));
614770
615-   //  clear resolve cache on instantiate
616-   obj->resolve_cache_ .clear ();
771+   {
772+     ModuleInstantiationContext instantiation_context;
773+     USE (module ->InstantiateModule (
774+         context,
775+         ModuleInstantiationContext::ResolveModuleCallback,
776+         ModuleInstantiationContext::ResolveSourceCallback));
777+ 
778+     //  instantiation_context goes out of scope.
779+   }
617780
618781  if  (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
619782    CHECK (!try_catch.Message ().IsEmpty ());
@@ -719,11 +882,16 @@ void ModuleWrap::InstantiateSync(const FunctionCallbackInfo<Value>& args) {
719882
720883  {
721884    TryCatchScope try_catch (env);
722-     USE (module ->InstantiateModule (
723-         context, ResolveModuleCallback, ResolveSourceCallback));
724885
725-     //  clear resolve cache on instantiate
726-     obj->resolve_cache_ .clear ();
886+     {
887+       ModuleInstantiationContext instantiation_context;
888+       USE (module ->InstantiateModule (
889+           context,
890+           ModuleInstantiationContext::ResolveModuleCallback,
891+           ModuleInstantiationContext::ResolveSourceCallback));
892+ 
893+       //  instantiation_context goes out of scope.
894+     }
727895
728896    if  (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
729897      CHECK (!try_catch.Message ().IsEmpty ());
@@ -965,98 +1133,6 @@ void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
9651133  args.GetReturnValue ().Set (module ->GetException ());
9661134}
9671135
968- MaybeLocal<Module> ModuleWrap::ResolveModuleCallback (
969-     Local<Context> context,
970-     Local<String> specifier,
971-     Local<FixedArray> import_attributes,
972-     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" specifier );
987-     return  MaybeLocal<Module>();
988-   }
989- 
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" specifier );
993-     return  MaybeLocal<Module>();
994-   }
995- 
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" specifier );
1001-     return  MaybeLocal<Module>();
1002-   }
1003- 
1004-   ModuleWrap* module ;
1005-   ASSIGN_OR_RETURN_UNWRAP (&module , module_object, MaybeLocal<Module>());
1006-   return  module ->module_ .Get (isolate);
1007- }
1008- 
1009- MaybeLocal<Object> ModuleWrap::ResolveSourceCallback (
1010-     Local<Context> context,
1011-     Local<String> specifier,
1012-     Local<FixedArray> import_attributes,
1013-     Local<Module> referrer) {
1014-   Isolate* isolate = context->GetIsolate ();
1015-   Environment* env = Environment::GetCurrent (context);
1016-   if  (env == nullptr ) {
1017-     THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE (isolate);
1018-     return  MaybeLocal<Object>();
1019-   }
1020- 
1021-   ModuleCacheKey cache_key =
1022-       ModuleCacheKey::From (context, specifier, import_attributes);
1023- 
1024-   ModuleWrap* dependent = GetFromModule (env, referrer);
1025-   if  (dependent == nullptr ) {
1026-     THROW_ERR_VM_MODULE_LINK_FAILURE (
1027-         env, " request for '%s' is from invalid module" specifier );
1028-     return  MaybeLocal<Object>();
1029-   }
1030- 
1031-   if  (dependent->resolve_cache_ .count (cache_key) != 1 ) {
1032-     THROW_ERR_VM_MODULE_LINK_FAILURE (
1033-         env, " request for '%s' is not in cache" specifier );
1034-     return  MaybeLocal<Object>();
1035-   }
1036- 
1037-   Local<Object> module_object =
1038-       dependent->resolve_cache_ [cache_key].Get (isolate);
1039-   if  (module_object.IsEmpty () || !module_object->IsObject ()) {
1040-     THROW_ERR_VM_MODULE_LINK_FAILURE (
1041-         env, " request for '%s' did not return an object" specifier );
1042-     return  MaybeLocal<Object>();
1043-   }
1044- 
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>();
1058- }
1059- 
10601136static  MaybeLocal<Promise> ImportModuleDynamicallyWithPhase (
10611137    Local<Context> context,
10621138    Local<Data> host_defined_options,
0 commit comments