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()));

136138137139

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

}

143154144155

ModuleWrap::~ModuleWrap() {

@@ -159,6 +170,30 @@ Local<Context> ModuleWrap::context() const {

159170

return 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+162197

ModuleWrap* 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) {

571606

void 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;

577611

ASSIGN_OR_RETURN_UNWRAP(&dependent, args.This());

578612579613

CHECK_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>();

584627

CHECK_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

}

603632604633

void 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));

614643615-

// 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));

724750725-

// 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

}

967990991+

// static

968992

MaybeLocal<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);

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);

1020104810211049

ModuleCacheKey cache_key =

10221050

ModuleCacheKey::From(context, specifier, import_attributes);

102310511024-

ModuleWrap* dependent = GetFromModule(env, referrer);

1052+

ModuleWrap* dependent = ModuleWrap::GetFromModule(env, referrer);

10251053

if (dependent == nullptr) {

10261054

THROW_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()) {

10321059

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*>();

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()) {

10401068

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*>();

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

}

1059107710601078

static MaybeLocal<Promise> ImportModuleDynamicallyWithPhase(