From 48af056c6c99c2e592cd9207777a11f0ee061c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 2 May 2025 11:36:05 +0200 Subject: [PATCH 1/2] Test a module depending on a non-root node of an async cycle --- .../pending-async-dep-from-cycle.js | 70 +++++++++++++++++++ ...async-dep-from-cycle_cycle-leaf_FIXTURE.js | 8 +++ ...async-dep-from-cycle_cycle-root_FIXTURE.js | 8 +++ ...ep-from-cycle_import-cycle-leaf_FIXTURE.js | 6 ++ ...ding-async-dep-from-cycle_setup_FIXTURE.js | 4 ++ 5 files changed, 96 insertions(+) create mode 100644 test/language/module-code/top-level-await/pending-async-dep-from-cycle.js create mode 100644 test/language/module-code/top-level-await/pending-async-dep-from-cycle_cycle-leaf_FIXTURE.js create mode 100644 test/language/module-code/top-level-await/pending-async-dep-from-cycle_cycle-root_FIXTURE.js create mode 100644 test/language/module-code/top-level-await/pending-async-dep-from-cycle_import-cycle-leaf_FIXTURE.js create mode 100644 test/language/module-code/top-level-await/pending-async-dep-from-cycle_setup_FIXTURE.js diff --git a/test/language/module-code/top-level-await/pending-async-dep-from-cycle.js b/test/language/module-code/top-level-await/pending-async-dep-from-cycle.js new file mode 100644 index 00000000000..c0b0271698a --- /dev/null +++ b/test/language/module-code/top-level-await/pending-async-dep-from-cycle.js @@ -0,0 +1,70 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: > + A module depending on an async module of a separate cycle should wait for the cycle root to complete +info: | + Module graph: + + ┌──────────────────┐ + │ entrypoint │ + └──────────────────┘ + │ │ + ▼ ▼ + ┌──────────────────┐ ┌────────────────────────┐ + │ cycle root (TLA) │ │ importer of cycle leaf │ + └──────────────────┘ └────────────────────────┘ + │ ▲ │ + ▼ │ │ + ┌──────────────────┐ │ + │ cycle leaf (TLA) │ ◄──────┘ + └──────────────────┘ + + This test exercises step 11.c.iv.1 of the following algorithm when _module_ is + "importer of cycle leaf", _requiredModule_ is "cycle leaf (TLA)", and + _requiredModule_.[[CycleRoot]] is "cycle root (TLA)". + The [[Status]] of "cycle leaf (TLA)" and of "cycle root (TLA)" is ~evaluating-async~, + because they have alredy been traversed and they are blocked on the TLA in "cycle leaf (TLA)". + Thus, their [[AsyncEvaluationOrder]] is an integer, so the _requiredModule_ variable is used + to determine what module "importer of cycle leaf" should wait for. + + InnerModuleEvaluation ( module, stack, index ) + ... + 11. For each ModuleRequest Record request of module.[[RequestedModules]], do + a. Let requiredModule be GetImportedModule(module, request). + b. Set index to ? InnerModuleEvaluation(requiredModule, stack, index). + c. If requiredModule is a Cyclic Module Record, then + i. Assert: requiredModule.[[Status]] is one of evaluating, evaluating-async, or evaluated. + ii. Assert: requiredModule.[[Status]] is evaluating if and only if stack contains requiredModule. + iii. If requiredModule.[[Status]] is evaluating, then + 1. Set module.[[DFSAncestorIndex]] to min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]]). + iv. Else, + 1. Set requiredModule to requiredModule.[[CycleRoot]]. + 2. Assert: requiredModule.[[Status]] is either evaluating-async or evaluated. + 3. If requiredModule.[[EvaluationError]] is not empty, return ? requiredModule.[[EvaluationError]]. + v. If requiredModule.[[AsyncEvaluationOrder]] is an integer, then + 1. Set module.[[PendingAsyncDependencies]] to module.[[PendingAsyncDependencies]] + 1. + 2. Append module to requiredModule.[[AsyncParentModules]]. + +flags: [module, async] +features: [top-level-await] +includes: [compareArray.js] +---*/ + +import "./pending-async-dep-from-cycle_setup_FIXTURE.js"; +import "./pending-async-dep-from-cycle_cycle-root_FIXTURE.js"; +import "./pending-async-dep-from-cycle_import-cycle-leaf_FIXTURE.js"; + +assert.compareArray(globalThis.logs, [ + "cycle leaf start", + "cycle leaf end", + "cycle root start", + // Without the step covered by this test, + // these last two entries would be swapped. + "cycle root end", + "importer of cycle leaf" +]); + +$DONE(); diff --git a/test/language/module-code/top-level-await/pending-async-dep-from-cycle_cycle-leaf_FIXTURE.js b/test/language/module-code/top-level-await/pending-async-dep-from-cycle_cycle-leaf_FIXTURE.js new file mode 100644 index 00000000000..abe8adc6c98 --- /dev/null +++ b/test/language/module-code/top-level-await/pending-async-dep-from-cycle_cycle-leaf_FIXTURE.js @@ -0,0 +1,8 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./pending-async-dep-from-cycle_cycle-root_FIXTURE.js"; + +globalThis.logs.push("cycle leaf start"); +await 1; +globalThis.logs.push("cycle leaf end"); diff --git a/test/language/module-code/top-level-await/pending-async-dep-from-cycle_cycle-root_FIXTURE.js b/test/language/module-code/top-level-await/pending-async-dep-from-cycle_cycle-root_FIXTURE.js new file mode 100644 index 00000000000..618217c6537 --- /dev/null +++ b/test/language/module-code/top-level-await/pending-async-dep-from-cycle_cycle-root_FIXTURE.js @@ -0,0 +1,8 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./pending-async-dep-from-cycle_cycle-leaf_FIXTURE.js"; + +globalThis.logs.push("cycle root start"); +await 1; +globalThis.logs.push("cycle root end"); diff --git a/test/language/module-code/top-level-await/pending-async-dep-from-cycle_import-cycle-leaf_FIXTURE.js b/test/language/module-code/top-level-await/pending-async-dep-from-cycle_import-cycle-leaf_FIXTURE.js new file mode 100644 index 00000000000..1e102a9de86 --- /dev/null +++ b/test/language/module-code/top-level-await/pending-async-dep-from-cycle_import-cycle-leaf_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./pending-async-dep-from-cycle_cycle-leaf_FIXTURE.js"; + +globalThis.logs.push("importer of cycle leaf"); diff --git a/test/language/module-code/top-level-await/pending-async-dep-from-cycle_setup_FIXTURE.js b/test/language/module-code/top-level-await/pending-async-dep-from-cycle_setup_FIXTURE.js new file mode 100644 index 00000000000..5a4508019b4 --- /dev/null +++ b/test/language/module-code/top-level-await/pending-async-dep-from-cycle_setup_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.logs = []; From d21858bbff3883636c1ce6c54435e73d44f08103 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Tue, 28 Oct 2025 11:47:35 -0400 Subject: [PATCH 2/2] fixup! Test a module depending on a non-root node of an async cycle --- .../module-code/top-level-await/pending-async-dep-from-cycle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/language/module-code/top-level-await/pending-async-dep-from-cycle.js b/test/language/module-code/top-level-await/pending-async-dep-from-cycle.js index c0b0271698a..d8438bb3cc2 100644 --- a/test/language/module-code/top-level-await/pending-async-dep-from-cycle.js +++ b/test/language/module-code/top-level-await/pending-async-dep-from-cycle.js @@ -26,7 +26,7 @@ info: | "importer of cycle leaf", _requiredModule_ is "cycle leaf (TLA)", and _requiredModule_.[[CycleRoot]] is "cycle root (TLA)". The [[Status]] of "cycle leaf (TLA)" and of "cycle root (TLA)" is ~evaluating-async~, - because they have alredy been traversed and they are blocked on the TLA in "cycle leaf (TLA)". + because they have already been traversed and they are blocked on the TLA in "cycle leaf (TLA)". Thus, their [[AsyncEvaluationOrder]] is an integer, so the _requiredModule_ variable is used to determine what module "importer of cycle leaf" should wait for.