Skip to content

Commit edbcf7c

Browse files
devsnekBridgeAR
authored andcommitted
src, lib: return promises from link
Returns the promises created by link so that they can be awaited to get rid of race conditions while resolving and loading modules. PR-URL: nodejs#18394 Reviewed-By: Tiancheng "Timothy" Gu <[email protected]>
1 parent 3cd7977 commit edbcf7c

File tree

2 files changed

+16
-15
lines changed

2 files changed

+16
-15
lines changed

lib/internal/loader/ModuleJob.js

+10-14
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ const { decorateErrorStack } = require('internal/util');
66
const assert = require('assert');
77
const resolvedPromise = SafePromise.resolve();
88

9-
const enableDebug = (process.env.NODE_DEBUG || '').match(/\besm\b/) ||
10-
process.features.debug;
11-
129
/* A ModuleJob tracks the loading of a single Module, and the ModuleJobs of
1310
* its dependencies, over time. */
1411
class ModuleJob {
@@ -27,25 +24,24 @@ class ModuleJob {
2724

2825
// Wait for the ModuleWrap instance being linked with all dependencies.
2926
const link = async () => {
30-
const dependencyJobs = [];
3127
({ module: this.module,
3228
reflect: this.reflect } = await this.modulePromise);
3329
if (inspectBrk) {
3430
const initWrapper = process.binding('inspector').callAndPauseOnStart;
3531
initWrapper(this.module.instantiate, this.module);
3632
}
3733
assert(this.module instanceof ModuleWrap);
38-
this.module.link(async (dependencySpecifier) => {
39-
const dependencyJobPromise =
40-
this.loader.getModuleJob(dependencySpecifier, url);
41-
dependencyJobs.push(dependencyJobPromise);
42-
const dependencyJob = await dependencyJobPromise;
43-
return (await dependencyJob.modulePromise).module;
34+
35+
const dependencyJobs = [];
36+
const promises = this.module.link(async (specifier) => {
37+
const jobPromise = this.loader.getModuleJob(specifier, url);
38+
dependencyJobs.push(jobPromise);
39+
return (await (await jobPromise).modulePromise).module;
4440
});
45-
if (enableDebug) {
46-
// Make sure all dependencies are entered into the list synchronously.
47-
Object.freeze(dependencyJobs);
48-
}
41+
42+
if (promises !== undefined)
43+
await SafePromise.all(promises);
44+
4945
return SafePromise.all(dependencyJobs);
5046
};
5147
// Promise for the list of all dependencyJobs.

src/module_wrap.cc

+6-1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
171171
Local<Context> mod_context = obj->context_.Get(isolate);
172172
Local<Module> module = obj->module_.Get(isolate);
173173

174+
Local<Array> promises = Array::New(isolate,
175+
module->GetModuleRequestsLength());
176+
174177
// call the dependency resolve callbacks
175178
for (int i = 0; i < module->GetModuleRequestsLength(); i++) {
176179
Local<String> specifier = module->GetModuleRequest(i);
@@ -193,9 +196,11 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
193196
}
194197
Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
195198
obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_promise);
199+
200+
promises->Set(mod_context, specifier, resolve_promise).FromJust();
196201
}
197202

198-
args.GetReturnValue().Set(that);
203+
args.GetReturnValue().Set(promises);
199204
}
200205

201206
void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {

0 commit comments

Comments
 (0)