|
3 | 3 | Tracking notes for the current top-level `await` bring-up. Use this as a scratchpad while iterating (similar spirit to `docs/fix-assignment-destructuring-evaluation-order.md`). |
4 | 4 |
|
5 | 5 | ## What changed this round |
6 | | -- Async modules now predeclare exports with `AsyncExportBinding` placeholders. The placeholder wraps a realm-scoped `JsPromise` and swaps to the resolved value once set. Export hoisting (`PredeclareExportNames`) creates these promise-backed bindings so imports observe the eventual value instead of `undefined`. |
7 | | -- Module evaluation for async modules runs asynchronously: `EvaluateModuleBodyWithTopLevelAwait` awaits async dependencies, then executes the body on a background task and records the promise on the module entry. |
8 | | -- Await semantics were aligned with the realm Promise prototype. Await wraps non-promise values via `Promise.resolve` (using the realm constructor/prototype) before driving through the shared scheduler. |
9 | | -- Module path normalization regained “keep it relative” behavior for harness loaders. With a module loader present we normalize relative to the referrer directory without stripping the `/language/...` prefix. |
10 | | -- Import evaluation now temporarily detaches the current microtask queue when waiting on an async dependency and prepends the preserved microtasks afterwards. This prevents caller-queued ticks from running while we synchronously block on the imported module. |
| 6 | +- Async dependencies still start evaluation immediately, but async parents are now drained before executing the importing module body so DFS completion ordering and import bindings stay deterministic. |
| 7 | +- Blocking waits on async imports detach and restore the caller microtask queue, and microtask enqueue/drain now run under a lock to avoid cross-thread races. |
11 | 8 |
|
12 | | -## Current failing ModuleCode_topLevelAwait tests |
13 | | -Run: `dotnet test tests/Asynkron.JsEngine.Tests.Test262/Asynkron.JsEngine.Tests.Test262.csproj --filter "ModuleCode_topLevelAwait" --logger "console;verbosity=minimal"` |
14 | | - |
15 | | -- `language/module-code/top-level-await/await-dynamic-import-resolution.js` (strict) |
16 | | - - Still throws `Module not found: module-import-resolution_FIXTURE.js`. |
17 | | - - Normalization now yields `language/module-code/top-level-await/module-import-resolution_FIXTURE.js`, but the loader lookup still fails (likely a mismatch between normalized key and Test262Stream lookup). |
18 | | -- `language/module-code/top-level-await/module-graphs-does-not-hang.js` (strict) |
19 | | - - Throws `Module not found: module-graphs-grandparent-tla_FIXTURE.js`. |
20 | | - - Same symptom as above; needs loader path investigation. |
21 | | -- `language/module-code/top-level-await/async-module-does-not-block-sibling-modules.js` (strict) |
22 | | - - Assertion fails: `check` was `false` (the async sibling ticked earlier than expected). Indicates we’re still draining microtasks from the importing module while awaiting an async dependency; the preserved microtask approach didn’t fully isolate the tick ordering. |
23 | | -- `language/module-code/top-level-await/dfs-invariant.js` (strict) |
24 | | - - `globalThis.test262` stayed `undefined`; ordering of async parent completion remains off (likely same microtask/drain ordering issue). |
| 9 | +## Current status |
| 10 | +- `ModuleCode_topLevelAwait` is green (strict and sloppy). |
25 | 11 |
|
26 | 12 | ## Next steps |
27 | | -1) Module loader resolution: confirm the exact specifier strings passed to `SetModuleLoader` for dynamic import and nested TLA graphs. Add temporary logging or reproduce via a tiny harness to see why `Test262Stream.GetTestFile` misses `module-import-resolution_FIXTURE.js` and `module-graphs-grandparent-tla_FIXTURE.js`. |
28 | | -2) Microtask ordering: prevent caller-queued microtasks from running while a sync import waits on an async dependency. The current detach/restore works only for `EvaluateImport`; promise draining elsewhere (e.g., `AwaitScheduler` loops) still runs the caller’s microtasks. Investigate a dedicated “await while preserving existing queue” path or defer draining until after dependency resolution. |
29 | | -3) Re-run `ModuleCode_topLevelAwait` after fixes and update this file. |
| 13 | +- Keep an eye on parallel runner behaviour; top-level await still expects deterministic microtask draining while async parents settle. |
0 commit comments