history API is asynchronous, preventing: history.go(); history.replaceState(); from applying state to correct entry
Reported by
jamesgil...@gmail.com,
Oct 17 2017
|
||||
Issue description
UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.0 Safari/537.36
Steps to reproduce the problem:
1. history.pushState({}, null, '/foo')
2. history.go(-1)
3. history.replaceState({}, null, '/bar')
What is the expected behavior?
The URL you end up on is the first entry of 2 in the history stack (as indicated by the availability of the forward button) and has the url /foo.
What went wrong?
replaceState operates on the 2nd entry, changing it from /foo to /bar, while going back the original URL.
Did this work before? N/A
Does this work in other browsers? N/A
Chrome version: 63.0.3239.0 Channel: n/a
OS Version: OS X 10.11.6
Flash Version:
In other browsers (tested on Safari + Firefox, OSX), these operations are executed synchronously, correctly applying replaceState to the first entry.
ALSO NOTE: this is a contrived example. A better example might be just changing the state object in step 3, as a means to go somewhere else in the stack, while simultaneously changing its state.
,
Oct 17 2017
To test this, make sure to paste steps 2 and 3 in the console and execute them together. It works if there is a pause of what seems to be at least 17ms between the two (i.e. one animation frame).
For example this works:
history.go(-1)
setTimeout(() => {
history.replaceState({}, null, '/bar')
}, 17)
while this does not:
history.go(-1)
history.replaceState({}, null, '/bar') // incorrect entry has its state replaced
,
Oct 17 2017
Try disabling chrome://flags/#browser-side-navigation and see if it helps.
,
Oct 17 2017
unfortunately it did not.
,
Oct 17 2017
History API is in HTML spec, so moving DOM to HTML component. Also adding UI>Browser>Navigation. At a glance at spec https://html.spec.whatwg.org/multipage/history.html#the-history-interface there is no mention about how history.go() (or back/forward) can be asynchronous or synchronous. Anyhow this behavior differs from other browsers, marking as Hotlist-Interop.
,
Feb 13 2018
,
Feb 13 2018
The spec for history.go() uses the "traverse the history by a delta" algorithm: https://html.spec.whatwg.org/multipage/history.html#traverse-the-history-by-a-delta Step 5 is to queue a task to perform the history traversal. That strongly implies that it's permissible for the navigation to be asynchronous, so from a narrow spec-correctness perspective, this is working as intended. That said, there's almost certainly room to improve the spec for this API. Some ideas I've heard floated that might help: * Have a history operation queue, so that all operations are guaranteed to execute in-order. * Make all history operations (including pushState and replaceState) async, and have them return a promise. |
||||
►
Sign in to add a comment |
||||
Comment 1 Deleted