lib,src: iterate module requests of a module wrap in JS · nodejs/node@f13589f

11

'use strict';

2233

const {

4+

Array,

45

ArrayPrototypeJoin,

5-

ArrayPrototypePush,

66

ArrayPrototypeSome,

77

FunctionPrototype,

88

ObjectSetPrototypeOf,

@@ -82,31 +82,8 @@ class ModuleJob extends ModuleJobBase {

8282

this.modulePromise = PromiseResolve(this.modulePromise);

8383

}

848485-

// Wait for the ModuleWrap instance being linked with all dependencies.

86-

const link = async () => {

87-

this.module = await this.modulePromise;

88-

assert(this.module instanceof ModuleWrap);

89-90-

// Explicitly keeping track of dependency jobs is needed in order

91-

// to flatten out the dependency graph below in `_instantiate()`,

92-

// so that circular dependencies can't cause a deadlock by two of

93-

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

94-

const dependencyJobs = [];

95-

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

96-

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

97-

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

98-

ArrayPrototypePush(dependencyJobs, job);

99-

return job.modulePromise;

100-

});

101-102-

if (promises !== undefined) {

103-

await SafePromiseAllReturnVoid(promises);

104-

}

105-106-

return SafePromiseAllReturnArrayLike(dependencyJobs);

107-

};

10885

// Promise for the list of all dependencyJobs.

109-

this.linked = link();

86+

this.linked = this._link();

11087

// This promise is awaited later anyway, so silence

11188

// 'unhandled rejection' warnings.

11289

PromisePrototypeThen(this.linked, undefined, noop);

@@ -116,6 +93,49 @@ class ModuleJob extends ModuleJobBase {

11693

this.instantiated = undefined;

11794

}

1189596+

/**

97+

* Iterates the module requests and links with the loader.

98+

* @returns {Promise<ModuleJob[]>} Dependency module jobs.

99+

*/

100+

async _link() {

101+

this.module = await this.modulePromise;

102+

assert(this.module instanceof ModuleWrap);

103+104+

const moduleRequests = this.module.getModuleRequests();

105+

// Explicitly keeping track of dependency jobs is needed in order

106+

// to flatten out the dependency graph below in `_instantiate()`,

107+

// so that circular dependencies can't cause a deadlock by two of

108+

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

109+

// Create an ArrayLike to avoid calling into userspace with `.then`

110+

// when returned from the async function.

111+

const dependencyJobs = Array(moduleRequests.length);

112+

ObjectSetPrototypeOf(dependencyJobs, null);

113+114+

// Specifiers should be aligned with the moduleRequests array in order.

115+

const specifiers = Array(moduleRequests.length);

116+

const modulePromises = Array(moduleRequests.length);

117+

// Iterate with index to avoid calling into userspace with `Symbol.iterator`.

118+

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

119+

const { specifier, attributes } = moduleRequests[idx];

120+121+

const dependencyJobPromise = this.#loader.getModuleJob(

122+

specifier, this.url, attributes,

123+

);

124+

const modulePromise = PromisePrototypeThen(dependencyJobPromise, (job) => {

125+

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

126+

dependencyJobs[idx] = job;

127+

return job.modulePromise;

128+

});

129+

modulePromises[idx] = modulePromise;

130+

specifiers[idx] = specifier;

131+

}

132+133+

const modules = await SafePromiseAllReturnArrayLike(modulePromises);

134+

this.module.link(specifiers, modules);

135+136+

return dependencyJobs;

137+

}

138+119139

instantiate() {

120140

if (this.instantiated === undefined) {

121141

this.instantiated = this._instantiate();

@@ -269,18 +289,20 @@ class ModuleJobSync extends ModuleJobBase {

269289

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

270290

assert(this.module instanceof ModuleWrap);

271291

this.#loader = loader;

272-

const moduleRequests = this.module.getModuleRequestsSync();

273-

const linked = [];

292+

const moduleRequests = this.module.getModuleRequests();

293+

// Specifiers should be aligned with the moduleRequests array in order.

294+

const specifiers = Array(moduleRequests.length);

295+

const modules = Array(moduleRequests.length);

296+

const jobs = Array(moduleRequests.length);

274297

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

275-

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

276-

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

277-

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

278-

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

279-

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

280-

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

281-

ArrayPrototypePush(linked, job);

298+

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

299+

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

300+

specifiers[i] = specifier;

301+

modules[i] = job.module;

302+

jobs[i] = job;

282303

}

283-

this.linked = linked;

304+

this.module.link(specifiers, modules);

305+

this.linked = jobs;

284306

}

285307286308

get modulePromise() {