Execution — bi-07-css-engine

Steps extracted from CONCEPTS.md. Read the concepts first; this file is the doing.

Record results in observation.md; tick checkpoints in verification.md.


6. Lab — mini-browser M4–M6

Build a CSS engine supporting div {}, .foo {}, #header {}, .parent .child {}.

  1. Tokenizer + parser producing a rule list.
  2. Selector representation and right-to-left matching.
  3. Specificity, cascade, inheritance, computed style.
  4. Deliberately naive first: on any DOM change, recompute every element's style. Measure on a 10,000-node tree.
  5. Then build an index. Bucket rules by key selector. Measure again.
  6. Then build invalidation sets. On classList.add(x), consult a precomputed map from class → affected-descendant descriptors. Measure again.
  7. Add a selector your analysis cannot handle precisely (a sibling combinator). Implement the subtree fallback. Measure the cliff.

Deliverable: a table of recalculated-element counts and wall time for stages 4, 5, 6 and 7, plus a written explanation of where each speedup came from. Stage 7 is the point of the lab — you must be able to state exactly which selector shapes cost you precision.


7. Failure Lab

  1. Invalidate too little. Deliberately omit sibling invalidation. Construct markup that renders incorrectly. This is the bug class the complexity exists to prevent.
  2. Invalidate too much. Fall back to whole-document invalidation always. Show it is correct and unusable.
  3. Style-sharing defeat. Add a unique inline style to every row of a 10,000-row list. Measure memory and recalc time against the shared version.
  4. The container-query cycle. Construct a case where an element's style depends on a container's size, which depends on that element's size. Predict the outcome, then check what real browsers do and find the rule that breaks the cycle.

8. Debugging Exercise

  1. DevTools → Performance: capture a classList.add that triggers recalc. Find the number of elements affected. Find where DevTools reports it.
  2. Construct two changes with identical visual effect but 100× different recalc scope. Explain the difference by selector shape alone.
  3. Trace with the blink category and locate style-recalc trace events. Correlate one back to source by grepping its literal event name (bi-01, rung 3 → rung 1).
  4. Find, in the local checkout, the code path that decides to fall back to subtree invalidation. Write down the exact condition.