fix: reset IntersectionObserver on 0→non-zero root width transition#8184
Conversation
|
…strengthen test assertions Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com>
4589f21
into
copilot/fix-zero-size-root-race
|
The recovery path for Safari's zero-width root race condition was a no-op.
observeSubscribedElements()calledobserver.observe(el)on elements already being observed — which the IntersectionObserver spec defines as a no-op — so no fresh initial batch was ever delivered. Items that had collapsed during the bad zero-width batch stayed stuck as "not overflowing."Changes
OverflowObserverProvider.tsx0 → non-zeroroot width transition, fully reset the sharedIntersectionObserverbefore re-observing:getObserver()to construct a newIntersectionObserver, which delivers a correct initial batch for every subscribed element. No new persistent observers are introduced.useOverflowObserver.test.tsxdisconnected: booleantracking toMockIntersectionObserver.disconnect().vi.spyOn(HTMLElement.prototype, 'clientWidth', 'get')is applied beforerender()so the ResizeObserver effect captureslastWidth = 0(in a real Chromium environment the<ul>hasclientWidth > 0without this). The test now explicitly asserts that the old observer was disconnected and a new instance was created — it fails against the prior no-op implementation.Changelog
New
Changed
OverflowObserverProvider: on the 0→non-zero root width transition, the sharedIntersectionObserveris now fully disconnected and rebuilt to guarantee a fresh observation batch.Removed
Rollout strategy
Testing & Reviewing
The updated test verifies the contract directly: it fails if
disconnect()is not called on the prior observer instance and fails if no newIntersectionObserverinstance is created on the transition. The zero-width guard test and sub-pixel threshold test are unchanged and still pass.