Observation — Foster Parenting (fill this in; do NOT open docs/answer-key.md until §8 is done)
Started: Finished:
Step 1 — Predictions (write BEFORE running anything)
Case A — <table>hello<div>world</div></table>
body
...
table.parentNode =
table.childNodes.length =
Case B — <table><input type="hidden" name="a"><input type="text" name="b"></table>
body
...
table.parentNode =
table.childNodes.length =
Case C — multiline (exact whitespace)
body
...
Total text nodes in the body subtree:
Does <table> have any children?
Case D — <table><tr><td>a</td></tr></table>
body
...
Element present in the DOM that was never written in the source: Spec rule that creates it:
Step 2 — Observed
| Case | Prediction | Verdict (exact / structural / wrong) | What I got wrong |
|---|---|---|---|
| A | |||
| B | |||
| C | |||
| D |
Step 3 — Spec
Insertion mode active inside <table>:
Character sub-mode, and why it exists separately:
Algorithm that relocates the node:
Case B exception — quote the sentence:
Per-case spec sentences:
- A:
- B:
- C:
- D:
Step 4 — Blink implementation
| What | Name found | Search query that found it |
|---|---|---|
| Relocation function | ||
| Owning class | ||
| Predicate deciding relocation | ||
| Insertion-site locator | ||
| Case B predicate | ||
| Start-tag handler for in-table |
Callers (from the xref panel): Callees:
CL that introduced the Case B exception (link + one-line summary of its message):
Step 5 — Tests
| Kind | Path | What it catches that the others do not |
|---|---|---|
| C++ unit test | ||
| Blink web test | ||
| WPT |
Step 6 — foster.js
Passes A / B / D: Attempted C: What writing it taught me that reading could not:
Step 7 — Breakages
- Remove relocation entirely → First test to fail:
- Remove the Case B exception → First test to fail:
- Remove the character sub-mode (insert chars immediately) → First test to fail: Why is the batching load-bearing rather than an optimization?
Diffs observed in my own foster.js under the same three mutations:
Step 8 — The gate (§44)
-
Why does this code exist?
-
What invariant does it maintain?
-
Who calls it?
-
What does it call?
-
Which process and thread executes it? (is the answer always the same one?)
-
What happens if it is removed?
-
How is it tested?
-
What simpler design would fail, and why?
Complexity notebook entry #1 — HTML parser insertion modes
Observed complexity:
My simpler design:
What requirement breaks my design:
Production constraint:
Resulting architecture:
Essential architecture, or accreted complexity? (defend it)