Methodology
This site makes specific claims about the order in which JavaScript runs. Here is how those claims are checked, what the animations deliberately simplify, and what to do when something looks wrong.
Every output is executed, not asserted
Each case ships three independent artefacts: the code snippet, a hand-authored execution trace, and a set of multiple-choice answers. A validation script runs on every commit and checks all three against each other by actually executing the snippet and capturing the real console output.
real console output === trace's final console state === the answer marked correct If any of the three disagree, the build fails. Currently 13 cases and 17 experiments — 621 execution steps — pass this check. This has already caught real mistakes, including one where the validator itself was wrong.
What CI does and does not prove
The validator runs in Node.js. That is what the "CI verified" line on each case refers to, and it is the only automated claim made anywhere on this site.
No case is executed in a real browser by CI. Browser-specific behaviour — the rendering step, frame timing, network transport — follows the HTML Standard and the references listed on each page. Where a browser-only API is involved, the case says so and names the substitution used. If a page ever claims a browser version was checked, it means a human checked it.
The invocation context is part of the answer
Snippets are started from a fresh macrotask, which matches a browser
<script>
and a Node CommonJS module body. ES modules are evaluated as a module job — inside a microtask —
so cases about ESM are run that way instead.
This is not a technicality. The same Node file prints
nextTick
before or after a promise depending on whether it is loaded as
.cjs or
.mjs.
Every Node case here states its module system explicitly.
Where the code is stubbed, and where it is not
Two APIs cannot run truthfully in a test process: fetch
would hit the network, and requestAnimationFrame
does not exist outside a browser. Those cases supply a small stub used
only during validation; the code shown on the page is real.
The rule the stubs follow: a stub may replace a mechanism, never an ordering. The fetch stub still resolves in two stages, headers then body, because that separation is the lesson. If a case could not be checked without deciding its own answer, it would not belong here.
What the animations simplify
The panels are a teaching model, not a picture of engine internals. Specifically:
- Browsers maintain several task queues (timers, user interaction, networking) and may choose between them. The single "Task Queue" panel collapses that into one lane.
- "Web APIs" stands in for a large amount of host machinery — timer threads, the network stack, the compositor — none of which is JavaScript.
- Steps are discrete for teaching. Real execution has no pause between pushing a frame and running it, and engines reorder and optimise aggressively.
- Timings shown for network and frame boundaries are illustrative. Only the relative order is guaranteed.
What is accurate is the observable behaviour: the order in which your code runs and your output appears. That is the thing the validator enforces.
Terminology
The HTML standard defines tasks and microtasks. The word "macrotask" is community shorthand for an ordinary task and does not appear in any specification — it is used here only where it aids recognition, with the spec term alongside. Similarly, "Web APIs" is a teaching label, not a spec concept.
Found a mistake?
Corrections are welcome and taken seriously — a teaching tool that is subtly wrong is worse than no tool. The most useful report includes the case, the runtime and version you observed, and the output you got. Every page carries the exact runtime it was verified against and the date it was last reviewed, so you can tell whether a claim has simply gone stale.
Prefer to see it rather than read about it? Start with a case →