src: clear all linked module caches once instantiated · nodejs/node@6a47ff4
@@ -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()));
136138137139if (!synthetic_evaluation_step->IsUndefined()) {
138140 synthetic_ = true;
139141 }
140142MakeWeak();
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}
143154144155ModuleWrap::~ModuleWrap() {
@@ -159,6 +170,30 @@ Local<Context> ModuleWrap::context() const {
159170return obj.As<Object>()->GetCreationContextChecked();
160171}
161172173+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) {
164199auto 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();
575609576610 ModuleWrap* dependent;
577611ASSIGN_OR_RETURN_UNWRAP(&dependent, args.This());
578612579613CHECK_EQ(args.Length(), 1);
580614615+ 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>();
584627CHECK_EQ(modules->Length(), static_cast<uint32_t>(requests->Length()));
585628586- 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}
603632604633void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
@@ -612,9 +641,6 @@ void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
612641USE(module->InstantiateModule(
613642 context, ResolveModuleCallback, ResolveSourceCallback));
614643615-// clear resolve cache on instantiate
616- obj->resolve_cache_.clear();
617-618644if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
619645CHECK(!try_catch.Message().IsEmpty());
620646CHECK(!try_catch.Exception().IsEmpty());
@@ -722,9 +748,6 @@ void ModuleWrap::InstantiateSync(const FunctionCallbackInfo<Value>& args) {
722748USE(module->InstantiateModule(
723749 context, ResolveModuleCallback, ResolveSourceCallback));
724750725-// clear resolve cache on instantiate
726- obj->resolve_cache_.clear();
727-728751if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
729752CHECK(!try_catch.Message().IsEmpty());
730753CHECK(!try_catch.Exception().IsEmpty());
@@ -965,48 +988,51 @@ void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
965988 args.GetReturnValue().Set(module->GetException());
966989}
967990991+// 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", 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 {};
9881001 }
1002+DCHECK_NOT_NULL(resolved_module);
1003+return resolved_module->module_.Get(context->GetIsolate());
1004+}
9891005990-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 {};
9941016 }
1017+DCHECK_NOT_NULL(resolved_module);
9951018996- 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 {};
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}
100810331009-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);
10161042if (env == nullptr) {
10171043THROW_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);
1020104810211049 ModuleCacheKey cache_key =
10221050ModuleCacheKey::From(context, specifier, import_attributes);
102310511024- ModuleWrap* dependent = GetFromModule(env, referrer);
1052+ ModuleWrap* dependent = ModuleWrap::GetFromModule(env, referrer);
10251053if (dependent == nullptr) {
10261054THROW_ERR_VM_MODULE_LINK_FAILURE(
10271055 env, "request for '%s' is from invalid module", cache_key.specifier);
1028-return MaybeLocal<Object>();
1056+return Nothing<ModuleWrap*>();
10291057 }
1030-1031-if (dependent->resolve_cache_.count(cache_key) != 1) {
1058+if (!dependent->IsLinked()) {
10321059THROW_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*>();
10351064 }
103610651037- 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()) {
10401068THROW_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*>();
10431071 }
104410721045- 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}
1059107710601078static MaybeLocal<Promise> ImportModuleDynamicallyWithPhase(