Open
Description
Consider the test case below.
There are two modules (a and b), with a depending on b. b uses top-level await. We dynamically import a and b, and then settle the promise that b is waiting on.
// entrypoint.js
import { p1, pA, pB } from "./setup.js";
let logs = [];
const importsP = Promise.all([
import("./a.js").finally(() => logs.push(1)).catch(() => {}),
import("./b.js").finally(() => logs.push(2)).catch(() => {}),
])
// Wait for evaluation of both graphs with entyrpoints in A and B to start before
// settling the promise that B is blocked on.
Promise.all([pA.promise, pB.promise]).then(p1.resolve);
importsP.then(() => {
print(logs);
});
// setup.js
export const p1 = Promise.withResolvers();
export const pA = Promise.withResolvers();
export const pB = Promise.withResolvers();
// a.js
import "./a-sentinel.js";
import "./b.js";
// b.js
import "./b-sentinel.js";
import { p1 } from "./setup.js";
await p1.promise;
// a-sentinel.js
import { pA } from "./setup.js";
pA.resolve();
// b-sentinel.js
import { pB } from "./setup.js";
pB.resolve();
- If we fullfill p1 (
p1.resolve()
), then thelogs
order will be2,1
(b
's promise settles first). This is because AsyncModuleExecutionFulfilled(module) (where module isb
) first resolves module.[[TopLevelCapability]] and then recurses to its parents. - If we reject p1 (
p1.reject()
), then thelogs
order will be1,2
(a
's promise settles first). This is because AsyncModuleExecutionRejected(module) first recurses to module's parents and then rejects module.[[TopLevelCapability]].
Obviously the order for the .resolve()
case cannot change (because a
could itself use TLA), but the order for .reject()
can be changed because there is no code execution between when b
errors and all its ancestors get rejected.
My eshost is broken, but I tried in Deno and Bun and neither follows the spec:
- Deno logs
2,1
in both cases - Bun logs
1,2
in both cases
I propose that we change the spec to match what Deno/V8 is doing.
This is not covered by test262, so even if we decide to keep the current behavior we need to add a test.
Metadata
Metadata
Assignees
Labels
No labels