[whatwg] Onpopstate is Flawed
Justin Lebar
justin.lebar at gmail.com
Sun Feb 6 10:18:21 PST 2011
> 1) Fire popstates as we currently do, with the caveat that you never
> fire a stale popstate -- that is, if any navigations or
> push/replaceStates have occurred since you queued the task to fire the
> popstate, don't fire it.
>
> Proposal B has the advantage of requiring fewer changes.
The more I think about this, the more I like this option. It's a
smaller change than option A (though again, we certainly could expose
the state object through a DOM property separately from this
proposal), and I think it would be sufficient to fix some sites which
are currently broken. (For instance, I've gotten Facebook to receive
stale popstates and show me the wrong page just by clicking around
quickly.)
Furthermore, this avoids the edge case in option B of "you don't get a
popstate on the initial initial load, but you do get a popstate if
you're reloading from far enough back in the session history, or after
a session restore."
I was concerned that pages might become confused when they don't get a
popstate they were expecting -- for instance, if you pushState before
the initial popstate, a page may never see a popstate event -- but I
think this might not be such a big deal. A call to push/replaceState
would almost certainly be accompanied by code updating the DOM to the
new state. Popstate's main purpose is to tell me to update the DOM,
so I don't think I'd be missing much by not getting it in that case.
I don't know if this is something we can get done in time for FF4, but
I can see.
-Justin
On Wed, Feb 2, 2011 at 3:37 PM, Justin Lebar <justin.lebar at gmail.com> wrote:
> Oh, I think I now understand what Jonas meant.
>
> Proposal A, as I understand it:
>
> 1) Don't fire an initial popstate, because this causes stale popstates
> when pushState is called before the popstate.
>
> 2) Expose the state object to the DOM so pages can find out what the
> initial state is when they load. (The initial state might not be null
> if we're restoring after a crash, or if we're going back in history
> after we unloaded the document.)
>
> 3) Otherwise, fire popstate like normal, once for each navigation.
> (With the caveat that you never want to fire a stale popstate -- that
> is, if any navigations or push/replaceStates have occurred since you
> queued the task to fire the popstate, don't fire it.)
>
> I think we need the caveat in step 3 because firing popstate isn't
> synchronous (step 11 at [1]).
>
> But if we need that caveat, maybe it's better to do what Jonas
> originally proposed. Proposal B:
>
> 1) Fire popstates as we currently do, with the caveat that you never
> fire a stale popstate -- that is, if any navigations or
> push/replaceStates have occurred since you queued the task to fire the
> popstate, don't fire it.
>
> Proposal B has the advantage of requiring fewer changes. (We could,
> of course, add the DOM property later -- it's orthogonal to proposal
> B, but required by proposal A.)
>
> [1] http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#traverse-the-history
>
> On Wed, Feb 2, 2011 at 2:48 PM, Jonas Sicking <jonas at sicking.cc> wrote:
>> On Wed, Feb 2, 2011 at 2:34 PM, Justin Lebar <justin.lebar at gmail.com> wrote:
>>>> So during loading, any script that wants to know what the initial (or
>>>> current) state is does not need to wait for the first popstate, but
>>>> can simply grab the state and go.
>>>
>>> Yeah, I think it's too late to move to this approach.
>>
>> Even if we also include the new state in the popstate events? Such a
>> change seems mostly additive to the current spec.
>>
>>>> My thinking was that if someone calls replaceState, then probably that
>>>> means that they're currently changing the page to represent that new
>>>> state. If they do that then I don't see that they initial popstate
>>>> would help them in any way?
>>>
>>> I agree it's potentially misinformative to give the page a popstate in
>>> this case. But it's possible that a page might be built so that it
>>> doesn't begin to function properly until it receives the initial
>>> popstate. If a user clicks on a link and causes a replaceState call
>>> before the initial popstate, then such a page could break.
>>
>> But with my suggested change, pages have no reason to wait until the
>> initial popstate fires. And in fact they can't since we don't fire it
>> at all :) But yes, I agree that it could break already existing pages
>> that have the above behavior.
>>
>> So the question is if webkit would be ok with such a change.
>>
>>>> So during loading, any script that wants to know what the initial (or
>>>> current) state is does not need to wait for the first popstate, but
>>>> can simply grab the state and go.
>>>
>>> Oh, is this why we needed the initial popstate? For instance, we
>>> persist state objects across session restore, so when the user
>>> restarts, a page could get an onload followed by a popstate with a
>>> non-null state object.
>>>
>>> [Aside: What we currently have doesn't work well for this case, since
>>> the page really needs the state object at the moment it starts to run
>>> script so it can decide what content to load, but it doesn't get the
>>> state object until after onload.]
>>>
>>> If we can't get rid of the initial popstate because of the above, then
>>> I think what Jonas proposed is reasonable. I just wish we had
>>> something with fewer gotchas.
>>
>> I think my latest proposed change makes this a whole lot better since
>> the state is immediately available to scripts. The problem with only
>> sticking the state in an event is that there is really no good point
>> to fire the event. The later you fire it the longer it takes before
>> the page works properly. The sooner you fire it the bigger risk you
>> run that some script runs too late to get be able to catch the event.
>>
>> / Jonas
>>
>
More information about the whatwg
mailing list