unobservable-global-async-evaluation-count-reset.js (3485B)
1 // |reftest| module async 2 // Copyright (C) 2025 Igalia, S.L. All rights reserved. 3 // This code is governed by the BSD license found in the LICENSE file. 4 5 /*--- 6 description: > 7 An implementation may unobservably reset [[ModuleAsyncEvaluationCount]] to 0 8 whenever there are no pending modules. 9 info: | 10 IncrementModuleAsyncEvaluationCount ( ) 11 1. Let AR be the Agent Record of the surrounding agent. 12 2. Let count be AR.[[ModuleAsyncEvaluationCount]]. 13 3. Set AR.[[ModuleAsyncEvaluationCount]] to count + 1. 14 4. Return count. 15 16 NOTE: This value is only used to keep track of the relative evaluation order 17 between pending modules. An implementation may unobservably reset 18 [[ModuleAsyncEvaluationCount]] to 0 whenever there are no pending modules. 19 20 InnerModuleEvaluation ( module, stack, index ) 21 ... 22 12. If module.[[PendingAsyncDependencies]] > 0 or module.[[HasTLA]] is true, then 23 a. Assert: module.[[AsyncEvaluationOrder]] is unset. 24 b. Set module.[[AsyncEvaluationOrder]] to IncrementModuleAsyncEvaluationCount(). 25 ... 26 27 AsyncModuleExecutionFulfilled ( module ) 28 ... 29 9. Perform GatherAvailableAncestors(module, execList). 30 10. ... 31 11. Let sortedExecList be a List whose elements are the elements of execList, sorted by their [[AsyncEvaluationOrder]] field in ascending order. 32 12. For each Cyclic Module Record m of sortedExecList, do 33 a. If m.[[Status]] is evaluated, then 34 i. Assert: m.[[EvaluationError]] is not empty. 35 b. Else if m.[[HasTLA]] is true, then 36 i. Perform ExecuteAsyncModule(m). 37 c. Else, 38 i. Let result be m.ExecuteModule(). 39 ... 40 41 Module graph (the order of dependencies in each module is important, and it's left-to-right): 42 ┌─────┐ ┌─────┐ ┌─────┐ 43 │ A │ │ C │ │ D │ 44 └─────┘ └─────┘ └─────┘ 45 │ │ │ 46 │ ▼ │ 47 │ ┌─────┐ │ 48 │ │ E │ │ 49 │ └─────┘ │ 50 │ ┌──────────────────┘ 51 ▼ ▼ 52 ┌───────┐ 53 │ B │ 54 └───────┘ 55 56 Where B and C have top-level await. The test orchestrates the evaluation order such that: 57 - Import A first 58 - Once B starts evaluating, import C and immediately resolve its top-level await 59 - Once C finishes evaluating, import D 60 - Once E is evaluated, resolve B's await 61 62 esid: sec-IncrementModuleAsyncEvaluationCount 63 flags: [module, async] 64 features: [top-level-await, dynamic-import, promise-with-resolvers] 65 includes: [compareArray.js] 66 ---*/ 67 68 import { logs, pB, pB_start, pE_start } from "./unobservable-global-async-evaluation-count-reset-setup_FIXTURE.js"; 69 70 const pA = import("./unobservable-global-async-evaluation-count-reset-a_FIXTURE.js"); 71 let pD; 72 73 pB_start.promise.then(() => { 74 return import("./unobservable-global-async-evaluation-count-reset-c_FIXTURE.js"); 75 }).then(() => { 76 pD = import("./unobservable-global-async-evaluation-count-reset-d_FIXTURE.js"); 77 return pE_start.promise; 78 }).then(() => { 79 pB.resolve(); 80 return Promise.all([pA, pD]); 81 }).then(() => { 82 assert.compareArray(logs, ["A", "D"], "A should evaluate before D"); 83 }).then($DONE, $DONE);