Re: Executing script-inserted external scripts in insertion order

Adam Barth wrote:
> I see. I missed the point about there being two timescales.

I'm thinking of four times:

 * The present. The most important concern is what needs to be done to support existing deployment of LABjs and the "order" plug-in for RequireJS. Not necessarily for the benefit of JS developers but for the benefit of browser users who come into contact with sites that use pre-existing versions of LABjs and the "order" plug-in for RequireJS.

 * The future. I think we should get to a future where 1) all browsers implement script running per spec (not necessarily per today's spec draft) and 2) the use case that LABjs and the "order" plug-in for RequireJS try to addressed is addressed by the spec.

 * The time between the present and the future. I think there should be a way from getting from here to there that doesn't require prospective UA sniffing/inference. That is, if we specced the future today, there should be a way for LABjs to capability-sniff for the future traits. The problem I have with simply speccing that script-inserted external script that don't have the async attribute maintain order among themselves is that it gives no way for LABjs to prepare for WebKit and IE implementing the spec at a later date.

 * The time after the future. We should minimize the cruft accumulated as a side effect of getting from the present to the future so that it doesn't haunt us after we've gotten to the future.

James Graham wrote (on IRC):
> <jgraham> Doesn't it make more sense to make preserving order the default
> <jgraham> and opt-in to racy behaviour?
> * jgraham reads again
> <jgraham> Specifically the script-inserted exteral scripts blocking parser-inserted scripts part
> <jgraham> Although I suppose the percieved problem with the safe solution is that it will not be accepted by WebKit/IE

"Please leave your sense of logic at the door, thank." :-)
More seriously, it really doesn't make sense to make script-inserted external scripts and parser-inserted scripts to maintain order by default (probably not at all). Since WebKit and IE taken together have non-trivial market share, Web authors can't rely on the stronger ordering provided by Opera and Firefox 3.6. When authors have to develop for the weaker guarantee anyway, the result is that authors can't benefit from the stronger guarantee but it still carries a perf penalty. Specifically, Gecko (and presumably Opera, though I didn't investigate) loses to IE and WebKit in perf if the page author follows the advice from http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/ but also has an additional parser-inserted script after the performance recipe. Gecko doesn't lose if the page author uses RequireJS instead (without the "order" plug-in!), because RequireJS sets async to true on scripts when ordering isn't specifically requested.

It doesn't make sense to make script-inserted inline script maintain order relative to script-inserted external scripts by default. The reason is that it's bad when a typically synchronous operation becomes asynchronous depending on what has happened before. In the typical case, a script-inserted inline script is evaluated synchronously. However, if order is maintained as in Firefox 3.6, the operation becomes asynchronous if there happens to be a pending external script. This leads to subtle and surprising-to-debug problems. In fact, this scenario causing a site to break was what prompted the implementation of HTML5-compliant script running in a hurry between Firefox 4 beta 6 and beta 7.

Maciej Stachowiak wrote:
> On Oct 8, 2010, at 11:35 AM, Boris Zbarsky wrote:
> 
> > On 10/8/10 2:24 PM, Maciej Stachowiak wrote:
> >> Whether or not we added Henri's proposed opt-in feature, it seems
> >> like HTML5 should specify the IE/WebKit behavior for unknown type
> >> attribute, unless there is some compelling reason to go with the
> >> Gecko behavior.
> >
> > There sort of is... The gecko behavior doesn't involve making a
> > network request for data you then plan to do nothing with, right?
> > Whereas the IE/Webkit behavior involves doing just that, as far as I
> > can see.
> 
> Is it common to use unknown script types on external scripts for
> purposes other than preloading the script (as these libraries seem to
> do)? I guess there might be pages with unconditional includes of
> vbscript, but I don't know how typical this is.

One option would be speccing a special case for the bogus types already in use (at least script/cache; are there others?) and support preloading those instead of preloading all unknown types.
Maciej Stachowiak wrote:
> Whether or not we added Henri's proposed opt-in feature, it seems like
> HTML5 should specify the IE/WebKit behavior for unknown type
> attribute, unless there is some compelling reason to go with the Gecko
> behavior. The mix of choices in the spec leaves no way to even emulate
> ordered script loading.

Note that speccing the IE/WebKit behavior for unknown types (or just for script/cache) wouldn't permit Opera and Gecko to implement the spec without willful violation and support existing content. If we want a situation where all browsers can implement the spec without willful violations and support existing content without constraining how -moz-appearance is reflected in CSSOM or how the opera object stringifies, we should put in the spec *both* the thing that makes the IE/WebKit code path of LABjs work *and* the thing that makes the Gecko/WebKit code path of LABjs work. That is, that's what we want, the spec should say that script-inserted external scripts that don't have the async attribute maintain insertion order among themselves *and* trying to load a script with type=script/cache causes the file to be fetched into cache and the the load event to be fired.

Would WebKit and IE implement the spec if it required script-inserted external scripts that don't have the async attribute to maintain order among themselves (with the async attribute as an opt-out mechanism for requesting unordered behavior) and also required at least type=script/cache to be fetched? If WebKit and IE were willing to do this, adding the 'ordered' DOM property that I proposed would not be worthwhile. However, then the question would be: How could a LABjs version released before WebKit or IE complied with the edited spec capability-sniff ordered execution so that a LABjs version written after the spec change but before WebKit/IE changes would put WebKit or IE on the code path the relies on ordered execution once WebKit or IE complied?

Boris Zbarsky wrote:
> Yes, which is why in the short term Gecko is doing the willful spec
> violation thing. Then we'd ship a version that has "ordered" _and_ the
> spec violation. Then we'd ship a version that just does "ordered" and
> hope/push for sites to update to a working labjs.

This was my thinking, yes. It's a rather optimistic approach, since it assumes we would be able to get sites to update LABjs and RequireJS *and* that in the meantime more JS code relying on UA sniffing and ordered execution wouldn't crop up.

It may well be worthwhile to consider a pessimistic approach that starts with the assumption that Gecko and Opera won't be able to get rid of ordered execution of script-inserted external scripts that don't have the async attribute and that IE and WebKit won't be able to get rid of supporting preloading text/cache scripts.
-- 
Henri Sivonen
hsivonen@iki.fi
http://hsivonen.iki.fi/

Received on Monday, 11 October 2010 08:38:07 UTC