|
2 | 2 |
|
3 | 3 | const assert = require('internal/assert');
|
4 | 4 | const {
|
| 5 | + Array, |
5 | 6 | ArrayIsArray,
|
6 | 7 | ArrayPrototypeForEach,
|
7 | 8 | ArrayPrototypeIndexOf,
|
| 9 | + ArrayPrototypeMap, |
8 | 10 | ArrayPrototypeSome,
|
9 | 11 | ObjectDefineProperty,
|
10 | 12 | ObjectFreeze,
|
11 | 13 | ObjectGetPrototypeOf,
|
12 | 14 | ObjectSetPrototypeOf,
|
| 15 | + PromiseResolve, |
| 16 | + PromisePrototypeThen, |
13 | 17 | ReflectApply,
|
14 |
| - SafePromiseAllReturnVoid, |
| 18 | + SafePromiseAllReturnArrayLike, |
15 | 19 | Symbol,
|
16 | 20 | SymbolToStringTag,
|
17 | 21 | TypeError,
|
@@ -303,46 +307,62 @@ class SourceTextModule extends Module {
|
303 | 307 | importModuleDynamically,
|
304 | 308 | });
|
305 | 309 |
|
306 |
| - this[kLink] = async (linker) => { |
307 |
| - this.#statusOverride = 'linking'; |
| 310 | + this[kDependencySpecifiers] = undefined; |
| 311 | + } |
308 | 312 |
|
309 |
| - const promises = this[kWrap].link(async (identifier, attributes) => { |
310 |
| - const module = await linker(identifier, this, { attributes, assert: attributes }); |
311 |
| - if (module[kWrap] === undefined) { |
312 |
| - throw new ERR_VM_MODULE_NOT_MODULE(); |
313 |
| - } |
314 |
| - if (module.context !== this.context) { |
315 |
| - throw new ERR_VM_MODULE_DIFFERENT_CONTEXT(); |
316 |
| - } |
317 |
| - if (module.status === 'errored') { |
318 |
| - throw new ERR_VM_MODULE_LINK_FAILURE(`request for '${identifier}' resolved to an errored module`, module.error); |
319 |
| - } |
320 |
| - if (module.status === 'unlinked') { |
321 |
| - await module[kLink](linker); |
322 |
| - } |
323 |
| - return module[kWrap]; |
| 313 | + async [kLink](linker) { |
| 314 | + this.#statusOverride = 'linking'; |
| 315 | + |
| 316 | + const moduleRequestsLength = this[kWrap].moduleRequests.length; |
| 317 | + // Iterates the module requests and links with the linker. |
| 318 | + // Specifiers should be aligned with the moduleRequests array in order. |
| 319 | + const specifiers = Array(moduleRequestsLength); |
| 320 | + const modulePromises = Array(moduleRequestsLength); |
| 321 | + // Iterates with index to avoid calling into userspace with `Symbol.iterator`. |
| 322 | + for (let idx = 0; idx < moduleRequestsLength; idx++) { |
| 323 | + const { specifier, attributes } = this[kWrap].moduleRequests[idx]; |
| 324 | + |
| 325 | + const linkerResult = linker(specifier, this, { |
| 326 | + attributes, |
| 327 | + assert: attributes, |
324 | 328 | });
|
325 |
| - |
326 |
| - try { |
327 |
| - if (promises !== undefined) { |
328 |
| - await SafePromiseAllReturnVoid(promises); |
329 |
| - } |
330 |
| - } catch (e) { |
331 |
| - this.#error = e; |
332 |
| - throw e; |
333 |
| - } finally { |
334 |
| - this.#statusOverride = undefined; |
335 |
| - } |
336 |
| - }; |
337 |
| - |
338 |
| - this[kDependencySpecifiers] = undefined; |
| 329 | + const modulePromise = PromisePrototypeThen( |
| 330 | + PromiseResolve(linkerResult), async (module) => { |
| 331 | + if (module[kWrap] === undefined) { |
| 332 | + throw new ERR_VM_MODULE_NOT_MODULE(); |
| 333 | + } |
| 334 | + if (module.context !== this.context) { |
| 335 | + throw new ERR_VM_MODULE_DIFFERENT_CONTEXT(); |
| 336 | + } |
| 337 | + if (module.status === 'errored') { |
| 338 | + throw new ERR_VM_MODULE_LINK_FAILURE(`request for '${specifier}' resolved to an errored module`, module.error); |
| 339 | + } |
| 340 | + if (module.status === 'unlinked') { |
| 341 | + await module[kLink](linker); |
| 342 | + } |
| 343 | + return module[kWrap]; |
| 344 | + }); |
| 345 | + modulePromises[idx] = modulePromise; |
| 346 | + specifiers[idx] = specifier; |
| 347 | + } |
| 348 | + |
| 349 | + try { |
| 350 | + const modules = await SafePromiseAllReturnArrayLike(modulePromises); |
| 351 | + this[kWrap].link(specifiers, modules); |
| 352 | + } catch (e) { |
| 353 | + this.#error = e; |
| 354 | + throw e; |
| 355 | + } finally { |
| 356 | + this.#statusOverride = undefined; |
| 357 | + } |
339 | 358 | }
|
340 | 359 |
|
341 | 360 | get dependencySpecifiers() {
|
342 | 361 | if (this[kWrap] === undefined) {
|
343 | 362 | throw new ERR_VM_MODULE_NOT_MODULE();
|
344 | 363 | }
|
345 |
| - this[kDependencySpecifiers] ??= ObjectFreeze(this[kWrap].getStaticDependencySpecifiers()); |
| 364 | + this[kDependencySpecifiers] ??= ObjectFreeze( |
| 365 | + ArrayPrototypeMap(this[kWrap].moduleRequests, (request) => request.specifier)); |
346 | 366 | return this[kDependencySpecifiers];
|
347 | 367 | }
|
348 | 368 |
|
@@ -408,10 +428,10 @@ class SyntheticModule extends Module {
|
408 | 428 | context,
|
409 | 429 | identifier,
|
410 | 430 | });
|
| 431 | + } |
411 | 432 |
|
412 |
| - this[kLink] = () => this[kWrap].link(() => { |
413 |
| - assert.fail('link callback should not be called'); |
414 |
| - }); |
| 433 | + [kLink]() { |
| 434 | + /** nothing to do for synthetic modules */ |
415 | 435 | }
|
416 | 436 |
|
417 | 437 | setExport(name, value) {
|
|
0 commit comments