HTML Parsing & Script Loading
Bytes to tokens to a tree, streaming as it arrives — and what `script`, `defer`, `async` and `type=module` actually do to that stream.
Bytes become characters become tokens, through a specified state machine that has no fatal errors and that the tree builder can reach in and reconfigure.
Tokens become a DOM through insertion modes and a stack of open elements — which is why the tree the browser built is frequently not the markup you wrote.
The parser starts on the first chunk and never waits for the last one — which makes time to first byte, flush behaviour and document order performance decisions rather than server details.
A classic `<script>` suspends tree construction because the script may write into the document at that exact point — and it also waits for pending stylesheets it may never touch.
Three genuinely different orderings: `defer` keeps document order and runs before DOMContentLoaded, `async` runs whenever it arrives with no order guarantee, and modules are deferred by default.
A second, lightweight reader runs ahead of the real parser looking for URLs to fetch — and almost every modern loading pattern accidentally hides resources from it.