CHAPTER 10 – How HTML Works
Checking engine…

10.2 — The HTML Parser, Interlocking & Fault Tolerance

The real‑world web is messy. Network packets arrive in bursts, stylesheets and scripts fight for the main thread, and decades of legacy markup are riddled with errors. The HTML parser meets this chaos with three superpowers: incremental streaming, execution interlocking, and deterministic error recovery.

Streaming Parsing – Building the DOM in Chunks

Unlike a traditional compiler that expects a complete file in memory, the HTML parser begins work the moment the first network packet arrives. Raw bytes flow into the tokenizer while the server is still sending data. The parser processes a chunk, builds part of the DOM tree, then pauses if it runs out of input – resuming exactly where it left off when the next packet arrives.

This incremental architecture dramatically reduces the time to first paint, but it also means the tokenizer and tree constructor must be capable of operating on incomplete document fragments at any moment.

Diagram showing network packets arriving in chunks, parser building DOM tree incrementally
Figure 10.6: The streaming parser constructs the DOM as packets arrive, never waiting for the full document.

The Style‑Script Interlock

When the HTML parser encounters a synchronous <script>, it must stop. But if the script appears after a stylesheet, an even stricter rule kicks in: the script cannot execute until all pending CSS is fully downloaded and the CSS Object Model (CSSOM) is built.

Why? JavaScript can query an element’s computed styles. If the stylesheet hadn’t been applied, the script would receive stale or non‑existent data – a catastrophic race condition. The browser enforces a strict dependency chain:

  • Parser is blocked by <script>.
  • <script> execution is blocked by pending CSS.
  • The main thread remains suspended until the CSSOM is ready, guaranteeing deterministic behaviour for the script.
Diagram illustrating parser blocked by script, script blocked by pending stylesheet
Figure 10.7: The style‑script interlock – scripts cannot run before CSS is fully parsed.

Error Recovery – The Adoption Agency Algorithm

Mis‑nested inline formatting tags (e.g., <b>...<i>...</b>...</i>) are one of the most common authoring mistakes. A naive parser would create a tangled, invalid DOM. The HTML tree constructor uses the adoption agency algorithm to repair this seamlessly.

The algorithm maintains a list of active formatting elements. When it detects an overlap, it unwinds the stack of open elements, isolates the mis‑nested tags, clones the necessary formatting nodes, and re‑parents the text beneath them. The result is a perfectly valid, well‑nested tree – and the visual rendering remains correct.

Diagram showing mis-nested tags being fixed by the adoption agency algorithm
Figure 10.8: The adoption agency algorithm repairs overlapping inline tags into a clean hierarchy.

Error Recovery – Foster Parenting

A second extreme case is when text or block elements are placed directly inside a <table> but outside any <td> or <th>. A strict XML parser would reject this outright. The HTML parser uses foster parenting: it searches backward through the stack of open elements, finds the table’s context, and moves the stray node before the table in the DOM.

This ensures the visual table layout remains intact, while the illegal content is still preserved and rendered – it is never discarded. The web’s supreme directive is never to break existing content, and foster parenting is one of the mechanisms that upholds that promise.

Diagram showing stray content being moved outside a table via foster parenting
Figure 10.9: Foster parenting – stray nodes inside a table are hoisted outside the table structure.
TAKEAWAY

The HTML parser is not a rigid compiler – it is a resilient, streaming engine. It builds the DOM incrementally from network packets, enforces a strict execution order between scripts and stylesheets, and applies deterministic algorithms like the adoption agency and foster parenting to repair broken markup. This fault tolerance is the bedrock of the web’s backward compatibility, ensuring that even the oldest, most chaotic pages still render correctly today.

Checking engine…