Skip to content

Commit 3586912

Browse files
Add test for importing a succesfully evaluated module of an async errored SCC
1 parent 419d85a commit 3586912

5 files changed

+93
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
/*---
5+
esid: sec-innermoduleevaluation
6+
description: >
7+
A module depending on an ~evaluated~ module that is part of a SCC that failed asynchronously
8+
info: |
9+
Module graph:
10+
11+
┌──────────────────┐ ┌────────────────────────┐
12+
│ SCC root │ │ importer of SCC leaf │
13+
└──────────────────┘ └────────────────────────┘
14+
│ ▲ │ ▲ │
15+
▼ │ ▼ │ ▼
16+
┌───────────────────────┐ ┌──────────────────┐
17+
│ SCC leaf (TLA, throw) │ │ SCC leaf 2 │
18+
└───────────────────────┘ └──────────────────┘
19+
20+
And let's assume that we import "SCC root" first and then, once its evaluation settles,
21+
we import "importer of SCC leaf".
22+
23+
This test exercises the case in which the condition in step 11.c.iv.3 of the following algorithm
24+
is true, when:
25+
- _module_ is "importer of SCC leaf",
26+
- _requiredModule_ is "SCC leaf",
27+
- _requiredModule_.[[CycleRoot]] is "SCC root".
28+
29+
After the sync pass of the evaluation of "SCC root",
30+
- the [[Status]] of "SCC leaf 2" is ~evaluated~, because even though it's in an
31+
async SCC after breaking the cycles it has no async dependencies.
32+
- the [[Status]] of "SCC leaf (TLA, throw)" and "SCC root" are ~evaluating-async~.
33+
34+
After that evaluation of "SCC leaf (TLA, throw)" resumes after the TLA, it throws
35+
and thus both its [[Status]] and "SCC root"'s [[Status]] are set to ~evaluated~,
36+
and their [[EvaluationError]] is set to the error thrown.
37+
38+
When later evaluating "importer of SCC leaf", its dependency "SCC leaf 2" has [[Status]]
39+
set to ~evaluated~ and no [[EvaluationError]], but "SCC leaf 2"'s [[CycleRoot]] has a
40+
non-empty [[EvaluationError]].
41+
42+
InnerModuleEvaluation ( module, stack, index )
43+
...
44+
11. For each ModuleRequest Record request of module.[[RequestedModules]], do
45+
a. Let requiredModule be GetImportedModule(module, request).
46+
b. Set index to ? InnerModuleEvaluation(requiredModule, stack, index).
47+
c. If requiredModule is a Cyclic Module Record, then
48+
i. Assert: requiredModule.[[Status]] is one of evaluating, evaluating-async, or evaluated.
49+
ii. Assert: requiredModule.[[Status]] is evaluating if and only if stack contains requiredModule.
50+
iii. If requiredModule.[[Status]] is evaluating, then
51+
1. Set module.[[DFSAncestorIndex]] to min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]]).
52+
iv. Else,
53+
1. Set requiredModule to requiredModule.[[CycleRoot]].
54+
2. Assert: requiredModule.[[Status]] is either evaluating-async or evaluated.
55+
3. If requiredModule.[[EvaluationError]] is not empty, return ? requiredModule.[[EvaluationError]].
56+
57+
flags: [module, async]
58+
features: [top-level-await]
59+
includes: [asyncHelpers.js]
60+
---*/
61+
62+
asyncTest(async function() {
63+
const sccRootPromise = import("./evaluated-dep-from-async-errored-scc_scc-root_FIXTURE.js");
64+
await assert.throwsAsync(Error, () => sccRootPromise, "Importing scc-root should reject");
65+
const sccRootError = await sccRootPromise.catch(e => e);
66+
assert.sameValue(sccRootError, globalThis.evaluationError);
67+
68+
const importerOfSccLeafPromise = import("./evaluated-dep-from-async-errored-scc_importer-of-scc-leaf_FIXTURE.js");
69+
await assert.throwsAsync(Error, () => importerOfSccLeafPromise, "Importing importer of SCC leaf should reject");
70+
const importerOfSccLeafError = await importerOfSccLeafPromise.catch(e => e);
71+
72+
assert.sameValue(sccRootError, importerOfSccLeafError, "The errors should be the same");
73+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
import "./evaluated-dep-from-async-errored-scc_scc-leaf-2_FIXTURE.js";
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
import "./evaluated-dep-from-async-errored-scc_scc-root_FIXTURE.js";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
import "./evaluated-dep-from-async-errored-scc_scc-root_FIXTURE.js";
5+
globalThis.evaluationError = new Error("boom");
6+
await 0;
7+
throw globalThis.evaluationError;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
import "./evaluated-dep-from-async-errored-scc_scc-leaf-tla-throw_FIXTURE.js";
5+
import "./evaluated-dep-from-async-errored-scc_scc-leaf-2_FIXTURE.js";

0 commit comments

Comments
 (0)