This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 27188 - popstate should not fire when pageshow does
Summary: popstate should not fire when pageshow does
Status: RESOLVED MOVED
Alias: None
Product: WHATWG
Classification: Unclassified
Component: HTML (show other bugs)
Version: unspecified
Hardware: Other All
: P3 normal
Target Milestone: Unsorted
Assignee: Ian 'Hixie' Hickson
QA Contact: contributor
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-10-29 12:05 UTC by Jens Widell
Modified: 2019-03-29 21:53 UTC (History)
6 users (show)

See Also:
annevk: needinfo? (bugs)


Attachments

Description Jens Widell 2014-10-29 12:05:08 UTC
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)
Comment 1 Ian 'Hixie' Hickson 2014-10-30 18:27:37 UTC
We definitely want to fire popstate if you're ending up in a different state, otherwise you won't be in the right state.
Comment 2 Jens Widell 2014-10-31 17:01:01 UTC
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.
Comment 3 Ian 'Hixie' Hickson 2014-11-04 00:43:26 UTC
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?
Comment 4 Jonas Sicking (Not reading bugmail) 2014-11-04 21:49:24 UTC
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.
Comment 5 Jonas Sicking (Not reading bugmail) 2014-11-04 21:53:36 UTC
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.
Comment 6 Ian 'Hixie' Hickson 2014-11-06 00:42:26 UTC
My understanding is consistent with sicking's, and I believe this matches the spec.
Comment 7 Jens Widell 2014-11-06 09:49:08 UTC
@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.
Comment 8 Ian 'Hixie' Hickson 2014-11-07 21:34:50 UTC
> @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.
Comment 9 Jonas Sicking (Not reading bugmail) 2014-11-08 02:29:32 UTC
(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.
Comment 10 Ian 'Hixie' Hickson 2015-01-13 23:31:39 UTC
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.
Comment 11 Jens Widell 2015-01-14 07:14:20 UTC
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.
Comment 12 Jonas Sicking (Not reading bugmail) 2015-01-15 06:20:39 UTC
Can you clarify what part of the spec that is different from the Firefox/Blink behavior?
Comment 13 Jens Widell 2015-01-15 07:12:08 UTC
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.
Comment 14 Ian 'Hixie' Hickson 2015-01-15 20:15:38 UTC
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.
Comment 15 Jonas Sicking (Not reading bugmail) 2015-01-16 01:49:20 UTC
If what you are saying about Firefox's behavior is correct, then I agree that that is indeed bad.
Comment 16 Jonas Sicking (Not reading bugmail) 2015-01-16 01:50:36 UTC
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.
Comment 17 Anne 2016-03-25 13:28:01 UTC
Olli, any final thoughts? It seems like this can be closed.
Comment 18 Domenic Denicola 2019-03-29 21:53:23 UTC
https://github.com/whatwg/html/issues/4488