Darin Fisher | 6 Jan 01:53 2010

question about the popstate event

I'd like to make sure that I'm understanding the spec for pushState and the popstate event properly.


Suppose, I have the following sequence of events:

1. Page A is loaded.
2. Page A calls pushState("foo", null).
3. The user navigates to Page B.
4. The user navigates back to Page A (clicks the back button once).

Assuming the document of Page A was disposed upon navigation to Page B (i.e., that it was not preserved in a page cache), should a popstate event be generated as a result of step 4?

From my reading of the spec, I would expect the following steps:

5. Page A is loaded.
6. The load event for Page A is dispatched.
7. The popstate event for Page A is dispatched.

Do I understand correctly?

Thanks,
-Darin
Justin Lebar | 6 Jan 03:55 2010
Picon

Re: question about the popstate event

> From my reading of the spec, I would expect the following steps:
> 5. Page A is loaded.
> 6. The load event for Page A is dispatched.
> 7. The popstate event for Page A is dispatched.

I think this is correct.  A popstate event is always dispatched
whenever a new session history entry is activated (6.10.3).

-Justin

On Tue, Jan 5, 2010 at 4:53 PM, Darin Fisher <darin@...> wrote:
> I'd like to make sure that I'm understanding the spec for pushState and the
> popstate event properly.
> Suppose, I have the following sequence of events:
> 1. Page A is loaded.
> 2. Page A calls pushState("foo", null).
> 3. The user navigates to Page B.
> 4. The user navigates back to Page A (clicks the back button once).
> Assuming the document of Page A was disposed upon navigation to Page B
> (i.e., that it was not preserved in a page cache), should a popstate event
> be generated as a result of step 4?
> From my reading of the spec, I would expect the following steps:
> 5. Page A is loaded.
> 6. The load event for Page A is dispatched.
> 7. The popstate event for Page A is dispatched.
> Do I understand correctly?
> Thanks,
> -Darin

Darin Fisher | 13 Jan 00:54 2010

Re: question about the popstate event

Hi,


I've been discussing this issue with Brady Eidson over at https://bugs.webkit.org/show_bug.cgi?id=33224,
and his interpretation appears to be different.  (I think he may have convinced me too.)

I'd really like some help understanding how pushState is intended to work and to see how that lines up
with the spec.

Also, assuming Brady is correct, then I wonder why pushState was designed this way.  It seems strange
to me that entries in session history would disappear when you navigate away from a document that used
pushState.

-Darin


On Tue, Jan 5, 2010 at 6:55 PM, Justin Lebar <justin.lebar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> From my reading of the spec, I would expect the following steps:
> 5. Page A is loaded.
> 6. The load event for Page A is dispatched.
> 7. The popstate event for Page A is dispatched.

I think this is correct.  A popstate event is always dispatched
whenever a new session history entry is activated (6.10.3).

-Justin

On Tue, Jan 5, 2010 at 4:53 PM, Darin Fisher <darin-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
> I'd like to make sure that I'm understanding the spec for pushState and the
> popstate event properly.
> Suppose, I have the following sequence of events:
> 1. Page A is loaded.
> 2. Page A calls pushState("foo", null).
> 3. The user navigates to Page B.
> 4. The user navigates back to Page A (clicks the back button once).
> Assuming the document of Page A was disposed upon navigation to Page B
> (i.e., that it was not preserved in a page cache), should a popstate event
> be generated as a result of step 4?
> From my reading of the spec, I would expect the following steps:
> 5. Page A is loaded.
> 6. The load event for Page A is dispatched.
> 7. The popstate event for Page A is dispatched.
> Do I understand correctly?
> Thanks,
> -Darin

Justin Lebar | 13 Jan 04:30 2010
Picon

Re: question about the popstate event

If I'm understanding the bug correctly, Brady is suggesting not that a
popstate event isn't fired when we navigate back to a document which
has been unloaded from memory, but that the state object in that
popstate event is null.

As I understand it, the crux of his argument relates to the algorithm
to "update the session history with the new page" [1]:

>    2) If the navigation was initiated for entry update of an entry
>
>       1) Replace the entry being updated with a new entry representing
>          the new resource and its Document object and related state.

I think he's arguing that the set of "related state" that is copied to
the new entry does not contain the state object.  His evidence for
this is mostly textual: This state is referenced in other parts of the
spec, and in those places, it's made clear that the state consists of
scroll position and form fields:

(From comment #4 at https://bugs.webkit.org/show_bug.cgi?id=33224)
> I believe "state" in this context is not referring to "state objects", but
> rather "persisted user state" as set forth in 5.11.9 step 3:
> "For example, some user agents might want to persist the scroll position, or
> the values of form controls."

I think this is a good point from a textual perspective.

But I think it's clear that we actually want to persist state objects
across Document unloads.  If we didn't care about this use case, we
could do away with state objects altogether.  A document could just
call pushstate with no state variable and store its state objects in a
global variable indexed by an identifier in the URL.  When the page
receives a popstate, it checks its URL and grabs the relevant state
object.  Simple.  (This doesn't handle multiple entries with the same
URL, but hash navigation doesn't handle that either, so that's not a
big problem.)

My point is that state objects are pretty much useless unless you
persist them after the document has been unloaded.

I also think the fact that we take the structured clone of a state
object before saving it (and that structured clone forbids pointers to
DOM objects and whatnot) indicates that the spec intended for state
objects to stick around after document unload.  Otherwise, why bother
making a restrictive copy?

(It should go without saying that if you're saving state objects
across document unloads, you should also be saving the "has same
document" relationships between history entries.  That is, suppose
history entry A calls pushstate and creates history entry B.  Some
time later, the document for A and B is unloaded, then the user goes
back to B, which is re-fetched into a fresh Document.  Then the user
clicks back, activating A.  We should treat the activation of A from B
as an activation between two entries with the same document, and not
re-fetch A.)

Where the spec needs to be clarified to support this, I think it
should be.  But let's first agree that this is the right thing to do.

-Justin

[1] http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#update-the-session-history-with-the-new-page

On Tue, Jan 12, 2010 at 3:54 PM, Darin Fisher <darin@...> wrote:
> Hi,
> I've been discussing this issue with Brady Eidson over
> at https://bugs.webkit.org/show_bug.cgi?id=33224,
> and his interpretation appears to be different.  (I think he may have
> convinced me too.)
> I'd really like some help understanding how pushState is intended to work
> and to see how that lines up
> with the spec.
> Also, assuming Brady is correct, then I wonder why pushState was designed
> this way.  It seems strange
> to me that entries in session history would disappear when you navigate away
> from a document that used
> pushState.
> -Darin
>
> On Tue, Jan 5, 2010 at 6:55 PM, Justin Lebar <justin.lebar@...> wrote:
>>
>> > From my reading of the spec, I would expect the following steps:
>> > 5. Page A is loaded.
>> > 6. The load event for Page A is dispatched.
>> > 7. The popstate event for Page A is dispatched.
>>
>> I think this is correct.  A popstate event is always dispatched
>> whenever a new session history entry is activated (6.10.3).
>>
>> -Justin
>>
>> On Tue, Jan 5, 2010 at 4:53 PM, Darin Fisher <darin@...> wrote:
>> > I'd like to make sure that I'm understanding the spec for pushState and
>> > the
>> > popstate event properly.
>> > Suppose, I have the following sequence of events:
>> > 1. Page A is loaded.
>> > 2. Page A calls pushState("foo", null).
>> > 3. The user navigates to Page B.
>> > 4. The user navigates back to Page A (clicks the back button once).
>> > Assuming the document of Page A was disposed upon navigation to Page B
>> > (i.e., that it was not preserved in a page cache), should a popstate
>> > event
>> > be generated as a result of step 4?
>> > From my reading of the spec, I would expect the following steps:
>> > 5. Page A is loaded.
>> > 6. The load event for Page A is dispatched.
>> > 7. The popstate event for Page A is dispatched.
>> > Do I understand correctly?
>> > Thanks,
>> > -Darin
>
>

Darin Fisher | 13 Jan 04:37 2010

Re: question about the popstate event

On Tue, Jan 12, 2010 at 7:30 PM, Justin Lebar <justin.lebar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
If I'm understanding the bug correctly, Brady is suggesting not that a
popstate event isn't fired when we navigate back to a document which
has been unloaded from memory, but that the state object in that
popstate event is null.

As I understand it, the crux of his argument relates to the algorithm
to "update the session history with the new page" [1]:

>    2) If the navigation was initiated for entry update of an entry
>
>       1) Replace the entry being updated with a new entry representing
>          the new resource and its Document object and related state.

I think he's arguing that the set of "related state" that is copied to
the new entry does not contain the state object.  His evidence for
this is mostly textual: This state is referenced in other parts of the
spec, and in those places, it's made clear that the state consists of
scroll position and form fields:

(From comment #4 at https://bugs.webkit.org/show_bug.cgi?id=33224)
> I believe "state" in this context is not referring to "state objects", but
> rather "persisted user state" as set forth in 5.11.9 step 3:
> "For example, some user agents might want to persist the scroll position, or
> the values of form controls."

I think this is a good point from a textual perspective.


Ah, yes... agreed.

 
But I think it's clear that we actually want to persist state objects
across Document unloads.  If we didn't care about this use case, we
could do away with state objects altogether.  A document could just
call pushstate with no state variable and store its state objects in a
global variable indexed by an identifier in the URL.  When the page
receives a popstate, it checks its URL and grabs the relevant state
object.  Simple.  (This doesn't handle multiple entries with the same
URL, but hash navigation doesn't handle that either, so that's not a
big problem.)

My point is that state objects are pretty much useless unless you
persist them after the document has been unloaded.

Right!  This is the very perspective I viewed pushState from, and it also
seems to me that the feature is far less useful if state objects are not
persisted after document unload.

-Darin

 

I also think the fact that we take the structured clone of a state
object before saving it (and that structured clone forbids pointers to
DOM objects and whatnot) indicates that the spec intended for state
objects to stick around after document unload.  Otherwise, why bother
making a restrictive copy?

(It should go without saying that if you're saving state objects
across document unloads, you should also be saving the "has same
document" relationships between history entries.  That is, suppose
history entry A calls pushstate and creates history entry B.  Some
time later, the document for A and B is unloaded, then the user goes
back to B, which is re-fetched into a fresh Document.  Then the user
clicks back, activating A.  We should treat the activation of A from B
as an activation between two entries with the same document, and not
re-fetch A.)

Where the spec needs to be clarified to support this, I think it
should be.  But let's first agree that this is the right thing to do.

-Justin

[1] http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#update-the-session-history-with-the-new-page

On Tue, Jan 12, 2010 at 3:54 PM, Darin Fisher <darin-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
> Hi,
> I've been discussing this issue with Brady Eidson over
> at https://bugs.webkit.org/show_bug.cgi?id=33224,
> and his interpretation appears to be different.  (I think he may have
> convinced me too.)
> I'd really like some help understanding how pushState is intended to work
> and to see how that lines up
> with the spec.
> Also, assuming Brady is correct, then I wonder why pushState was designed
> this way.  It seems strange
> to me that entries in session history would disappear when you navigate away
> from a document that used
> pushState.
> -Darin
>
> On Tue, Jan 5, 2010 at 6:55 PM, Justin Lebar <justin.lebar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>
>> > From my reading of the spec, I would expect the following steps:
>> > 5. Page A is loaded.
>> > 6. The load event for Page A is dispatched.
>> > 7. The popstate event for Page A is dispatched.
>>
>> I think this is correct.  A popstate event is always dispatched
>> whenever a new session history entry is activated (6.10.3).
>>
>> -Justin
>>
>> On Tue, Jan 5, 2010 at 4:53 PM, Darin Fisher <darin-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
>> > I'd like to make sure that I'm understanding the spec for pushState and
>> > the
>> > popstate event properly.
>> > Suppose, I have the following sequence of events:
>> > 1. Page A is loaded.
>> > 2. Page A calls pushState("foo", null).
>> > 3. The user navigates to Page B.
>> > 4. The user navigates back to Page A (clicks the back button once).
>> > Assuming the document of Page A was disposed upon navigation to Page B
>> > (i.e., that it was not preserved in a page cache), should a popstate
>> > event
>> > be generated as a result of step 4?
>> > From my reading of the spec, I would expect the following steps:
>> > 5. Page A is loaded.
>> > 6. The load event for Page A is dispatched.
>> > 7. The popstate event for Page A is dispatched.
>> > Do I understand correctly?
>> > Thanks,
>> > -Darin
>
>

Brady Eidson | 13 Jan 05:26 2010
Picon

Re: question about the popstate event


On Jan 12, 2010, at 7:30 PM, Justin Lebar wrote:

> As I understand it, the crux of his argument relates to the algorithm
> to "update the session history with the new page" [1]:
> 
>>   2) If the navigation was initiated for entry update of an entry
>> 
>>      1) Replace the entry being updated with a new entry representing
>>         the new resource and its Document object and related state.
> 
> I think he's arguing that the set of "related state" that is copied to
> the new entry does not contain the state object.  His evidence for
> this is mostly textual: This state is referenced in other parts of the
> spec, and in those places, it's made clear that the state consists of
> scroll position and form fields:
> 
> (From comment #4 at https://bugs.webkit.org/show_bug.cgi?id=33224)
>> I believe "state" in this context is not referring to "state objects", but
>> rather "persisted user state" as set forth in 5.11.9 step 3:
>> "For example, some user agents might want to persist the scroll position, or
>> the values of form controls."
> 
> I think this is a good point from a textual perspective.

My debate with Darin has so far primarily been about how one reads the spec, and this is most certainly how
I've read it.

> <long rant about why state objects should survive document unload, and that state objects are pointless
if they don't>

I think you're totally right.  As I've been discussing the spec with Darin in email and the webkit.org bug
I've basically come to the same conclusion.

That said...

> Where the spec needs to be clarified to support this, I think it
> should be.  But let's first agree that this is the right thing to do.

The discussion between Darin and I was about my interpretation of the spec, what I implemented based on that
interpretation, and how his interpretation was different.  

I think we're now in agreement on what it *should* be, I think the spec should be explicit about it, and I think
the ambiguity between "state," "state object,", and "persisted user state" is what might've led us all to
misread the other's positions. 

"Entry with persisted user state" is already used quite explicitly in two places, but needs application in
key place at the end of 6.11.1.

2 - If the navigation was initiated for entry update of an entry:
	1 - Replace the entry being updated with a new entry representing the new resource and its Document object
and related state. The user agent may propagate state from the old entry to the new entry (e.g. scroll position).

might read:

2 - If the navigation was initiated for entry update of an entry:
	1 - Replace the entry being updated with a new entry representing the new resource and its Document object. 
If the entry being updated is a state object entry the user agent must propagate the state object to the new
entry.  The user agent may propagate persisted user state from the old entry to the new entry (e.g. scroll position).

Thoughts?

~Brady

PS:  On a related note...

> If I'm understanding the bug correctly, Brady is suggesting not that a
> popstate event isn't fired when we navigate back to a document which
> has been unloaded from memory, but that the state object in that
> popstate event is null.

My argument was actually indeed, that the event is not fired at all.  But as I hit up the spec to present my
reasoning why, I discovered that 6.11.9 step 10 basically says that popstate events are fired for *ANY*
history traversal except for fragment scrolls between non-state-object entries.

So my argument shifts to what you say - the state object in that event is null.  This was just sloppy reading on
my part.

That we don't currently fire the popstate event in such cases is a WebKit bug that I have filed as https://bugs.webkit.org/show_bug.cgi?id=33571

> -Justin
> 
> [1] http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#update-the-session-history-with-the-new-page
> 
> On Tue, Jan 12, 2010 at 3:54 PM, Darin Fisher <darin@...> wrote:
>> Hi,
>> I've been discussing this issue with Brady Eidson over
>> at https://bugs.webkit.org/show_bug.cgi?id=33224,
>> and his interpretation appears to be different.  (I think he may have
>> convinced me too.)
>> I'd really like some help understanding how pushState is intended to work
>> and to see how that lines up
>> with the spec.
>> Also, assuming Brady is correct, then I wonder why pushState was designed
>> this way.  It seems strange
>> to me that entries in session history would disappear when you navigate away
>> from a document that used
>> pushState.
>> -Darin
>> 
>> On Tue, Jan 5, 2010 at 6:55 PM, Justin Lebar
<justin.lebar@...> wrote:
>>> 
>>>> From my reading of the spec, I would expect the following steps:
>>>> 5. Page A is loaded.
>>>> 6. The load event for Page A is dispatched.
>>>> 7. The popstate event for Page A is dispatched.
>>> 
>>> I think this is correct.  A popstate event is always dispatched
>>> whenever a new session history entry is activated (6.10.3).
>>> 
>>> -Justin
>>> 
>>> On Tue, Jan 5, 2010 at 4:53 PM, Darin Fisher <darin@...> wrote:
>>>> I'd like to make sure that I'm understanding the spec for pushState and
>>>> the
>>>> popstate event properly.
>>>> Suppose, I have the following sequence of events:
>>>> 1. Page A is loaded.
>>>> 2. Page A calls pushState("foo", null).
>>>> 3. The user navigates to Page B.
>>>> 4. The user navigates back to Page A (clicks the back button once).
>>>> Assuming the document of Page A was disposed upon navigation to Page B
>>>> (i.e., that it was not preserved in a page cache), should a popstate
>>>> event
>>>> be generated as a result of step 4?
>>>> From my reading of the spec, I would expect the following steps:
>>>> 5. Page A is loaded.
>>>> 6. The load event for Page A is dispatched.
>>>> 7. The popstate event for Page A is dispatched.
>>>> Do I understand correctly?
>>>> Thanks,
>>>> -Darin
>> 
>> 


Gmane