Skip to content

Commit c29250c

Browse files
committed
fixup! fixup! esm: use index-based resolution callbacks
1 parent 60eb5d1 commit c29250c

File tree

2 files changed

+39
-42
lines changed

2 files changed

+39
-42
lines changed

src/module_wrap.cc

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -185,30 +185,6 @@ Local<Context> ModuleWrap::context() const {
185185
return obj.As<Object>()->GetCreationContextChecked();
186186
}
187187

188-
ModuleWrap* ModuleWrap::GetLinkedRequest(uint32_t index) {
189-
DCHECK(IsLinked());
190-
Isolate* isolate = env()->isolate();
191-
EscapableHandleScope scope(isolate);
192-
Local<Data> linked_requests_data =
193-
object()->GetInternalField(kLinkedRequestsSlot);
194-
DCHECK(linked_requests_data->IsValue() &&
195-
linked_requests_data.As<Value>()->IsArray());
196-
Local<Array> requests = linked_requests_data.As<Array>();
197-
198-
CHECK_LT(index, requests->Length());
199-
200-
Local<Value> module_value;
201-
if (!requests->Get(context(), index).ToLocal(&module_value)) {
202-
return nullptr;
203-
}
204-
CHECK(module_value->IsObject());
205-
Local<Object> module_object = module_value.As<Object>();
206-
207-
ModuleWrap* module_wrap;
208-
ASSIGN_OR_RETURN_UNWRAP(&module_wrap, module_object, nullptr);
209-
return module_wrap;
210-
}
211-
212188
ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
213189
Local<Module> module) {
214190
auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash());
@@ -644,6 +620,7 @@ void ModuleWrap::GetModuleRequests(const FunctionCallbackInfo<Value>& args) {
644620
// moduleWrap.link(moduleWraps)
645621
void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
646622
Isolate* isolate = args.GetIsolate();
623+
HandleScope handle_scope(isolate);
647624
Realm* realm = Realm::GetCurrent(args);
648625
Local<Context> context = realm->context();
649626

@@ -655,8 +632,13 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
655632
Local<FixedArray> requests =
656633
dependent->module_.Get(isolate)->GetModuleRequests();
657634
Local<Array> modules = args[0].As<Array>();
658-
int request_count = requests->Length();
659-
CHECK_EQ(modules->Length(), static_cast<uint32_t>(request_count));
635+
std::vector<Global<Value>> modules_vector;
636+
if (FromV8Array(context, modules, &modules_vector).IsEmpty()) {
637+
return;
638+
}
639+
size_t request_count = static_cast<size_t>(requests->Length());
640+
CHECK_EQ(modules_vector.size(), request_count);
641+
std::vector<ModuleWrap*> linked_module_wraps(request_count);
660642

661643
// Track the duplicated module requests. For example if a modulelooks like
662644
// this:
@@ -670,13 +652,13 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
670652
// module request 1 would be mapped to mod_key and both should resolve to the
671653
// module identified by module request 0 (the first one with this identity),
672654
// and module request 2 should resolve the module identified by index 2.
673-
std::unordered_map<ModuleCacheKey, int, ModuleCacheKey::Hash>
655+
std::unordered_map<ModuleCacheKey, size_t, ModuleCacheKey::Hash>
674656
module_request_map;
675-
Local<Value> current_module;
676-
Local<Value> first_seen_module;
677-
for (int i = 0; i < request_count; i++) {
657+
658+
for (size_t i = 0; i < request_count; i++) {
678659
// TODO(joyeecheung): merge this with the serializeKey() in module_map.js.
679660
// This currently doesn't sort the import attributes.
661+
Local<Value> module_value = modules_vector[i].Get(isolate);
680662
ModuleCacheKey module_cache_key = ModuleCacheKey::From(
681663
context, requests->Get(context, i).As<ModuleRequest>());
682664
auto it = module_request_map.find(module_cache_key);
@@ -686,13 +668,12 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
686668
// check here.
687669
module_request_map[module_cache_key] = i;
688670
} else { // This identity has been seen before, check for mismatch.
689-
int first_seen_index = it->second;
671+
size_t first_seen_index = it->second;
690672
// Check that the module is the same as the one resolved by the first
691673
// request with this identity.
692-
if (!modules->Get(context, i).ToLocal(&current_module) ||
693-
!modules->Get(context, first_seen_index)
694-
.ToLocal(&first_seen_module) ||
695-
!current_module->StrictEquals(first_seen_module)) {
674+
Local<Value> first_seen_value =
675+
modules_vector[first_seen_index].Get(isolate);
676+
if (!module_value->StrictEquals(first_seen_value)) {
696677
// If the module is different from the one of the same request, throw an
697678
// error.
698679
THROW_ERR_MODULE_LINK_MISMATCH(
@@ -705,9 +686,16 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
705686
return;
706687
}
707688
}
689+
690+
CHECK(module_value->IsObject()); // Guaranteed by link methods in JS land.
691+
ModuleWrap* resolved =
692+
BaseObject::Unwrap<ModuleWrap>(module_value.As<Object>());
693+
CHECK_NOT_NULL(resolved); // Guaranteed by link methods in JS land.
694+
linked_module_wraps[i] = resolved;
708695
}
709696

710697
args.This()->SetInternalField(kLinkedRequestsSlot, modules);
698+
std::swap(dependent->linked_module_wraps_, linked_module_wraps);
711699
dependent->linked_ = true;
712700
}
713701

@@ -1109,10 +1097,15 @@ Maybe<ModuleWrap*> ModuleWrap::ResolveModule(Local<Context> context,
11091097
return Nothing<ModuleWrap*>();
11101098
}
11111099

1112-
ModuleWrap* module_wrap =
1113-
dependent->GetLinkedRequest(static_cast<uint32_t>(module_request_index));
1114-
CHECK_NOT_NULL(module_wrap);
1115-
return Just(module_wrap);
1100+
size_t linked_module_count = dependent->linked_module_wraps_.size();
1101+
if (linked_module_count > 0) {
1102+
CHECK_LT(module_request_index, linked_module_count);
1103+
} else {
1104+
UNREACHABLE("Module resolution callback invoked for a module"
1105+
" without linked requests");
1106+
}
1107+
1108+
return Just(dependent->linked_module_wraps_[module_request_index]);
11161109
}
11171110

11181111
static MaybeLocal<Promise> ImportModuleDynamicallyWithPhase(

src/module_wrap.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ class ModuleWrap : public BaseObject {
100100
kModuleSourceObjectSlot,
101101
kSyntheticEvaluationStepsSlot,
102102
kContextObjectSlot, // Object whose creation context is the target Context
103-
kLinkedRequestsSlot, // Array of linked requests
103+
kLinkedRequestsSlot, // Array of linked requests, each is a ModuleWrap JS
104+
// wrapper object.
104105
kInternalFieldCount
105106
};
106107

@@ -132,8 +133,6 @@ class ModuleWrap : public BaseObject {
132133

133134
bool IsLinked() const { return linked_; }
134135

135-
ModuleWrap* GetLinkedRequest(uint32_t index);
136-
137136
static v8::Local<v8::PrimitiveArray> GetHostDefinedOptions(
138137
v8::Isolate* isolate, v8::Local<v8::Symbol> symbol);
139138

@@ -216,6 +215,11 @@ class ModuleWrap : public BaseObject {
216215
// nullopt value.
217216
std::optional<bool> has_async_graph_ = std::nullopt;
218217
int module_hash_;
218+
// Corresponds to the ModuleWrap* of the wrappers in kLinkedRequestsSlot.
219+
// These are populated during Link(), and are only valid after that as
220+
// convenient shortcuts, but do not hold the ModuleWraps alive. The actual
221+
// strong references come from the array in kLinkedRequestsSlot.
222+
std::vector<ModuleWrap*> linked_module_wraps_;
219223
};
220224

221225
} // namespace loader

0 commit comments

Comments
 (0)