From 79030c90c16b38ca4e2773ae218b466259100fdb Mon Sep 17 00:00:00 2001 From: Caio Lima Date: Thu, 30 Apr 2026 12:19:01 -0300 Subject: [PATCH] [export-defer] Add tests for evaluation order This change adds test cases that covers `Evaluation Order` section from "Export Defer" test plan. --- .../barrel-order/a_FIXTURE.js | 5 ++ .../barrel-order/b_FIXTURE.js | 5 ++ .../barrel-order/barrel-order.js | 64 ++++++++++++++++++ .../barrel-order/barrel_FIXTURE.js | 6 ++ .../cycle-back-to-defer-source/b_FIXTURE.js | 5 ++ .../cycle-back-to-defer-source/c_FIXTURE.js | 6 ++ .../cycle-back-to-defer-source.js | 62 +++++++++++++++++ .../cycle-back-to-defer-source/d_FIXTURE.js | 5 ++ .../cycle-through-ancestor/b_FIXTURE.js | 5 ++ .../cycle-through-ancestor/c_FIXTURE.js | 6 ++ .../cycle-through-ancestor.js | 62 +++++++++++++++++ .../cycle-through-ancestor/d_FIXTURE.js | 5 ++ .../declaration-order/barrel_FIXTURE.js | 7 ++ .../declaration-order/declaration-order.js | 65 ++++++++++++++++++ .../declaration-order/dep-1_FIXTURE.js | 5 ++ .../declaration-order/dep-2_FIXTURE.js | 5 ++ .../declaration-order/dep-3_FIXTURE.js | 5 ++ .../barrel_FIXTURE.js | 8 +++ .../deferred-1_FIXTURE.js | 5 ++ .../deferred-2_FIXTURE.js | 5 ++ .../eager-1_FIXTURE.js | 5 ++ .../eager-2_FIXTURE.js | 5 ++ .../multiple-deferred-mixed-with-eager.js | 66 +++++++++++++++++++ .../barrel_FIXTURE.js | 6 ++ .../defer-dep_FIXTURE.js | 5 ++ .../eager-dep_FIXTURE.js | 5 ++ .../non-deferred-before-deferred-after.js | 62 +++++++++++++++++ .../same-source-barrel_FIXTURE.js | 6 ++ .../same-source-dep_FIXTURE.js | 6 ++ .../same-source-eager-and-deferred.js | 64 ++++++++++++++++++ .../evaluation-order/setup_FIXTURE.js | 4 ++ .../evaluation-order/tla-async-dep_FIXTURE.js | 6 ++ .../evaluation-order/tla-barrel_FIXTURE.js | 5 ++ .../evaluation-order/tla-deferred-source.js | 65 ++++++++++++++++++ 34 files changed, 651 insertions(+) create mode 100644 test/language/export/export-defer/evaluation-order/barrel-order/a_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/barrel-order/b_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/barrel-order/barrel-order.js create mode 100644 test/language/export/export-defer/evaluation-order/barrel-order/barrel_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/b_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/c_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/cycle-back-to-defer-source.js create mode 100644 test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/d_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/cycle-through-ancestor/b_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/cycle-through-ancestor/c_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/cycle-through-ancestor/cycle-through-ancestor.js create mode 100644 test/language/export/export-defer/evaluation-order/cycle-through-ancestor/d_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/declaration-order/barrel_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/declaration-order/declaration-order.js create mode 100644 test/language/export/export-defer/evaluation-order/declaration-order/dep-1_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/declaration-order/dep-2_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/declaration-order/dep-3_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/barrel_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/deferred-1_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/deferred-2_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/eager-1_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/eager-2_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/multiple-deferred-mixed-with-eager.js create mode 100644 test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/barrel_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/defer-dep_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/eager-dep_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/non-deferred-before-deferred-after.js create mode 100644 test/language/export/export-defer/evaluation-order/same-source-barrel_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/same-source-dep_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/same-source-eager-and-deferred.js create mode 100644 test/language/export/export-defer/evaluation-order/setup_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/tla-async-dep_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/tla-barrel_FIXTURE.js create mode 100644 test/language/export/export-defer/evaluation-order/tla-deferred-source.js diff --git a/test/language/export/export-defer/evaluation-order/barrel-order/a_FIXTURE.js b/test/language/export/export-defer/evaluation-order/barrel-order/a_FIXTURE.js new file mode 100644 index 00000000000..3918ddaa494 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/barrel-order/a_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("a"); +export const a = "a-value"; diff --git a/test/language/export/export-defer/evaluation-order/barrel-order/b_FIXTURE.js b/test/language/export/export-defer/evaluation-order/barrel-order/b_FIXTURE.js new file mode 100644 index 00000000000..1f038e50747 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/barrel-order/b_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("b"); +export const b = "b-value"; diff --git a/test/language/export/export-defer/evaluation-order/barrel-order/barrel-order.js b/test/language/export/export-defer/evaluation-order/barrel-order/barrel-order.js new file mode 100644 index 00000000000..bd9f59d682c --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/barrel-order/barrel-order.js @@ -0,0 +1,64 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: Barrel evaluation order with one eager and one deferred re-export resolves as b -> barrel -> a -> entrypoint +info: | + 1. Evaluate ( [ importedNames ] ) + 1. ... + 1. Else, + 1. ... + 1. Let _result_ be Completion(InnerModuleEvaluation(_module_, _stack_, 0)). + 1. ... + 1. ... + 1. Let _optionalIndirectRequests_ be _module_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Let _promises_ be « _topLevelPromise_ ». + 1. For each ModuleRequest Record _request_ of _optionalIndirectRequests_, do + 1. ... + 1. Let _innerPromise_ be _requiredModule_.Evaluate(_request_.[[ImportedNames]]). + 1. ... + 1. Append _innerPromise_ to _promises_. + 1. If _promises_ contains a Promise _P_ such that _P_.[[PromiseState]] is ~pending~, then + 1. ... + 1. Return ! SafePerformPromiseAll(...). + + 1. InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be « ». + 1. Perform BuildEvaluationList(_evaluationList_, _module_, _module_.[[RequestedModules]]). + + 1. BuildEvaluationList ( _evaluationList_, _referrer_, _moduleRequests_ ) + 1. For each ModuleRequest Record _request_ of _moduleRequests_, do + 1. Let _requiredModule_ be GetImportedModule(_referrer_, _request_.[[Specifier]]). + 1. If _request_.[[Phase]] is ~defer~, then + 1. Perform ListAppendUnique(_evaluationList_, GatherAsynchronousTransitiveDependencies(_requiredModule_)). + 1. Else if _evaluationList_ does not contain _requiredModule_, then + 1. Append _requiredModule_ to _evaluationList_. + 1. If _requiredModule_ is a Cyclic Module Record, then + 1. Let _importedNames_ be _request_.[[ImportedNames]]. + 1. ... + 1. Else, + 1. Let _optionalIndirectRequests_ be _requiredModule_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Perform BuildEvaluationList(_evaluationList_, _requiredModule_, _optionalIndirectRequests_). + + Modules that are re-exported using "defer" evaluates after the module that is + re-exporting it. +flags: [module] +features: [export-defer] +includes: [compareArray.js] +---*/ + +import "../setup_FIXTURE.js"; +import { a, b } from "./barrel_FIXTURE.js"; + +assert.sameValue(a, "a-value", "deferred re-export `a` resolves to the source's value"); +assert.sameValue(b, "b-value", "eager re-export `b` resolves to the source's value"); + +globalThis.evaluations.push("entrypoint"); + +assert.compareArray( + globalThis.evaluations, + ["b", "barrel", "a", "entrypoint"], + "evaluation order matches the bullet's expected b -> barrel -> a -> entrypoint" +); diff --git a/test/language/export/export-defer/evaluation-order/barrel-order/barrel_FIXTURE.js b/test/language/export/export-defer/evaluation-order/barrel-order/barrel_FIXTURE.js new file mode 100644 index 00000000000..12464900ff1 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/barrel-order/barrel_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +export { b } from "./b_FIXTURE.js"; +export defer { a } from "./a_FIXTURE.js"; +globalThis.evaluations.push("barrel"); diff --git a/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/b_FIXTURE.js b/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/b_FIXTURE.js new file mode 100644 index 00000000000..f50756fdb2b --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/b_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("b"); +export defer { x } from "./c_FIXTURE.js"; diff --git a/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/c_FIXTURE.js b/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/c_FIXTURE.js new file mode 100644 index 00000000000..9ed1d9b2691 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/c_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./d_FIXTURE.js"; +globalThis.evaluations.push("c"); +export const x = "x-from-c"; diff --git a/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/cycle-back-to-defer-source.js b/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/cycle-back-to-defer-source.js new file mode 100644 index 00000000000..0f4096482aa --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/cycle-back-to-defer-source.js @@ -0,0 +1,62 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: Cycle a -> b -> c -> d -> b where b deferred-re-exports x from c evaluates as b, d, c, a +info: | + 1. Evaluate ( [ importedNames ] ) + 1. ... + 1. Else, + 1. ... + 1. Let _result_ be Completion(InnerModuleEvaluation(_module_, _stack_, 0)). + 1. ... + 1. ... + 1. Let _optionalIndirectRequests_ be _module_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Let _promises_ be « _topLevelPromise_ ». + 1. For each ModuleRequest Record _request_ of _optionalIndirectRequests_, do + 1. ... + 1. Let _innerPromise_ be _requiredModule_.Evaluate(_request_.[[ImportedNames]]). + 1. ... + 1. Append _innerPromise_ to _promises_. + 1. If _promises_ contains a Promise _P_ such that _P_.[[PromiseState]] is ~pending~, then + 1. ... + 1. Return ! SafePerformPromiseAll(...). + + 1. InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be « ». + 1. Perform BuildEvaluationList(_evaluationList_, _module_, _module_.[[RequestedModules]]). + + 1. BuildEvaluationList ( _evaluationList_, _referrer_, _moduleRequests_ ) + 1. For each ModuleRequest Record _request_ of _moduleRequests_, do + 1. Let _requiredModule_ be GetImportedModule(_referrer_, _request_.[[Specifier]]). + 1. If _request_.[[Phase]] is ~defer~, then + 1. Perform ListAppendUnique(_evaluationList_, GatherAsynchronousTransitiveDependencies(_requiredModule_)). + 1. Else if _evaluationList_ does not contain _requiredModule_, then + 1. Append _requiredModule_ to _evaluationList_. + 1. If _requiredModule_ is a Cyclic Module Record, then + 1. Let _importedNames_ be _request_.[[ImportedNames]]. + 1. ... + 1. Else, + 1. Let _optionalIndirectRequests_ be _requiredModule_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Perform BuildEvaluationList(_evaluationList_, _requiredModule_, _optionalIndirectRequests_). + + Modules that are re-exported using "defer" evaluates after the module that is + re-exporting it. +flags: [module] +features: [export-defer] +includes: [compareArray.js] +---*/ + +import "../setup_FIXTURE.js"; +import { x } from "./b_FIXTURE.js"; + +assert.sameValue(x, "x-from-c", "deferred re-export `x` resolves through b to c's binding"); +globalThis.evaluations.push("a"); + +assert.compareArray( + globalThis.evaluations, + ["b", "d", "c", "a"], + "cycle back to defer source evaluates b -> d -> c -> a" +); diff --git a/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/d_FIXTURE.js b/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/d_FIXTURE.js new file mode 100644 index 00000000000..57f586737ac --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/cycle-back-to-defer-source/d_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./b_FIXTURE.js"; +globalThis.evaluations.push("d"); diff --git a/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/b_FIXTURE.js b/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/b_FIXTURE.js new file mode 100644 index 00000000000..f50756fdb2b --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/b_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("b"); +export defer { x } from "./c_FIXTURE.js"; diff --git a/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/c_FIXTURE.js b/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/c_FIXTURE.js new file mode 100644 index 00000000000..9ed1d9b2691 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/c_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./d_FIXTURE.js"; +globalThis.evaluations.push("c"); +export const x = "x-from-c"; diff --git a/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/cycle-through-ancestor.js b/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/cycle-through-ancestor.js new file mode 100644 index 00000000000..543e56e0dcc --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/cycle-through-ancestor.js @@ -0,0 +1,62 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: Cycle a -> b -> c -> d -> a where b deferred-re-exports x from c evaluates as b, d, c, a +info: | + 1. Evaluate ( [ importedNames ] ) + 1. ... + 1. Else, + 1. ... + 1. Let _result_ be Completion(InnerModuleEvaluation(_module_, _stack_, 0)). + 1. ... + 1. ... + 1. Let _optionalIndirectRequests_ be _module_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Let _promises_ be « _topLevelPromise_ ». + 1. For each ModuleRequest Record _request_ of _optionalIndirectRequests_, do + 1. ... + 1. Let _innerPromise_ be _requiredModule_.Evaluate(_request_.[[ImportedNames]]). + 1. ... + 1. Append _innerPromise_ to _promises_. + 1. If _promises_ contains a Promise _P_ such that _P_.[[PromiseState]] is ~pending~, then + 1. ... + 1. Return ! SafePerformPromiseAll(...). + + 1. InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be « ». + 1. Perform BuildEvaluationList(_evaluationList_, _module_, _module_.[[RequestedModules]]). + + 1. BuildEvaluationList ( _evaluationList_, _referrer_, _moduleRequests_ ) + 1. For each ModuleRequest Record _request_ of _moduleRequests_, do + 1. Let _requiredModule_ be GetImportedModule(_referrer_, _request_.[[Specifier]]). + 1. If _request_.[[Phase]] is ~defer~, then + 1. Perform ListAppendUnique(_evaluationList_, GatherAsynchronousTransitiveDependencies(_requiredModule_)). + 1. Else if _evaluationList_ does not contain _requiredModule_, then + 1. Append _requiredModule_ to _evaluationList_. + 1. If _requiredModule_ is a Cyclic Module Record, then + 1. Let _importedNames_ be _request_.[[ImportedNames]]. + 1. ... + 1. Else, + 1. Let _optionalIndirectRequests_ be _requiredModule_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Perform BuildEvaluationList(_evaluationList_, _requiredModule_, _optionalIndirectRequests_). + + Sub-trees that are re-exported using "defer" evaluates after the module that is + re-exporting it. +flags: [module] +features: [export-defer] +includes: [compareArray.js] +---*/ + +import "../setup_FIXTURE.js"; +import { x } from "./b_FIXTURE.js"; + +assert.sameValue(x, "x-from-c", "deferred re-export `x` resolves through b to c's binding"); +globalThis.evaluations.push("a"); + +assert.compareArray( + globalThis.evaluations, + ["b", "d", "c", "a"], + "cycle through ancestor evaluates b -> d -> c -> a" +); diff --git a/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/d_FIXTURE.js b/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/d_FIXTURE.js new file mode 100644 index 00000000000..24c53ebab3b --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/cycle-through-ancestor/d_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./cycle-through-ancestor.js"; +globalThis.evaluations.push("d"); diff --git a/test/language/export/export-defer/evaluation-order/declaration-order/barrel_FIXTURE.js b/test/language/export/export-defer/evaluation-order/declaration-order/barrel_FIXTURE.js new file mode 100644 index 00000000000..decde6bb98a --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/declaration-order/barrel_FIXTURE.js @@ -0,0 +1,7 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +export defer { a } from "./dep-1_FIXTURE.js"; +export defer { b } from "./dep-2_FIXTURE.js"; +export defer { c } from "./dep-3_FIXTURE.js"; +globalThis.evaluations.push("barrel"); diff --git a/test/language/export/export-defer/evaluation-order/declaration-order/declaration-order.js b/test/language/export/export-defer/evaluation-order/declaration-order/declaration-order.js new file mode 100644 index 00000000000..d3bcdc42c60 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/declaration-order/declaration-order.js @@ -0,0 +1,65 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: Multiple deferred re-exports evaluate in declaration order +info: | + 1. Evaluate ( [ importedNames ] ) + 1. ... + 1. Else, + 1. ... + 1. Let _result_ be Completion(InnerModuleEvaluation(_module_, _stack_, 0)). + 1. ... + 1. ... + 1. Let _optionalIndirectRequests_ be _module_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Let _promises_ be « _topLevelPromise_ ». + 1. For each ModuleRequest Record _request_ of _optionalIndirectRequests_, do + 1. ... + 1. Let _innerPromise_ be _requiredModule_.Evaluate(_request_.[[ImportedNames]]). + 1. ... + 1. Append _innerPromise_ to _promises_. + 1. If _promises_ contains a Promise _P_ such that _P_.[[PromiseState]] is ~pending~, then + 1. ... + 1. Return ! SafePerformPromiseAll(...). + + 1. InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be « ». + 1. Perform BuildEvaluationList(_evaluationList_, _module_, _module_.[[RequestedModules]]). + + 1. BuildEvaluationList ( _evaluationList_, _referrer_, _moduleRequests_ ) + 1. For each ModuleRequest Record _request_ of _moduleRequests_, do + 1. Let _requiredModule_ be GetImportedModule(_referrer_, _request_.[[Specifier]]). + 1. If _request_.[[Phase]] is ~defer~, then + 1. Perform ListAppendUnique(_evaluationList_, GatherAsynchronousTransitiveDependencies(_requiredModule_)). + 1. Else if _evaluationList_ does not contain _requiredModule_, then + 1. Append _requiredModule_ to _evaluationList_. + 1. If _requiredModule_ is a Cyclic Module Record, then + 1. Let _importedNames_ be _request_.[[ImportedNames]]. + 1. ... + 1. Else, + 1. Let _optionalIndirectRequests_ be _requiredModule_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Perform BuildEvaluationList(_evaluationList_, _requiredModule_, _optionalIndirectRequests_). + + Modules that are re-exported using "defer" evaluates after the module that is + re-exporting it. Per InnerModuleEvaluation, deferred ModuleRequest Records are processed + in the order they appear in [[RequestedModules]], which mirrors the + source-code declaration order of `export defer` statements. +flags: [module] +features: [export-defer] +includes: [compareArray.js] +---*/ + +import "../setup_FIXTURE.js"; +import { a, b, c } from "./barrel_FIXTURE.js"; + +assert.sameValue(a, 1, "deferred re-export `a` resolves to dep-1's value"); +assert.sameValue(b, 2, "deferred re-export `b` resolves to dep-2's value"); +assert.sameValue(c, 3, "deferred re-export `c` resolves to dep-3's value"); + +assert.compareArray( + globalThis.evaluations, + ["barrel", "dep-1", "dep-2", "dep-3"], + "deferred re-exports evaluate in declaration order: dep-1, dep-2, dep-3" +); diff --git a/test/language/export/export-defer/evaluation-order/declaration-order/dep-1_FIXTURE.js b/test/language/export/export-defer/evaluation-order/declaration-order/dep-1_FIXTURE.js new file mode 100644 index 00000000000..18b55737a5c --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/declaration-order/dep-1_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("dep-1"); +export const a = 1; diff --git a/test/language/export/export-defer/evaluation-order/declaration-order/dep-2_FIXTURE.js b/test/language/export/export-defer/evaluation-order/declaration-order/dep-2_FIXTURE.js new file mode 100644 index 00000000000..e366d99670b --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/declaration-order/dep-2_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("dep-2"); +export const b = 2; diff --git a/test/language/export/export-defer/evaluation-order/declaration-order/dep-3_FIXTURE.js b/test/language/export/export-defer/evaluation-order/declaration-order/dep-3_FIXTURE.js new file mode 100644 index 00000000000..48ff0188f8c --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/declaration-order/dep-3_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("dep-3"); +export const c = 3; diff --git a/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/barrel_FIXTURE.js b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/barrel_FIXTURE.js new file mode 100644 index 00000000000..b3bc22d69ef --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/barrel_FIXTURE.js @@ -0,0 +1,8 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +export { e1 } from "./eager-1_FIXTURE.js"; +export defer { d1 } from "./deferred-1_FIXTURE.js"; +export { e2 } from "./eager-2_FIXTURE.js"; +export defer { d2 } from "./deferred-2_FIXTURE.js"; +globalThis.evaluations.push("barrel"); diff --git a/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/deferred-1_FIXTURE.js b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/deferred-1_FIXTURE.js new file mode 100644 index 00000000000..41477ae972d --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/deferred-1_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("deferred-1"); +export const d1 = "deferred-1-value"; diff --git a/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/deferred-2_FIXTURE.js b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/deferred-2_FIXTURE.js new file mode 100644 index 00000000000..5ee5a576ce4 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/deferred-2_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("deferred-2"); +export const d2 = "deferred-2-value"; diff --git a/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/eager-1_FIXTURE.js b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/eager-1_FIXTURE.js new file mode 100644 index 00000000000..3175a8efb03 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/eager-1_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("eager-1"); +export const e1 = "eager-1-value"; diff --git a/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/eager-2_FIXTURE.js b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/eager-2_FIXTURE.js new file mode 100644 index 00000000000..7cea22019a5 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/eager-2_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("eager-2"); +export const e2 = "eager-2-value"; diff --git a/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/multiple-deferred-mixed-with-eager.js b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/multiple-deferred-mixed-with-eager.js new file mode 100644 index 00000000000..154eda5ccea --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/multiple-deferred-mixed-with-eager/multiple-deferred-mixed-with-eager.js @@ -0,0 +1,66 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: Interleaved eager and deferred re-exports respect declaration order across the eager-then-deferred phases +info: | + 1. Evaluate ( [ importedNames ] ) + 1. ... + 1. Else, + 1. ... + 1. Let _result_ be Completion(InnerModuleEvaluation(_module_, _stack_, 0)). + 1. ... + 1. ... + 1. Let _optionalIndirectRequests_ be _module_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Let _promises_ be « _topLevelPromise_ ». + 1. For each ModuleRequest Record _request_ of _optionalIndirectRequests_, do + 1. ... + 1. Let _innerPromise_ be _requiredModule_.Evaluate(_request_.[[ImportedNames]]). + 1. ... + 1. Append _innerPromise_ to _promises_. + 1. If _promises_ contains a Promise _P_ such that _P_.[[PromiseState]] is ~pending~, then + 1. ... + 1. Return ! SafePerformPromiseAll(...). + + 1. InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be « ». + 1. Perform BuildEvaluationList(_evaluationList_, _module_, _module_.[[RequestedModules]]). + + 1. BuildEvaluationList ( _evaluationList_, _referrer_, _moduleRequests_ ) + 1. For each ModuleRequest Record _request_ of _moduleRequests_, do + 1. Let _requiredModule_ be GetImportedModule(_referrer_, _request_.[[Specifier]]). + 1. If _request_.[[Phase]] is ~defer~, then + 1. Perform ListAppendUnique(_evaluationList_, GatherAsynchronousTransitiveDependencies(_requiredModule_)). + 1. Else if _evaluationList_ does not contain _requiredModule_, then + 1. Append _requiredModule_ to _evaluationList_. + 1. If _requiredModule_ is a Cyclic Module Record, then + 1. Let _importedNames_ be _request_.[[ImportedNames]]. + 1. ... + 1. Else, + 1. Let _optionalIndirectRequests_ be _requiredModule_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Perform BuildEvaluationList(_evaluationList_, _requiredModule_, _optionalIndirectRequests_). + + Modules that are re-exported using "defer" evaluates after the module that is + re-exporting it. Per InnerModuleEvaluation, deferred ModuleRequest Records are processed + in the order they appear in [[RequestedModules]], which mirrors the + source-code declaration order of `export defer` statements. +flags: [module] +features: [export-defer] +includes: [compareArray.js] +---*/ + +import "../setup_FIXTURE.js"; +import { e1, d1, e2, d2 } from "./barrel_FIXTURE.js"; + +assert.sameValue(e1, "eager-1-value", "eager re-export `e1` resolves to eager-1's value"); +assert.sameValue(d1, "deferred-1-value", "deferred re-export `d1` resolves to deferred-1's value"); +assert.sameValue(e2, "eager-2-value", "eager re-export `e2` resolves to eager-2's value"); +assert.sameValue(d2, "deferred-2-value", "deferred re-export `d2` resolves to deferred-2's value"); + +assert.compareArray( + globalThis.evaluations, + ["eager-1", "eager-2", "barrel", "deferred-1", "deferred-2"], + "eager re-exports evaluate first in declaration order; barrel; then deferred in declaration order" +); diff --git a/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/barrel_FIXTURE.js b/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/barrel_FIXTURE.js new file mode 100644 index 00000000000..bb4457c68af --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/barrel_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +export { x } from "./eager-dep_FIXTURE.js"; +export defer { y } from "./defer-dep_FIXTURE.js"; +globalThis.evaluations.push("barrel"); diff --git a/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/defer-dep_FIXTURE.js b/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/defer-dep_FIXTURE.js new file mode 100644 index 00000000000..237968b6942 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/defer-dep_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("defer-dep"); +export const y = 2; diff --git a/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/eager-dep_FIXTURE.js b/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/eager-dep_FIXTURE.js new file mode 100644 index 00000000000..1afa7d4c350 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/eager-dep_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("eager-dep"); +export const x = 1; diff --git a/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/non-deferred-before-deferred-after.js b/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/non-deferred-before-deferred-after.js new file mode 100644 index 00000000000..977a499548b --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/non-deferred-before-deferred-after/non-deferred-before-deferred-after.js @@ -0,0 +1,62 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: Non-deferred re-exports evaluate before the re-exporter; deferred re-exports evaluate after +info: | + 1. Evaluate ( [ importedNames ] ) + 1. ... + 1. Else, + 1. ... + 1. Let _result_ be Completion(InnerModuleEvaluation(_module_, _stack_, 0)). + 1. ... + 1. ... + 1. Let _optionalIndirectRequests_ be _module_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Let _promises_ be « _topLevelPromise_ ». + 1. For each ModuleRequest Record _request_ of _optionalIndirectRequests_, do + 1. ... + 1. Let _innerPromise_ be _requiredModule_.Evaluate(_request_.[[ImportedNames]]). + 1. ... + 1. Append _innerPromise_ to _promises_. + 1. If _promises_ contains a Promise _P_ such that _P_.[[PromiseState]] is ~pending~, then + 1. ... + 1. Return ! SafePerformPromiseAll(...). + + 1. InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be « ». + 1. Perform BuildEvaluationList(_evaluationList_, _module_, _module_.[[RequestedModules]]). + + 1. BuildEvaluationList ( _evaluationList_, _referrer_, _moduleRequests_ ) + 1. For each ModuleRequest Record _request_ of _moduleRequests_, do + 1. Let _requiredModule_ be GetImportedModule(_referrer_, _request_.[[Specifier]]). + 1. If _request_.[[Phase]] is ~defer~, then + 1. Perform ListAppendUnique(_evaluationList_, GatherAsynchronousTransitiveDependencies(_requiredModule_)). + 1. Else if _evaluationList_ does not contain _requiredModule_, then + 1. Append _requiredModule_ to _evaluationList_. + 1. If _requiredModule_ is a Cyclic Module Record, then + 1. Let _importedNames_ be _request_.[[ImportedNames]]. + 1. ... + 1. Else, + 1. Let _optionalIndirectRequests_ be _requiredModule_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Perform BuildEvaluationList(_evaluationList_, _requiredModule_, _optionalIndirectRequests_). + +flags: [module] +features: [export-defer] +includes: [compareArray.js] +---*/ + +import "../setup_FIXTURE.js"; +import { x, y } from "./barrel_FIXTURE.js"; + +globalThis.evaluations.push("entrypoint"); + +assert.sameValue(x, 1, "eager re-export `x` resolves to eager-dep's value"); +assert.sameValue(y, 2, "deferred re-export `y` resolves to defer-dep's value"); + +assert.compareArray( + globalThis.evaluations, + ["eager-dep", "barrel", "defer-dep", "entrypoint"], + "non-deferred dep evaluates before barrel; deferred dep evaluates after barrel and before entrypoint completes" +); diff --git a/test/language/export/export-defer/evaluation-order/same-source-barrel_FIXTURE.js b/test/language/export/export-defer/evaluation-order/same-source-barrel_FIXTURE.js new file mode 100644 index 00000000000..6638519df0e --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/same-source-barrel_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +export defer { x } from "./same-source-dep_FIXTURE.js"; +export { y } from "./same-source-dep_FIXTURE.js"; +globalThis.evaluations.push("same-source-barrel"); diff --git a/test/language/export/export-defer/evaluation-order/same-source-dep_FIXTURE.js b/test/language/export/export-defer/evaluation-order/same-source-dep_FIXTURE.js new file mode 100644 index 00000000000..085d686da7b --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/same-source-dep_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("same-source-dep"); +export const x = "deferred-x"; +export const y = "eager-y"; diff --git a/test/language/export/export-defer/evaluation-order/same-source-eager-and-deferred.js b/test/language/export/export-defer/evaluation-order/same-source-eager-and-deferred.js new file mode 100644 index 00000000000..a069df50238 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/same-source-eager-and-deferred.js @@ -0,0 +1,64 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: A re-exporter using both `export defer { x }` and `export { y }` against the same source evaluates the source once, with the eager re-export controlling order +info: | + 1. Evaluate ( [ importedNames ] ) + 1. ... + 1. Else, + 1. ... + 1. Let _result_ be Completion(InnerModuleEvaluation(_module_, _stack_, 0)). + 1. ... + 1. ... + 1. Let _optionalIndirectRequests_ be _module_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Let _promises_ be « _topLevelPromise_ ». + 1. For each ModuleRequest Record _request_ of _optionalIndirectRequests_, do + 1. ... + 1. Let _innerPromise_ be _requiredModule_.Evaluate(_request_.[[ImportedNames]]). + 1. ... + 1. Append _innerPromise_ to _promises_. + 1. If _promises_ contains a Promise _P_ such that _P_.[[PromiseState]] is ~pending~, then + 1. ... + 1. Return ! SafePerformPromiseAll(...). + + 1. InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be « ». + 1. Perform BuildEvaluationList(_evaluationList_, _module_, _module_.[[RequestedModules]]). + + 1. BuildEvaluationList ( _evaluationList_, _referrer_, _moduleRequests_ ) + 1. For each ModuleRequest Record _request_ of _moduleRequests_, do + 1. Let _requiredModule_ be GetImportedModule(_referrer_, _request_.[[Specifier]]). + 1. If _request_.[[Phase]] is ~defer~, then + 1. Perform ListAppendUnique(_evaluationList_, GatherAsynchronousTransitiveDependencies(_requiredModule_)). + 1. Else if _evaluationList_ does not contain _requiredModule_, then + 1. Append _requiredModule_ to _evaluationList_. + 1. If _requiredModule_ is a Cyclic Module Record, then + 1. Let _importedNames_ be _request_.[[ImportedNames]]. + 1. ... + 1. Else, + 1. Let _optionalIndirectRequests_ be _requiredModule_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Perform BuildEvaluationList(_evaluationList_, _requiredModule_, _optionalIndirectRequests_). + + When the same module appears in both an eager and a deferred ModuleRequest + for a re-exporter, the eager request causes the source to evaluate before + the re-exporter's body. The deferred request adds no additional evaluation + because the source is already evaluated. +flags: [module] +features: [export-defer] +includes: [compareArray.js] +---*/ + +import "./setup_FIXTURE.js"; +import { x, y } from "./same-source-barrel_FIXTURE.js"; + +assert.sameValue(x, "deferred-x", "deferred re-export `x` resolves to the shared source's value"); +assert.sameValue(y, "eager-y", "eager re-export `y` resolves to the shared source's value"); + +assert.compareArray( + globalThis.evaluations, + ["same-source-dep", "same-source-barrel"], + "the shared source evaluates exactly once; eager `export { y }` controls placement" +); diff --git a/test/language/export/export-defer/evaluation-order/setup_FIXTURE.js b/test/language/export/export-defer/evaluation-order/setup_FIXTURE.js new file mode 100644 index 00000000000..c72aabeac21 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/setup_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations = []; diff --git a/test/language/export/export-defer/evaluation-order/tla-async-dep_FIXTURE.js b/test/language/export/export-defer/evaluation-order/tla-async-dep_FIXTURE.js new file mode 100644 index 00000000000..ef855605169 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/tla-async-dep_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("tla-async-dep"); +await null; +export const x = "tla-x"; diff --git a/test/language/export/export-defer/evaluation-order/tla-barrel_FIXTURE.js b/test/language/export/export-defer/evaluation-order/tla-barrel_FIXTURE.js new file mode 100644 index 00000000000..f849bc740cf --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/tla-barrel_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +export defer { x } from "./tla-async-dep_FIXTURE.js"; +globalThis.evaluations.push("tla-barrel"); diff --git a/test/language/export/export-defer/evaluation-order/tla-deferred-source.js b/test/language/export/export-defer/evaluation-order/tla-deferred-source.js new file mode 100644 index 00000000000..f768581ae74 --- /dev/null +++ b/test/language/export/export-defer/evaluation-order/tla-deferred-source.js @@ -0,0 +1,65 @@ +// Copyright (C) 2026 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-GatherAsynchronousTransitiveDependenciesForRequests +description: A deferred re-export whose source uses top-level await is gathered into the async dependency graph and resolved before the entrypoint accesses it +info: | + 1. Evaluate ( [ importedNames ] ) + 1. ... + 1. Else, + 1. ... + 1. Let _result_ be Completion(InnerModuleEvaluation(_module_, _stack_, 0)). + 1. ... + 1. ... + 1. Let _optionalIndirectRequests_ be _module_.GetOptionalIndirectExportsModuleRequests(_importedNames_). + 1. Let _promises_ be « _topLevelPromise_ ». + 1. For each ModuleRequest Record _request_ of _optionalIndirectRequests_, do + 1. ... + 1. Let _innerPromise_ be _requiredModule_.Evaluate(_request_.[[ImportedNames]]). + 1. ... + 1. Append _innerPromise_ to _promises_. + 1. If _promises_ contains a Promise _P_ such that _P_.[[PromiseState]] is ~pending~, then + 1. ... + 1. Return ! SafePerformPromiseAll(...). + + 1. InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be « ». + 1. Perform BuildEvaluationList(_evaluationList_, _module_, _module_.[[RequestedModules]]). + + 1. BuildEvaluationList ( _evaluationList_, _referrer_, _moduleRequests_ ) + 1. For each ModuleRequest Record _request_ of _moduleRequests_, do + 1. Let _requiredModule_ be GetImportedModule(_referrer_, _request_.[[Specifier]]). + 1. If _request_.[[Phase]] is ~defer~, then + 1. Perform ListAppendUnique(_evaluationList_, GatherAsynchronousTransitiveDependencies(_requiredModule_)). + 1. Else if _evaluationList_ does not contain _requiredModule_, then + 1. Append _requiredModule_ to _evaluationList_. + 1. If _requiredModule_ is a Cyclic Module Record, then + 1. Let _importedNames_ be _request_.[[ImportedNames]]. + 1. If importedNames = all, then + 1. Let allOptionalIndirectRequests be requiredModule.GetOptionalIndirectExportsModuleRequests(importedNames). + 1. Let seen be a new empty List. + 1. 3. Perform ListAppendUnique(evaluationList, GatherAsynchronousTransitiveDependenciesForRequests(requiredModule, allOptionalIndirectRequests, seen)). + 1. Else, + 1. ... + + GatherAsynchronousTransitiveDependenciesForRequests collects async + dependencies through deferred ModuleRequest Records when they would be + forced by ImportedNames, which is ~all~ in this case. +flags: [module, async] +features: [export-defer, top-level-await] +includes: [asyncHelpers.js, compareArray.js] +---*/ + +import "./setup_FIXTURE.js"; + +asyncTest(async () => { + const ns = await import("./tla-barrel_FIXTURE.js"); + assert.sameValue(ns.x, "tla-x", "deferred re-export `x` resolves to the TLA source's value"); + assert.compareArray( + globalThis.evaluations, + ["tla-barrel", "tla-async-dep"], + "TLA source of a deferred re-export evaluates after the barrel body but completes before namespace access returns" + ); +});