|
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