Navigation API: scroll "after-transition" restore on an intercepted traversal uses stale layout when the intercept handler changed the page height
Categories
(Core :: DOM: Navigation, defect)
Tracking
()
People
(Reporter: simrpgman, Unassigned)
References
(Blocks 1 open bug)
Details
Attachments
(1 file)
|
2.38 KB,
text/html
|
Details |
Steps to reproduce
Product / Component: Core :: DOM: Navigation
Version: 157 Branch (the Release build used)
Platform: ARM64 / macOS
Summary: Navigation API: scroll "after-transition" restore on an intercepted traversal uses stale layout when the intercept handler changed the page height
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:157.0) Gecko/20100101 Firefox/157.0 (also reproduced on Nightly 160.0a1, build ID 20261010084543)
Steps to reproduce:
- Save the attached
scroll-restore.htmland serve it over http (for examplenpx http-server). - Open it. The page is 5000px tall and scrolls to 1000. It navigates with
navigation.navigate('?pushed'), and the intercepted push's handler sets the content height to 0. It then callsnavigation.back(). The intercepted traversal's handler (defaultscroll: "after-transition") waits 20 ms, then sets the height back to 5000px without reading layout. - Read the log: scrollY when
back().finishedsettles, and 100 ms later. - Repeat with
?render=microtask(the height is restored a microtask into the handler), with?framed(the same page in an iframe), and with?flush=1(the handler readsdocument.documentElement.scrollHeightat the end).
Actual results
Actual results:
- Top level: scrollY is 0 when
finishedsettles. It becomes 1000 within 100 ms with the 20 ms render. With the microtask render it stays 0 in most runs. - In an iframe: scrollY stays 0. (On Nightly, the iframe run with the 20 ms render crashes the tab instead; that is a separate bug about the traversal being committed twice in an iframe, filed alongside.
?framed&render=microtaskshows the scroll bug on Nightly.) - With
?flush=1: scrollY is 1000 atfinishedin every case.
Expected results
Expected results:
scrollY is 1000 when finished settles, at top level and in an iframe, with or without the layout read, as in Chrome. Per HTML, the handler's promise settling runs "finish a NavigateEvent", then "process scroll behavior", then "restore scroll position data", all before the finished promises resolve. By then the document is 5000px tall again, so the restore should not clamp to the old 0px range.
- https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigate-event-intercept-commit-handler-steps
- https://html.spec.whatwg.org/multipage/nav-history-apis.html#process-scroll-behavior
- https://html.spec.whatwg.org/multipage/browsing-the-web.html#restore-scroll-position-data
Additional information:
- Reproduced on Release 157.0.1, Beta 158.0b5, Developer Edition 158.0b5 and Nightly 160.0a1 (macOS arm64), with new profiles, headless and headed.
- Reading
document.documentElement.scrollHeightat the end of the handler works around it, which points at the restore using layout from before the handler's style change. Bug 217120 was the same kind of problem on the classic history path. - Related: bug 1950894 (Navigation API tracker; this should probably block it) and bug 2050964 (fixed the "has been scrolled by the user" check in the same restore step).
- Not covered by WPT:
navigation-api/scroll-behavior/after-transition-traverse-no-fragment.htmlnever changes the page height during the navigation. A variant that shrinks the page on push and grows it back in the traverse handler, run at top level and in an iframe, would catch this. - Real-world impact: a router that renders the destination view inside the intercept handler (ui-router's Navigation API location plugin, with its
interceptTraverseoption) loses the back/forward scroll position unless it forces layout itself.
Comment 1•9 days ago
|
||
The Bugbug bot thinks this bug should belong to the 'Core::DOM: Navigation' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.
Updated•8 days ago
|
Updated•8 days ago
|
Description
•