Closed Bug 640387 Opened 13 years ago Closed 13 years ago

onhashchange not fired on navigation when navigation entries created via history.pushState

Categories

(Core :: DOM: Events, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla6

People

(Reporter: glenn, Assigned: justin.lebar+bug)

References

()

Details

Attachments

(2 files, 9 obsolete files)

User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 (.NET CLR 3.5.30729)
Build Identifier: FF4 RC1

When history states that only change the URL hash are added via history.pushState, navigating via browser back does not fire onhashchange.


Reproducible: Always

Steps to Reproduce:
1. Open the web console.
2. Load http://zewt.org/~glenn/test-hashchange-ff4.html.  The page will add several history states.
3. Click browser back to navigate back to "/test-hashchange-ff4.html#2".

A single "hashchange: #2" should be logged to the console; it isn't.
Oh, that's bad.  I wonder if this regressed from the changes to pushstate we made recently.
Justin, want to take this?
Status: UNCONFIRMED → NEW
Ever confirmed: true
I can't until I finish school and move, March 23 or so at the earliest.

So if we want to fix this for the release, no way.  :)
I don't think we're going to be changing this for the release at this point, unless someone really thinks this is a stop-ship blocker.  I certainly don't think it is.
Assignee: nobody → justin.lebar+bug
Attached patch Patch v1 (obsolete) — Splinter Review
Attachment #522759 - Flags: review?(bzbarsky)
Attached patch Patch v1.1 (obsolete) — Splinter Review
Closing body/html tags in test.
Attachment #522759 - Attachment is obsolete: true
Attachment #522759 - Flags: review?(bzbarsky)
Comment on attachment 523006 [details] [diff] [review]
Patch v1.1

This changes behavior in a way that matters, I think.

In particular, when going from

  http://example.com/#foo

to

  http://example.com/

via a non-history load the old code does a load instead of a scroll.  It looks like your new code will do a scroll.  If we don't have a test for this already, we should.  That's what this block is all about:

     if (hashNew == kNotFound &&
         (hashCurrent == kNotFound || aLoadType != LOAD_HISTORY)) {
         return NS_OK;
     }

in the old code.
Attachment #523006 - Flags: review-
In this case, should we fire a hashchange event?
6.5.9 History traversal, step 6:

> If the specified entry has a URL whose fragment identifier differs from that of > the current entry's when compared in a case-sensitive manner, and the two share > the same Document object, then let hash changed be true

Doing a real load creates a new document object (right?), so I guess we're off the hook.
Quote fail.

6.5.9 History traversal, step 6:

> If the specified entry has a URL whose fragment identifier differs from that of 
> the current entry's when compared in a case-sensitive manner, and the two share 
> the same Document object, then let hash changed be true.
Attached patch Patch v2 (obsolete) — Splinter Review
Attachment #523096 - Flags: review?(bzbarsky)
Attachment #523006 - Attachment is obsolete: true
Attached file Interdiff v1 -> v2 (obsolete) —
Attachment #523096 - Flags: review?(bzbarsky) → review?(Olli.Pettay)
> In this case, should we fire a hashchange event?

No; comment 9 is correct.
Comment on attachment 523096 [details] [diff] [review]
Patch v2

Based on IRC I'm expecting some re-factoring related to hash parsing.
Attachment #523096 - Flags: review?(Olli.Pettay)
Attached patch Patch v3 (obsolete) — Splinter Review
Attachment #523333 - Flags: review?(Olli.Pettay)
Attachment #523096 - Attachment is obsolete: true
Attached file Interdiff v2 -> v3 (obsolete) —
Attachment #523107 - Attachment is obsolete: true
nsContentUtils::SplitURIAtHash should take const nsACStrings; please consider that fixed.
(In reply to comment #17)
> nsContentUtils::SplitURIAtHash should take const nsACStrings; please consider
> that fixed.

Whoops; nevermind.  I was looking at the wrong function.
Attached patch Patch v4 (obsolete) — Splinter Review
Attachment #523415 - Flags: review?(Olli.Pettay)
Attachment #523333 - Attachment is obsolete: true
Attachment #523333 - Flags: review?(Olli.Pettay)
Attached patch Patch v5 (obsolete) — Splinter Review
Attachment #523415 - Attachment is obsolete: true
Attachment #523415 - Flags: review?(Olli.Pettay)
My docshell logic wasn't quite right in v4 (detect by existing test, browser_500328.js).  It's improved in v5.  Perhaps it's even correct.
Is the latest patch ready for review?
Yes; sorry about that.  I was having trouble with bzexport, and I forgot to set the review tag manually.
Attachment #523658 - Flags: review?(Olli.Pettay)
Comment on attachment 523658 [details] [diff] [review]
Patch v5

>+  PRInt32 index = spec.FindChar('#');
>+  if (index == -1)
>+    index = spec.Length();
if () {
...
}


>+        // If we have no new anchor, we do not want to do a short-circuited
>+        // load, unless there is a current anchor and we are doing a history
>+        // load.
>+        PRBool doAnchorLoad = sameExceptHashes &&
>+            (!newHash.IsEmpty() ||
>+             (!curHash.IsEmpty() && aLoadType == LOAD_HISTORY));
Indentation
Attachment #523658 - Flags: review?(Olli.Pettay) → review+
Not to nit the nit, but...

> if () {
> ...
> }

My understanding is that the style guideline for this kind of thing is "match the surroundings."  I've read a variety of style documents, but we seem to actually follow only a few rules.

$ grep 'if\s*(.*)\s*$' nsContentUtils.cpp  | wc -l
73
$ grep 'if\s*(.*) {\s*$' nsContentUtils.cpp  | wc -l
372

The ratio is the same for content/base/src/*.cpp.  This doesn't indicate to me a strong preference for one form over another, since of course many of the if () {}'s are multiline if's.

Are we trying to move towards if () {} in new code?
if (expr) {
  statement;
}
is what the coding style says we should be doing.
In some code the rules haven't been followed, but IMHO,
in new code the rules should be followed - whenever possible.
(Though, using 2 space indentation in a code which uses 4 spaces would
 make the code hard to read.)

(Javascript code and Spidermonkey code may have different rules, and
 some files may unfortunately use their own rules.)
(2-space indentation makes *all* code hard to read.)
Comment on attachment 523658 [details] [diff] [review]
Patch v5

This is not quite right, unfortunately.

Suppose our history is

  foo.html#a
  bar.html
  foo.html#b  <-- current entry

and suppose we go(-2).  This patch will fire a hashchange, but that's wrong, since the two entries for foo.html correspond to different documents.
Attachment #523658 - Flags: review+ → review-
Attached patch Part 2 v1 (obsolete) — Splinter Review
This, on top of v5, seems to fix the problem.  But I need to push to try.
Attached patch Patch v6Splinter Review
It's finally green on try!

I ended up rewriting the docshell short-circuit load code, and it's entirely posssible I've changed some behavior, despite passing the tests, so I'd appreciate a close look at the changes to InternalLoad.
Attachment #524853 - Flags: review?(Olli.Pettay)
Attachment #523658 - Attachment is obsolete: true
Attachment #524316 - Attachment is obsolete: true
Attached file Interdiff v5 -> v6
Attachment #523334 - Attachment is obsolete: true
Comment on attachment 524853 [details] [diff] [review]
Patch v6


>-
>-                if (mLSHE && wasAnchor) {
>-                    // If it's an anchor load, set mLSHE's doc identifier to
>-                    // mOSHE's doc identifier -- These are the same documents,
>-                    // as far as HTML5 is concerned.
>-                    PRUint64 docIdent;
>-                    rv = mOSHE->GetDocIdentifier(&docIdent);
>-                    if (NS_SUCCEEDED(rv)) {
>-                        mLSHE->SetDocIdentifier(docIdent);
>-                    }
>-                }


Could you explain this. Why don't we need to update mLSHE anymore?
Ah, ok, seems like the SHEntry is updated a bit later...
Smaug asked me on IRC to comment about the docIdentifier / pageIdentifier change.

pageIdentifier existed before pushState.  Two SHEntries linked by only a difference in hashes have the same page identifier.

When I added pushState, I added document identifiers.  Two SHEntries have the same doc identifier if they had the same page identifier or if they were linked by pushState.

In some sense, the decision to keep both page and document identifiers was the root cause of this bug.  As far as I can tell, there should be no difference between a hash navigation and a pushstate.

The spec says (*) that if we have

  a) foo.html      pushstates to
  b) bar.html      pushstates to
  c) foo.html#bar

and we go back from (c) to (a), we should fire hashchange (because it's navigation within a document). So it's not necessary for us to keep track of the fact that (a) and (c) aren't directly linked by anchor navigations (i.e. that they would have different page identifiers).

(*) http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#history-traversal step 6:

If the specified entry has a URL whose fragment identifier differs from that of the current entry's when compared in a case-sensitive manner, and the two share the same Document object, then let hash changed be true
Attachment #524853 - Flags: review?(Olli.Pettay) → review+
http://hg.mozilla.org/mozilla-central/rev/228d41c97600
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
OS: Windows XP → Android
Hardware: x86 → All
Target Milestone: --- → mozilla6
Version: unspecified → Trunk
OS: Android → All
Depends on: 653741
Depends on: 662094
Did this fix not make it into the FF5 release, even though it was made almost two months earlier?  This problem is still happening, with the same test case.
Correct, the change didn't make it into Firefox 5.  FF5 branched on 4/12, but the change was checked in on 4/20.  The change is in Firefox 6, which is currently in the aurora channel.

The calendar is at https://wiki.mozilla.org/RapidRelease/Calendar  The pipeline is 12 weeks deep, so it takes at most 3 months for a change to make it from trunk to a release.
Glenn, for future reference you can typically see which release a change will be in by looking at the "Target Milestone" field.
Depends on: 694584
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: