New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.
Starred by 84 users

Issue metadata

Status: Fixed
Owner:
Closed: Jan 2014
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 2
Type: Bug



Sign in to add a comment

Add window.history.state and don't fire popstate after load

Reported by rcalh...@gmail.com, Nov 13 2010 Back to list

Issue description

Chrome Version       :  Google Chrome	7.0.517.44 (Official Build 64615)  WebKit	534.7
URLs (if applicable) :http://www.splefty.com/js/popstate.html
Other browsers tested:
Add OK or FAIL after other browsers where you have tested this issue:
     Safari 5: OK
  Firefox 3.x: not tested 
       IE 7/8: onpopstate not supported

What steps will reproduce the problem?
1. Go to URL above. You should not get a alert box, but you will because Chrome is throwing an onpopstate event on page load. It should only be thrown on a history action (forward / back buttons)

What is the expected result?

I believe it should do nothing. Review the W3C editors acerbic response in ticket 10365 below and see if you agree.

What happens instead?

In the latest build of Chrome, onpopstate fires on initial navigation to the page.. This much is clear.

Please provide any additional information below. Attach a screenshot if
possible.

See also http://www.google.com/support/forum/p/Chrome/thread?tid=34fd0582af7d5584&hl=en

See also W3C:  http://www.w3.org/Bugs/Public/show_bug.cgi?id=10365

Relevant quote from ticket 10365: 

"The spec seems completely unambiguous here — search for the string 'fire a popstate event' for the only two occurrences, neither of which can happen
without history traversal. Regarding the question in comment 2, a page load results in the "navigate" algorithm being invoked, which unambiguously results in history traversal.

Thus what you describe is an implementation bug."
 

Comment 1 by temp01...@gmail.com, Nov 13 2010

Labels: -Area-Undefined Area-WebKit WebKit-JavaScript
Status: Untriaged

Comment 2 by mihaip@chromium.org, Nov 13 2010

Status: WontFix
This is behaving as designed. See the discussion on https://bugs.webkit.org/show_bug.cgi?id=41372, and the change to the HTML5 spec that was made: http://html5.org/tools/web-apps-tracker?from=5345&to=5346. Firing popstate after onload is as designed.

I'm not sure why Hixie said this was an implementation bug, since his first sentence makes it clear that popstate should be fired as part of navigation: "The spec seems completely unambiguous here — search for the string 'fire a popstate event' for the only two occurrences, neither of which can happen
without history traversal. Regarding the question in comment 2, a page load results in the "navigate" algorithm being invoked, which unambiguously results in history traversal."
I was wrong.

Comment 4 by mihaip@chromium.org, Nov 13 2010

Thanks for clarifying!

Comment 5 by rcalh...@gmail.com, Nov 15 2010

Thank you very much for the lightning-fast clarification!

It would be useful to put together a best-practices code pattern for the onpopstate handler. Is there a preferred method for a script to distinguish between the initial onpopstate firing with a null state and a subsquent firing with a null state? It seems to me the first call with null state should be ignored (since the page has just been loaded) while later null states may require reloading or re-rendering of the page in order to recover the initial content associated with that URL.

Comment 7 by mihaip@chromium.org, May 27 2011

Labels: Mstone-14
Owner: mihaip@chromium.org
Status: Assigned
Summary: Add window.history.state and don't fire popstate after load (was: NULL)
Yes, there was a meeting with Mozilla and a spec-change in March. Mozilla implemented these changes (http://hacks.mozilla.org/2011/03/history-api-changes-in-firefox-4/), Chrome/WebKit has not yet. Re-purposing this bug for that.

Comment 8 by mihaip@chromium.org, Jul 26 2011

Labels: -Mstone-14 Mstone-15

Comment 9 by mihaip@chromium.org, Aug 30 2011

Cc: anan...@chromium.org vivianz@chromium.org
 Issue 87522  has been merged into this issue.
Labels: -Mstone-15 Mstone-16
//found fast workaround to get same behawior as ff4:

setTimeout(function(){
	window.onpopstate = function(event){
		window.console && window.console.log(event);
	};
},1000);

Comment 12 by laforge@google.com, Oct 24 2011

Labels: -Mstone-16 MovedFrom-16 Mstone-17
Labels: WebKit-ID-70876
Owner: ----
Status: Available
Project Member

Comment 14 by bugdroid1@chromium.org, Nov 2 2011

Labels: -WebKit-ID-70876 WebKit-ID-70876-NEW

Comment 15 by k...@google.com, Dec 19 2011

Labels: -Mstone-17 MovedFrom-17
Removing milestone on all bugs marked available and targeted at m17.  Please re-triage to a new milestone if desired.
This was mentioned again recently in http://dropshado.ws/post/15251622664/ignore-initial-popstate .  Who's a good owner for this?
Project Member

Comment 17 by bugdroid1@chromium.org, Jan 20 2012

Labels: -WebKit-ID-70876-NEW WebKit-ID-70876-RESOLVED
https://bugs.webkit.org/show_bug.cgi?id=70876
Labels: -WebKit-ID-70876-RESOLVED WebKit-ID-76035
Project Member

Comment 19 by bugdroid1@chromium.org, Jan 21 2012

Labels: -WebKit-ID-76035 WebKit-ID-76035-UNCONFIRMED WebKit-Rev-105308
https://bugs.webkit.org/show_bug.cgi?id=76035
http://trac.webkit.org/changeset/105308
Project Member

Comment 20 by bugdroid1@chromium.org, Jan 27 2012

Labels: WebKit-Rev-106077
http://trac.webkit.org/changeset/106077
Project Member

Comment 21 by bugdroid1@chromium.org, Feb 8 2012

Labels: -WebKit-ID-76035-UNCONFIRMED WebKit-ID-76035-RESOLVED WebKit-Rev-107058
https://bugs.webkit.org/show_bug.cgi?id=76035
http://trac.webkit.org/changeset/107058
please don't fire onpopstate after load like firefox
I think onpopstate must be one-to-one with every pushState
There are 2 bugs here. history.state is implemented. We can make that as fixed.
onpopstate firing on page load should be moved to a new issue.
Any update?
The popstate event emitted on load is really annoying.

Comment 25 Deleted

Here is my workaround if it can helps someone:
https://gist.github.com/3551566
The latest W3C Candidate Recommendation (http://www.w3.org/TR/2012/CR-html5-20121217/browsers.html#history-traversal) makes it relatively clear that his is indeed a bug.


To paraphrase, "Fire a popstate event at the Window object of the Document if the Document of the specified entry has a latest entry, and that entry is not the specified entry."

Comment 28 by ianh@google.com, Jan 11 2013

Note that that spec is way out of date and has numerous problems. I would recommend http://whatwg.org/html instead.

Comment 30 by Deleted ...@, Jan 13 2013

I've being trying to avoid this (as comment 11: https://code.google.com/p/chromium/issues/detail?id=63040#c11) and I guess this way behaves a little faster:

$(window).on('load', function () {
  setTimeout(function () {
    $(window).bind("popstate", function (event) {
      // Do whatever you want...
    });
  }, 0);
});

Binding the popstate event after the window loads works for me even with no delay.
Project Member

Comment 31 by bugdroid1@chromium.org, Mar 10 2013

Labels: -Area-WebKit -WebKit-JavaScript Cr-Content-JavaScript Cr-Content

Comment 32 Deleted

Comment 33 by Deleted ...@, Mar 26 2013

Does popstate fired when user pressing on Back button and before browser navigate to previous page (user can listen this event and stop the navigation process of back button, like disable back button)? According to w3c:

onpopstate : Script to be run when the window's history changes

So, I though when pressing on Back button the history object invoked back() function which navigate to previous state on history object => that fired the popstate event.
Currently, Chrome fire popstate after window load success.
Project Member

Comment 34 by bugdroid1@chromium.org, Apr 6 2013

Labels: -Cr-Content Cr-Blink
Project Member

Comment 35 by bugdroid1@chromium.org, Apr 6 2013

Labels: -Cr-Content-JavaScript Cr-Blink-JavaScript

Comment 36 by i...@segment.io, Oct 25 2013

Not firing a popstate event is still a bug many months later. Any updates? 

The only workarounds are really kludgey involving timeouts or assuming things about history.state...
Please fix this! While Chrome's behavior did indeed match W3C specs circa 2010, the HTML5 spec was fixed in 2011 knocking Chrome out of compliance. If that's not incentive enough to do the right thing, even Microsoft (i.e., IE10) gets this behavior correct;)
Please fix this.

Comment 39 by Deleted ...@, Jan 8 2014

when is this going to be fixed? 
FYI, it is easy to fix this yourself if you have some sort of page state counter. For example:

window.onpopstate = function (evt) {
 var new_state = evt.state // evt.state can't be modified.
 if (typeof gs.page_state == "undefined") gs.page_state = null
 if ((gs.page_state == null) && (new_state == null)) return // Fix for browsers that pop the state on page load.
 set_page_state (new_state, true)
}

Comment 41 by Deleted ...@, Jan 12 2014

Please fix this old and very irritating bug.

There is no 100% reliable workaround.

Comment 42 by j...@opera.com, Jan 13 2014

Owner: j...@opera.com
Status: Started
We're tired of workarounds, please fix this.
Project Member

Comment 45 by bugdroid1@chromium.org, Jan 16 2014

The following revision refers to this bug:
    http://src.chromium.org/viewvc/blink?view=rev&rev=165221

------------------------------------------------------------------------
r165221 | jl@opera.com | 2014-01-16T13:53:34.787797Z

Changed paths:
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/pushstate-object-types.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/pushstate-then-replacestate.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/replacestate-then-pushstate.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/popstate-after-load-complete-window-attribute.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/popstate-after-load-complete-body-inline-attribute.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/history/same-document-iframes-changing-pushstate-expected.txt?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/http/tests/history/popstate-fires-with-pending-requests.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/http/tests/navigation/redirect-on-back-updates-history-item-expected.txt?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/pushstate-with-fragment-urls-and-hashchange.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/document-destroyed-navigate-back.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/Source/core/frame/DOMWindow.cpp?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/http/tests/navigation/redirect-on-reload-updates-history-item-expected.txt?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/history/same-document-iframes-changing-fragment-expected.txt?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/popstate-after-load-complete-body-attribute.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/document-destroyed-navigate-back-with-fragment-scroll.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/popstate-after-load-complete-addeventlistener.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/resources/pushstate-in-iframe-child.html?r1=165221&r2=165220&pathrev=165221
   M http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/loader/stateobjects/resources/replacestate-in-iframe-window-child.html?r1=165221&r2=165220&pathrev=165221

Don't fire popstate event on initial document load

According to the specification [1], a popstate event should only be fired
when the document has a "last entry" and the entry being navigated to isn't
it.  A document is created without a "last entry" and gets one just after
this check when it is first navigated to, so a popstate should be fired any
time a document is navigated to except for the first time after it has been
created.

[1] http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#traverse-the-history (step 12-14 in particular)

BUG= 63040 

Review URL: https://codereview.chromium.org/136463002
------------------------------------------------------------------------

Comment 46 by j...@opera.com, Jan 16 2014

Status: Fixed
Still not landed on Chrome 32 stable, fixed on Chrome Canary 34.
Oh god thank you very much.
This is a good change, but it breaks our Chrome-only page (PNaCl demos -- https://gonativeclient.appspot.com/demo) which were relying on a null popstate event firing. Is it possible to make it more clear to a web developer of this behavior change?
!!!This bug is not fixed!!! The patch still misinterprets the text of the specification.

#45
'According to the specification [1], a popstate event should only be fired
when the document has a "last entry" and the entry being navigated to isn't
it.  A document is created without a "last entry" and gets one just after
this check when it is first navigated to, so a popstate should be fired any
time a document is navigated to except for the first time after it has been
created.'

'[1] http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#traverse-the-history (step 12-14 in particular)'

1) The document being navigated to is called the "specified entry".
2) The document being navigated from is called the "latest entry".
3) Steps 12-14 discuss the "specified entry" and the "latest entry".. not the LAST ENTRY! Latest entry, not last entry. BIG DIFFERENCE HERE my friend!!!

From http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#traverse-the-history:
"12) Let state changed be true if the Document of the specified entry has a latest entry, and that entry is not the specified entry; otherwise let it be false."
The "state changed" is true, because the latest entry is not the specified entry. This is where the logic of the patch diverges, because the patch considers the latest entry to be the "LAST" entry.

Examine the code below. Going to e.g. google.com, then the page with the code below, then back to google.com and back again to this page, should NOT FIRE ONPOPSTATE!

<!DOCTYPE html>
<html lang="en">
 <head>
 </head>
 <body>
  <script type="text/javascript">
   var history_control = new history_control_object ()
   function history_control_object (new_state) {
    window.addEventListener ('popstate', function (evt) {console.log (evt.state)})
    history.replaceState ({url: 'apple'}, "")
   }
  </script>
 </body>
</html>

Sign in to add a comment