[whatwg] history.back()

On Thu, 21 Jan 2010, Darin Fisher wrote:
>
> In WebKit, history.back() is currently implemented asynchronously.

It's not clear to me what you mean by "asynchronously".

Do you mean that the events fire asynchronously? That the Location object 
is updated asynchronously? That the decision about whether the call is a 
noop or not is fired asynchronously? That the navigation, if one is 
necessary, is done asynchronously? Are we talking about same-frame, or 
cross-frame? Same-origin, or cross-origin? Traversal from one entry in one 
document to another entry in the same document, or in another document?

I made some demos to test this out, and it seems that IE8 behaves 
differently whether it's cross-frame or same-frame. I'd really rather we 
define this in a way that is consistent for all ways of invoking the API. 
It does the Location changes synchronously if invoked in-page, and 
asynchronously if the traversal affects another page.

For simple cases, Firefox consistently does the Location change 
synchronously. Opera (10.x on Windows), Safari (4 for Windows), and Chrome 
do it async. But complicated cases make these descriptions simplistic.

   http://www.hixie.ch/tests/adhoc/dom/level0/history/sync-vs-async/


> IE however appears to implement history.back() asynchronously in all 
> cases just like newer versions of WebKit.

That doesn't appear to be completely accurate.


> From a web compat perspective, it seems wise to match the behavior of 
> IE. It also has other benefits.
> 
> Can we change the spec?

Yes, but that won't make it async if the goal is to match IE.


On Thu, 21 Jan 2010, Jonas Sicking wrote:
> 
> Sounds good to me. Having all navigation be asynchronous I suspect would 
> have implementations benefits in Gecko too.

It would be a reasonably minor change to the spec. I'm happy to go either 
way on this. The problem is I don't know exactly what "async" vs "sync" 
really means in this context, since the algorithms are quite complicated.


On Thu, 21 Jan 2010, Olli Pettay wrote:
>
> And still one thing to test and specify;
> if history.back()/forward() is asynchronous,
> does that mean that loading start asynchronously,
> or that entries are added asynchronously to session history?
> 
> What should happen if a page calls:
> history.back();
> history.forward();
> 
> What if the page calls:
> history.back();
> history.go(-2);

Indeed. There are the kinds of questions I am curious about.

Another is what should happen if a page goes back() past its fragment 
identifier entries, and then modifies the document or alerts the location? 
What location should it get? Which document should it mutate? (test 007)

How about:

   location.hash = 'a';
   /* spin event loop */
   history.back();
   location.hash = 'b';
   history.forward();
   alert(location.hash);
   /* spin event loop */
   alert(location.hash);

What does this alert? (test 008)

How about:

   location.hash = 'x';
   location.hash = 'a';
   /* spin event loop */
   history.back();
   /* spin event loop */
   history.forward();
   location.hash = 'b';
   /* spin event loop */
   history.back();
   /* spin event loop */
   alert(location.hash);

What does this alert? (test 010)


> And btw, some of the session history handling is anyway synchronous. Per 
> the current HTML5 draft calling document.open() adds a new entry to 
> session history immediately (IIRC, webkit is the only one which doesn't 
> support this).

Another example is navigating to a fragment identifier, which in all 
browsers I tested changes the Location object immediately also.


As I see it these are the criteria that we have to consider here in making 
a decision, in order of importance:

 * Compatibility.
   It seems that browsers are quite inconsistent here, and so it's likely 
   that we have some room to maneuver. Nobody has mentioned any 
   particular bugs in sites caused by implementing this one way or 
   another. I am not convinced that compatibility is a factor at this 
   point.

 * Consistency for authors
   I think whatever solution we come up with we should make sure it is 
   sane for authors. In this case, however, pretty much any model works,
   so this doesn't really help decide what is best, so long as we are 
   consistent in how we specify and implement it.

 * Implementation concerns
   This may be the deciding factor, in particular due to the multiprocess 
   session history issues Darin raised.

 * Specification sanity
   I think we can probably make any model work in the spec, without even 
   much of a rewrite being needed. It's just a matter of saying when 
   things happen, for which the spec now has considerable infrastructure.


Does anyone have any opinions on how the examples above should work? How 
should document.open() and location's setter interact with history.back()? 
Should navigation to fragment identifiers asynchronously set Location? 
Should Location be set synchronously but with the session history actually 
being updated asynchronously using a task, so that .back() and .forward() 
calls get interleaved with the Location setter? Should document.open() 
synchronously clear the session history, or should it asynchronously queue 
a task and do it that way? Should we, instead of using tasks that could 
run much later (e.g. if the script has previously invoked a bunch of 
setTimeout(0)s), add a step to the event loop so that after each task, any 
history traversal that's been queued up gets processed immediately?

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

Received on Friday, 22 January 2010 02:08:53 UTC