tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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);