[whatwg] Onpopstate is Flawed

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
>

Received on Wednesday, 2 February 2011 15:37:14 UTC