This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.
Firefox's and MSIE's current behavior (AFAICT) is to only fire popstate when navigating between entries that have the same document. This means a navigation either fires pagehide+pageshow (between documents) or popstate (within document) but never both. Blink's current behavior is to always fire popstate except on initial page load, but this is definitely wrong per spec and will be changed, most likely to match Firefox and MSIE. The current specification, OTOH, says effectively to also fire popstate when navigating between documents if the target document was last active via a different session history entry than the one now being navigated to, since that would then be the document's "latest entry", different from the "specified entry" in 7.6.10 History traversal, step 12. References Blink bug: https://code.google.com/p/chromium/issues/detail?id=400427 Mozilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1059382 (see in particular comment #6)
We definitely want to fire popstate if you're ending up in a different state, otherwise you won't be in the right state.
I have no strong opinion myself, really. Adding Jonas Sicking to CC, who might like to weigh in. One thing to note is that the point of firing popstate ought to be signal a mismatch between history.state (and/or URL or fragment) and the rest of the page's state, so that the page can adjust. Given that, it's also somewhat questionable to suppress popstate in the "no latest entry" case since that might be because the document had been discarded. IOW, any entry (including that which is really the latest) can be activated without a popstate event (per spec), as long as the document had been discarded in between. If the (used-to-be) latest entry is navigated to, but the document had been discarded, then the page probably needs to restore state, despite not getting a popstate. It would then need to do that in the load or pageshow event.
If the document is discarded, so's the state, at which point you just have a URL. You'll still get a hashchange event, though, no?
Let me check that I understand the question correctly. Say that the user does 1. Go to page A (creates session-history entry 1) 2. Press a button which causes pushState to be called, with a non-null "data" argument and a new URL (creates session-history entry 2) 3. User clicks link which causes a navigation to page B (creates session-history entry 3) 4. User uses some in-browser UI to jump two steps back in history, i.e. directly to session-history entry 1. Alternatively, page B calls history.go(-2) And the question is, will step 4 cause popstate to fire or not. Am I understanding the question correctly? I think there are two possible valid behaviors. A) If the browser kept page A in memory (Firefox calls this feature fast-back, chrome doesn't implement this), then the browser would display page A, and fire the popstate event. I.e. it would behave almost exactly as if the user had clicked the normal 'back' button instead of doing step 3. B) If the browser tore down page A during step 3, then the browser would load page A again, but with history.state set to null, and the URL being the URL navigated to in step 1. No popstate event is fired. I don't know if this is what the spec states, but if it doesn't, it should. This was the behavior we intended to implement in Firefox, but of course we might have bugs. Seems like https://bugzilla.mozilla.org/show_bug.cgi?id=1059382 is one of those bugs.
In scenario A above, pageshow definitely needs to fire. So that's a scenario when both pageshow and popstate can both fire. I haven't thought about about which order they should fire in though. And when history.state should change to being null. Intuitively it seems like we should first fire pageshow, then update history.state, then fire popstate. The last two should definitely happen from the same async task. I don't have a strong opinion about if pageshow should also happen from that same task or if it could be a separate async task which runs first.
My understanding is consistent with sicking's, and I believe this matches the spec.
@jonas: In https://bugzilla.mozilla.org/show_bug.cgi?id=1059382#c6 you write "The proper behavior should be that popstate should only fire when transitioning between two session-history entries that use the same Document. Any time that the user presses back/forward and we switch Document, that should never fire popstate." Given what you've written here, I guess this statement assumed single-step history navigation? AFAICT, it does accurately describe Firefox's behavior for all history navigation, however. And also Blink's behavior on trunk, FWIW. @ian: When you say "the state" is discarded along with the document, are you talking about the state object stored in the session history entry (i.e. the first argument to pushState()/replaceState())? If so, where in the specification is this described? It's not a conclusion I have drawn from anything I've read, or from anything I could find now. It's also not what either Blink or Firefox does. FYI, I've constructed a pair of test cases here: http://jenswidell.se/history.html http://jenswidell.se/history-with-unload.html Both set up two history positions with history.state and fragment identifiers (replaceState+pushState) and then navigates to a second document. Upon history navigation, the first document then records pageshow and popstate events with a time delta from when the document was loaded (to detect whether the document was discarded.) MSIE's behavior on these tests appear a bit erratic, BTW. Navigating two steps back (whether using the back button or history.go(-2)) seems to reload the document for target session history entry, so that you end up with a different document object for each session history entry. Trying to detect how it handles popstate events in the scenario this bug is about is thus impossible, it turns out.
> @ian: When you say "the state" is discarded along with the document, are you > talking about the state object stored in the session history entry (i.e. the > first argument to pushState()/replaceState())? Yes, but I am mistaken about this. The state remains. popstate should fire accordingly.
(In reply to Jens Lindström from comment #7) > @jonas: In https://bugzilla.mozilla.org/show_bug.cgi?id=1059382#c6 you write > > "The proper behavior should be that popstate should only fire when > transitioning between two session-history entries that use the same > Document. Any time that the user presses back/forward and we switch > Document, that should never fire popstate." > > Given what you've written here, I guess this statement assumed single-step > history navigation? Correct. > AFAICT, it does accurately describe Firefox's behavior > for all history navigation, however. And also Blink's behavior on trunk, > FWIW. Like I said in comment 5. There are definitely scenarios where popstate and pageshow both fire. If that's not the case in Firefox please do file a bug. It is not an intentional behavior.
So what's the conclusion here? Is the spec ok? I'm not sure I understand what the difference is between what you want and what the spec says.
IMO, the specification itself is fine as it is now and would also be fine with the modification I've suggested here. I have no strong opinion in favor of either alternative, really. Both Firefox and Blink currently implement the modified behavior I've suggested.
Can you clarify what part of the spec that is different from the Firefox/Blink behavior?
The difference is when navigating multiple steps backwards or forwards in history (e.g. history.go(-2)) between different documents. This lets you navigate to a session entry that's not its document's "latest entry", in which case, per current specification, a popstate event should be fired in addition to the pageshow that is fired. Neither Blink nor Firefox fire a popstate event in this situation, AFAICT. Instead, popstate events are only fired when navigating between session entries that reference the same document. IOW, navigations fire either pageshow or popstate, and never both. https://jenswidell.se/history.html is a test case for this.
Yeah, the spec behaviour seems more correct to me than the implemented behaviour in this scenario. I think we should leave the spec as is.
If what you are saying about Firefox's behavior is correct, then I agree that that is indeed bad.
Also adding Olli who might have an opinion on this. But I agree that if Firefox allows transitioning a document between session-history states without firing popstate then that sounds like a bug.
Olli, any final thoughts? It seems like this can be closed.
https://github.com/whatwg/html/issues/4488