textarea (the audit-CONFIRMED violation): measureAutosize wrote
height:auto then synchronously read scrollHeight + getComputedStyle — a
forced reflow on EVERY keystroke (input / clear / mount). The read block
now defers through the context ActiveDom's dom.measure: write stays in
the event turn, the read runs post-layout in the coalesced pre-paint
frame (typing bursts coalesce to one measurement; stale pending reads
cancel), and the clamped height is written back inside the frame
(read->write, no mid-turn reflow). Verified live: style.height is 'auto'
synchronously after input (the old code showed px immediately) and the
grown px lands next frame.
Directed census over the audit candidates, violations fixed:
- scroll-area: the thumb's size/offset getters read the track's
clientWidth/Height inside the thumb props $derived — a forced reflow
per scroll tick. The scrollbar now mirrors its track size into $state
fed by a ResizeObserver; thumb math + drag read the mirrors. The
initial viewport measurement defers through dom.measure.
- virtual-list (both viewports) / virtual-grid: the initial
updateSize/updateScroll ran sync at ref-attach right after DOM
insertion — deferred through dom.measure (observers keep them fresh).
- carousel: the mount seed defers through dom.measure (lands pre-paint,
before any interaction), which closes the async-observer gap the
viewportSize $derived's live clientWidth fallback guarded — that
fallback (a render-time layout read) is removed.
Classified compliant (event-time reads before writes — D13 is a timing
rule): float-panel (drag already caches bounds; open seed is one-shot),
cropper, splitter.
Suites updated to the deferred contract and green (scroll-area 3/3,
carousel 4/4, virtual-list, virtual-grid); baseline 59.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>