@@ -133,12 +133,23 @@ ModuleWrap::ModuleWrap(Realm* realm,
133133  object->SetInternalField (kSyntheticEvaluationStepsSlot ,
134134                           synthetic_evaluation_step);
135135  object->SetInternalField (kContextObjectSlot , context_object);
136+   object->SetInternalField (kLinkedRequestsSlot ,
137+                            v8::Undefined (realm->isolate ()));
136138
137139  if  (!synthetic_evaluation_step->IsUndefined ()) {
138140    synthetic_ = true ;
139141  }
140142  MakeWeak ();
141143  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+   }
142153}
143154
144155ModuleWrap::~ModuleWrap () {
@@ -159,6 +170,30 @@ Local<Context> ModuleWrap::context() const {
159170  return  obj.As <Object>()->GetCreationContextChecked ();
160171}
161172
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+ 
162197ModuleWrap* ModuleWrap::GetFromModule (Environment* env,
163198                                      Local<Module> module ) {
164199  auto  range = env->hash_to_module_map .equal_range (module ->GetIdentityHash ());
@@ -571,34 +606,28 @@ void ModuleWrap::GetModuleRequests(const FunctionCallbackInfo<Value>& args) {
571606void  ModuleWrap::Link (const  FunctionCallbackInfo<Value>& args) {
572607  Realm* realm = Realm::GetCurrent (args);
573608  Isolate* isolate = args.GetIsolate ();
574-   Local<Context> context = realm->context ();
575609
576610  ModuleWrap* dependent;
577611  ASSIGN_OR_RETURN_UNWRAP (&dependent, args.This ());
578612
579613  CHECK_EQ (args.Length (), 1 );
580614
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+ 
581624  Local<FixedArray> requests =
582625      dependent->module_ .Get (isolate)->GetModuleRequests ();
583626  Local<Array> modules = args[0 ].As <Array>();
584627  CHECK_EQ (modules->Length (), static_cast <uint32_t >(requests->Length ()));
585628
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 ;
602631}
603632
604633void  ModuleWrap::Instantiate (const  FunctionCallbackInfo<Value>& args) {
@@ -612,9 +641,6 @@ void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
612641  USE (module ->InstantiateModule (
613642      context, ResolveModuleCallback, ResolveSourceCallback));
614643
615-   //  clear resolve cache on instantiate
616-   obj->resolve_cache_ .clear ();
617- 
618644  if  (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
619645    CHECK (!try_catch.Message ().IsEmpty ());
620646    CHECK (!try_catch.Exception ().IsEmpty ());
@@ -722,9 +748,6 @@ void ModuleWrap::InstantiateSync(const FunctionCallbackInfo<Value>& args) {
722748    USE (module ->InstantiateModule (
723749        context, ResolveModuleCallback, ResolveSourceCallback));
724750
725-     //  clear resolve cache on instantiate
726-     obj->resolve_cache_ .clear ();
727- 
728751    if  (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
729752      CHECK (!try_catch.Message ().IsEmpty ());
730753      CHECK (!try_catch.Exception ().IsEmpty ());
@@ -965,48 +988,51 @@ void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
965988  args.GetReturnValue ().Set (module ->GetException ());
966989}
967990
991+ //  static
968992MaybeLocal<Module> ModuleWrap::ResolveModuleCallback (
969993    Local<Context> context,
970994    Local<String> specifier,
971995    Local<FixedArray> import_attributes,
972996    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>();
997+   ModuleWrap* resolved_module;
998+   if  (!ResolveModule (context, specifier, import_attributes, referrer)
999+            .To (&resolved_module)) {
1000+     return  {};
9881001  }
1002+   DCHECK_NOT_NULL (resolved_module);
1003+   return  resolved_module->module_ .Get (context->GetIsolate ());
1004+ }
9891005
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>();
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  {};
9941016  }
1017+   DCHECK_NOT_NULL (resolved_module);
9951018
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>();
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  {};
10021029  }
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>();
10071032}
10081033
1009- MaybeLocal<Object> ModuleWrap::ResolveSourceCallback (
1034+ //  static
1035+ Maybe<ModuleWrap*> ModuleWrap::ResolveModule (
10101036    Local<Context> context,
10111037    Local<String> specifier,
10121038    Local<FixedArray> import_attributes,
@@ -1015,46 +1041,38 @@ MaybeLocal<Object> ModuleWrap::ResolveSourceCallback(
10151041  Environment* env = Environment::GetCurrent (context);
10161042  if  (env == nullptr ) {
10171043    THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE (isolate);
1018-     return  MaybeLocal<Object >();
1044+     return  Nothing<ModuleWrap* >();
10191045  }
1046+   //  Check that the referrer is not yet been instantiated.
1047+   DCHECK (referrer->GetStatus () <= Module::kInstantiated );
10201048
10211049  ModuleCacheKey cache_key =
10221050      ModuleCacheKey::From (context, specifier, import_attributes);
10231051
1024-   ModuleWrap* dependent = GetFromModule (env, referrer);
1052+   ModuleWrap* dependent = ModuleWrap:: GetFromModule
10251053  if  (dependent == nullptr ) {
10261054    THROW_ERR_VM_MODULE_LINK_FAILURE (
10271055        env, " request for '%s' is from invalid module" specifier );
1028-     return  MaybeLocal<Object >();
1056+     return  Nothing<ModuleWrap* >();
10291057  }
1030- 
1031-   if  (dependent->resolve_cache_ .count (cache_key) != 1 ) {
1058+   if  (!dependent->IsLinked ()) {
10321059    THROW_ERR_VM_MODULE_LINK_FAILURE (
1033-         env, " request for '%s' is not in cache" 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*>();
10351064  }
10361065
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 ()) {
10401068    THROW_ERR_VM_MODULE_LINK_FAILURE (
1041-         env, " request for '%s' did  not return an object " specifier );
1042-     return  MaybeLocal<Object >();
1069+         env, " request for '%s' is  not in cache " specifier );
1070+     return  Nothing<ModuleWrap* >();
10431071  }
10441072
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);
10581076}
10591077
10601078static  MaybeLocal<Promise> ImportModuleDynamicallyWithPhase (
0 commit comments