◐ Shell
clean mode source ↗

module: fix submodules loaded by require() and import() · nodejs/node@7625dc4

@@ -18,6 +18,9 @@ const {

1818

StringPrototypeSplit,

1919

StringPrototypeStartsWith,

2020

} = primordials;

21+

let debug = require('internal/util/debuglog').debuglog('esm', (fn) => {

22+

debug = fn;

23+

});

21242225

const { ModuleWrap, kEvaluated } = internalBinding('module_wrap');

2326

@@ -48,8 +51,7 @@ const isCommonJSGlobalLikeNotDefinedError = (errorMessage) =>

4851

);

49525053

class ModuleJobBase {

51-

constructor(loader, url, importAttributes, moduleWrapMaybePromise, isMain, inspectBrk) {

52-

this.loader = loader;

54+

constructor(url, importAttributes, moduleWrapMaybePromise, isMain, inspectBrk) {

5355

this.importAttributes = importAttributes;

5456

this.isMain = isMain;

5557

this.inspectBrk = inspectBrk;

@@ -62,11 +64,13 @@ class ModuleJobBase {

6264

/* A ModuleJob tracks the loading of a single Module, and the ModuleJobs of

6365

* its dependencies, over time. */

6466

class ModuleJob extends ModuleJobBase {

67+

#loader = null;

6568

// `loader` is the Loader instance used for loading dependencies.

6669

constructor(loader, url, importAttributes = { __proto__: null },

6770

moduleProvider, isMain, inspectBrk, sync = false) {

6871

const modulePromise = ReflectApply(moduleProvider, loader, [url, isMain]);

69-

super(loader, url, importAttributes, modulePromise, isMain, inspectBrk);

72+

super(url, importAttributes, modulePromise, isMain, inspectBrk);

73+

this.#loader = loader;

7074

// Expose the promise to the ModuleWrap directly for linking below.

7175

// `this.module` is also filled in below.

7276

this.modulePromise = modulePromise;

@@ -89,7 +93,8 @@ class ModuleJob extends ModuleJobBase {

8993

// these `link` callbacks depending on each other.

9094

const dependencyJobs = [];

9195

const promises = this.module.link(async (specifier, attributes) => {

92-

const job = await this.loader.getModuleJob(specifier, url, attributes);

96+

const job = await this.#loader.getModuleJob(specifier, url, attributes);

97+

debug(`async link() ${this.url} -> ${specifier}`, job);

9398

ArrayPrototypePush(dependencyJobs, job);

9499

return job.modulePromise;

95100

});

@@ -121,6 +126,8 @@ class ModuleJob extends ModuleJobBase {

121126

async _instantiate() {

122127

const jobsInGraph = new SafeSet();

123128

const addJobsToDependencyGraph = async (moduleJob) => {

129+

debug(`async addJobsToDependencyGraph() ${this.url}`, moduleJob);

130+124131

if (jobsInGraph.has(moduleJob)) {

125132

return;

126133

}

@@ -156,7 +163,7 @@ class ModuleJob extends ModuleJobBase {

156163

const { 1: childSpecifier, 2: name } = RegExpPrototypeExec(

157164

/module '(.*)' does not provide an export named '(.+)'/,

158165

e.message);

159-

const { url: childFileURL } = await this.loader.resolve(

166+

const { url: childFileURL } = await this.#loader.resolve(

160167

childSpecifier,

161168

parentFileUrl,

162169

kEmptyObject,

@@ -167,7 +174,7 @@ class ModuleJob extends ModuleJobBase {

167174

// in the import attributes and some formats require them; but we only

168175

// care about CommonJS for the purposes of this error message.

169176

({ format } =

170-

await this.loader.load(childFileURL));

177+

await this.#loader.load(childFileURL));

171178

} catch {

172179

// Continue regardless of error.

173180

}

@@ -257,18 +264,27 @@ class ModuleJob extends ModuleJobBase {

257264

// All the steps are ensured to be synchronous and it throws on instantiating

258265

// an asynchronous graph.

259266

class ModuleJobSync extends ModuleJobBase {

267+

#loader = null;

260268

constructor(loader, url, importAttributes, moduleWrap, isMain, inspectBrk) {

261-

super(loader, url, importAttributes, moduleWrap, isMain, inspectBrk, true);

269+

super(url, importAttributes, moduleWrap, isMain, inspectBrk, true);

262270

assert(this.module instanceof ModuleWrap);

271+

this.#loader = loader;

263272

const moduleRequests = this.module.getModuleRequestsSync();

273+

const linked = [];

264274

for (let i = 0; i < moduleRequests.length; ++i) {

265275

const { 0: specifier, 1: attributes } = moduleRequests[i];

266-

const wrap = this.loader.getModuleWrapForRequire(specifier, url, attributes);

276+

const job = this.#loader.getModuleWrapForRequire(specifier, url, attributes);

267277

const isLast = (i === moduleRequests.length - 1);

268278

// TODO(joyeecheung): make the resolution callback deal with both promisified

269279

// an raw module wraps, then we don't need to wrap it with a promise here.

270-

this.module.cacheResolvedWrapsSync(specifier, PromiseResolve(wrap), isLast);

280+

this.module.cacheResolvedWrapsSync(specifier, PromiseResolve(job.module), isLast);

281+

ArrayPrototypePush(linked, job);

271282

}

283+

this.linked = linked;

284+

}

285+286+

get modulePromise() {

287+

return PromiseResolve(this.module);

272288

}

273289274290

async run() {