fw-04 — Analysis

The generating constraint

A call stack cannot be paused, inspected, resumed, or duplicated.

Interruptible rendering needs all four, so the stack must become a heap data structure you own. The return (parent) pointer in a Fiber is the direct artefact: a recursive traversal never needs one, because the stack provides it.

Required invariants

  1. Render work is discardable, therefore side-effect free.
  2. Commit is atomic — exactly one continuation may touch the DOM.
  3. A new update makes in-flight work stale. Continuing it commits a tree where some components saw old state and some saw new: tearing.
  4. Two trees exist during render — current and work-in-progress.
  5. Higher priority abandons lower-priority in-progress work, which is only legal because of (1).

Invariants 1 and 2 are two statements of one requirement: discardable work must have done nothing, and output must be applied all at once.

The bug this module's spec caught

The reference implementation used to validate the spec failed the last test. Its scheduler treated a same-priority update arriving mid-render as "keep going," so a render half-finished with n = 1 continued after state became 2, and the commit mixed both.

The fix is one line of policy: any new update discards in-flight work and restarts. You are likely to write the same bug; the test will catch it.

This is the framework-level form of the defect useSyncExternalStore prevents at application level.

Does time-slicing help?

Helps whenDoes not help when
work is long (tens of ms)the long task is an effect or layout read
work is in the render phasetotal work is small; overhead dominates
there is higher-priority work to yield tothe real fix is doing less work

"Concurrent React fixes our INP" is true only when input delay comes from long render phases. The single diagnostic question is: is the long task a render, or something else? A LoAF scripts[] breakdown answers it in one recording.