Skip to content

fix(web): stop scrollbar-oscillation relayout loop in LinearLayoutManager#2361

Open
momomuchu wants to merge 1 commit into
Shopify:mainfrom
momomuchu:fix/scrollbar-oscillation-relayout-2334
Open

fix(web): stop scrollbar-oscillation relayout loop in LinearLayoutManager#2361
momomuchu wants to merge 1 commit into
Shopify:mainfrom
momomuchu:fix/scrollbar-oscillation-relayout-2334

Conversation

@momomuchu

Copy link
Copy Markdown

On web with classic (non-overlay) scrollbars, borderline-overflow content makes the scrollbar toggle on and off every frame, which loops relayout forever and crashes with "Maximum update depth exceeded".

updateLayoutParams() recomputed on any boundedSize change with no hysteresis, so a ~17px scrollbar-width delta alternated indefinitely. This adds A/B/A oscillation detection: when the cross-axis size alternates between two values within a scrollbar-width threshold (20px), it locks to the narrower one and treats further sub-threshold changes as noise. A real resize past the threshold unlocks and re-baselines; an axis flip clears the lock.

The test is a pure layout-manager unit test that feeds an oscillating width sequence and asserts convergence instead of unbounded recompute. It fails without the fix (10 unbounded recomputes) and passes with it. Layout-manager and grid/masonry suites green, tsc and lint clean.

Closes #2334

…nager

On web with classic (non-overlay) scrollbars, borderline-overflow content
can enter an infinite scrollbar show/hide feedback loop: showing the
vertical scrollbar narrows the measured cross-axis width (boundedSize),
which reflows items so content no longer overflows, which hides the
scrollbar, which widens the measurement again... crashing with
"Maximum update depth exceeded".

updateLayoutParams recomputed on ANY boundedSize change with no hysteresis,
so a ~15-17px scrollbar-width oscillation looped forever. Detect an A/B/A
bounce within a 20px threshold, lock boundedSize to the stable (narrower)
value, and ignore further scrollbar-width noise until a genuinely larger
resize arrives (which unlocks and re-baselines).

Adds pure-TS regression tests: an oscillating width sequence now converges
(recompute count bounded) instead of recomputing unboundedly, while a real
resize past the threshold still recomputes.

Closes Shopify#2334
@momomuchu momomuchu closed this Jul 5, 2026
@momomuchu momomuchu reopened this Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[WEB] Scrollbar oscillation cause infinite layout loop

1 participant