The readest#4727 regression test set scrollTop=0, dispatched a synthetic
wheel, waited 60ms, then asserted scrollTop stayed 0. On slow CI runners it
flaked with "expected 4 to be +0".
As sibling scroll pages finish loading, the renderer runs
restoreScrollModeAnchor asynchronously, which at scrollTop=0/page-index-0
snaps scrollTop to page 0's offsetTop, the 4px scroll-page-gap margin. The
60ms post-dispatch delay raced that re-anchoring, so the assertion observed 4
instead of 0. That 4 is unrelated to the wheel bug, which is a 120px jump.
The buggy handler was scrollBy with instant behavior, a synchronous scroll
that lands before dispatchEvent returns. Measure scrollTop synchronously
before and after the dispatch with no await in between and assert they match.
This isolates the wheel handler's own effect and is immune to the async
re-anchoring. Reintroducing the bug still fails the test (before=4, after=124,
a clean 120px delta).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bumps foliate-js to drop the redundant manual `scrollBy` the scrolled-mode
page iframes ran on every wheel event. Because those iframes are
`scrolling="no"`, the browser already chains the wheel to the host scroller
natively; the extra scrollBy stacked on top, so wheeling over a page moved
it ~2x as far in an instant lurch while the margins scrolled smoothly by one
notch. Native scroll-chaining now provides the single smooth scroll over both
the page and the margins.
Adds a browser-lane regression test that mounts the real <foliate-fxl>
renderer in scrolled mode and asserts a wheel over a page does not
programmatically move the host scroller.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>