Repository navigation
fix(renderer-dom): never estimate a row height we have already measured - #342
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…er-dom The first design's hypothesis (sub-pixel Range rounding on the tick-flash underline) was falsified at its verification gate. Measurement showed the spiked heights are never measured at all: they are estimateDomRowHeight's output, re-applied to rows already measured. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s own bound Retain only data rows, since the estimate gate that consumes retained heights is itself gated on data rows and group entries could never be looked up. Give retention its own `maxRetainedRowHeights` option rather than borrowing `maxRetainedMeasurements`, which bounds the height index's tombstones and does not bound live measurements at all. Sharing it meant a legitimate `0` silently disabled the fix. Pin the previously uncovered lines: the LRU refresh, the remove-path eviction, the disposal clear, and the data-row guard. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Vercel preview readyPreview: https://pretable-az3sw4s2p-cacheplane.vercel.app Updated automatically by the |
This was referenced Aug 13, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The homepage hero grid jittered in Chrome while streaming. The heights it jittered to were never measured — they were produced by
estimateDomRowHeightand applied on top of rows that had already been measured.Measured in Chrome over 8 seconds before the fix: the DOM measurement path produced
63/89/68, while the row nodes received63,66,114,89,68.66and114were published 71 times and measured zero times, and both reconcile exactly with the estimator's constants (1×24+42and3×24+42).Mechanism
While a row-model replacement is in flight,
controller.measureonly stages the measurement. Streaming issues anupdatefor every row every tick, which discards the staged entry — correctly, since the content changed — after which the estimate gate treats a row measured dozens of times as one never seen. The estimator overshoots the real DOM in both of its terms, so the correction a commit later is always downward and always visible.The fix
Retain the last measured height per data-row identity and use it as the estimate gate's fallback, so an estimate is only ever used for a row that has never been measured.
hasMeasurementstill goes false; the scheduler, the sliced catch-up, and the staging discard are untouched. The gate only iterates the planned window, so a retained height is only ever a one-frame placeholder for a row about to be re-measured.Retention is scoped to data rows (the gate itself is), bounded by a new
maxRetainedRowHeightsoption with least-recently-measured eviction, and cleared on dispose.Result
66/114)renderer-dom52/52,@pretable/core7/7,@pretable/react827/827, website smoke 12/12 including the existing "no row drift" guard. Every new line was mutation-checked: each was removed individually and shown to turn a test red.Not fixed here, deliberately
A row entering the window for the first time still jumps (66 → 63), because it has no prior measurement to fall back on. That needs the estimator's inputs to be real — its line height, chrome and character width are constants calibrated against the bench app rather than the active theme, and it is blind to
renderandformatbesides. Both are recorded as follow-ups in the design doc, along with a false comment atpackages/react/src/pretable-model.ts:405.Group rows also still revert on update; the estimate gate is data-only, so extending retention there is a separate product call.
Design:
docs/superpowers/specs/2026-08-12-row-height-estimate-stomping-design.md🤖 Generated with Claude Code