Given that it is possible to do this from script, how common is it for
 people to do it from script? If it's very common, that would be a good
 data point encouraging us to do this sooner rather than later.

6 of the top 10 US web sites load scripts after the load event: eBay, Facebook, Bing, MSN.com, MySpace, and Yahoo.

-Steve


On 3/16/2010 5:05 PM, Ian Hickson wrote:
On Tue, 3 Nov 2009, Brian Kuhn wrote:
In section
http://www.whatwg.org/specs/web-apps/current-work/#attr-script-async, it
says:

*Fetching an external script must delay the load event of the element's
document until the task that is queued by the networking task source
once the resource has been fetched (defined above) has been run.*

Has any thought been put into changing this for async scripts?  It seems
like it might be worthwhile to allow window.onload to fire while an
async script is still downloading if everything else is done.
On Fri, 6 Nov 2009, Brian Kuhn wrote:
It seems to me that the purpose of async scripts is to get out of the
way of user-visible functionality.  Many sites currently attach
user-visible functionality to window.onload, so it would be great if
async scripts at least had a way to not block that event.  It would help
minimize the affect that secondary-functionality like ads and web
analytics have on the user experience.
On Wed, 10 Feb 2010, Jonas Sicking wrote:
I'm concerned that this is too big of a departure from how people are
used to<script>s behaving.

If we do want to do something like this, one possibility would be to
create a generic attribute that can go on things like<img>,<link
rel=stylesheet>,<script>  etc that make the resource not block the
'load' event.
On Thu, 11 Feb 2010, Steve Souders wrote:
I just sent email last week proposing a POSTONLOAD attribute for
scripts.
On Thu, 11 Feb 2010, Jonas Sicking wrote:
Though what we want here is a DONTDELAYLOAD attribute. I.e. we want
load to start asap, but we don't want the load to hold up the load
event if all other resources finish loading before this one.
On Fri, 12 Feb 2010, Brian Kuhn wrote:
Right.  Async scripts aren't really asynchronous if they block all the
user-visible functionality that sites currently tie to window.onload.

I don't know if we need another attribute, or if we just need to change
the behavior for all async scripts.  But I think the best time to fix
this is now; before too many UAs implement async.
On Fri, 12 Feb 2010, Nicholas Zakas wrote:
To me "asynchronous" fundamentally means "doesn't block other things
from happening," so if async currently does block the load event from
firing then that seems very wrong to me.
On Fri, 12 Feb 2010, Steve Souders wrote:
ASYNC should not block the onload event. Thinking of the places where
ASYNC will be used, they would not want onload to be blocked.
On Sat, 13 Feb 2010, Darin Fisher wrote:
I don't know... to me, "asynchronous" means completes later.
Precedence: XMLHttpRequest.
On Sat, 13 Feb 2010, Boris Zbarsky wrote:

[...] my real worry about making any loads that don't block onload:
would web developers expect them to?
On Sat, 13 Feb 2010, Brian Kuhn wrote:
FWIW, loading scripts asynchronously with the "Script DOM Element"
approach does not block window.onload in IE.  In Chrome and Safari, the
downloading blocks, but execution doesn't.  In Firefox and Opera,
downloading and execution blocks.

So, it's pretty hard to say what web developers would expect with async
scripts.  I know that they will like having things like ads and
analytics not block window.onload though.  At the very least, we need
that ability to make that happen.
On Sat, 13 Feb 2010, Jonas Sicking wrote:
Yeah, my big concern is "what do developers expect". Having an explicit
attribute for not blocking onload definitely follows the path of least
surprise. Though having an explicit attribute does give Steve more
things to evangelize, i.e. it'll probably lead to more pages firing
onload later than they could.
On Sat, 13 Feb 2010, Darin Fisher wrote:
The thing is, almost all subresources load asynchronously.  The load
event exists to tell us when those asynchronous loads have finished.
So, I think it follows that an asynchronous resource load may reasonably
block the load event.  (That's the point of the load event afterall!)
I've changed the spec to fire 'DOMContentLoaded' without waiting for the
async scripts, so that if you need this you can just listen for that event
instead of 'load'. 'load' still waits for all scripts. 'DOMContentLoaded'
still waits for deferred scripts. As far as I can tell this handles all
the above (still makes sense, still consistent with the way other 'load'
events work, but still lets you do things without waiting).


On Wed, 30 Dec 2009, David Bruant wrote:
The "6.8.1 Client identification" starts with an explanation dealing
with browser-specific bugs and limitation ("browser-specific features"
are missing, aren't they ?) that Web authors are forced to work around.
"Browser-specific features" should be featured-tested, not version-tested.


A very interesting project dealing with these browsers specific
implementations is TestSwarm : http://testswarm.com/

As you may notice, the web browsers are classified this way :
1) Operating system
2) Web Browser (the equivalent of the current "window . navigator . appName")
3) Version (the equivalent of the current "window . navigator . appVersion")

In my opinion, the TestSwarm approach is relevant because a user agent with
the same "appName" and "appVersion" can have OS-specific bugs. However, in the
NavigatorID interface, there is currently no way to detect the operating
system. The current way to detect the operating system is to use the userAgent
String. However, this can be freely overridden in some browsers. As a
consequence, this string cannot be relied at all for OS detection.

To allow OS-specific bugs detection, a property could be added to the
NavigatorID interface.
window.navigator.operatingSystem ? opSysName and opSysVersion ? Name, SubName,
Version, SubVersion ? Something even more detailled ?
It would certainly also be the role of the spec to list the operating systems,
specify the concordant strings and/or give a rule for future and unknown
version and operation systems.
These strings could also be freely overridden in some browsers, so I don't
see why it would be any more reliable.

I'd rather not add yet more features to this particular object. We should
discourage this kind of thing, not encourage it.


On Wed, 20 Jan 2010, David Flanagan wrote:
I'm trying to understand the async and defer attributes of the script
tag. Unfortunately, since script execution is so intimately tied up with
HTML parsing, section 4.3.1 is particularly hard to make sense of. I've
got 3 questions, and 3 suggested clarifications to the spec. Thanks to
anyone who can explain these!

First, my questions.  Are the following three statements correct?  (I'm
only concerned with<script>  tags that actually appear in a document,
not those inserted or emitted (via document.write()) by another
script.):

1) Scripts without async or defer attributes are executed in the order
in which they appear in the document.  They are executed synchronously,
which means that the parser must stop parsing the document while they
run.
Mostly. There are ways to make things happen out of apparent order, e.g.
using document.write() and appendChild(). I'd rather not try to explain
this in detail (in the spec, for authors) because it's likely to be wrong,
and it's likely to cause implementors to ignore the real spec and instead
read the author-facing description. We've already seen this happen
multiple times for the green DOM intro boxes.


2) Scripts with the defer attribute, but without the async attribute are
executed in the order in which they appear in the document, but their
execution is deferred until the document has finished parsing. All these
scripts will execute before DOMContentLoaded and the load event are
fired.  A deferred script can assume that the entire DOM tree has been
constructed and is ready for manipulation--these scripts do not
generally need to register an onload event handler. A call to
document.write() within a deferred script will blow away the current
document and begin a new one.
Sounds right.


3) Scripts with the async attribute are executed as their script content
becomes available over the network, with no guarantee that they will be
executed in the order in which they appear in the document.  The only
guarantee is that these scripts will run before the DOMContentLoaded or
load events are fired. Document parsing may or may not have completed
when an async script is run, and a call to document.write() from an
async script will have unpredictable behavior. Though the order of
execution of async scripts is not predictable, the scripts will always
appear to run in some serial order without concurrent execution.
I just changed the DOMContentLoaded event to fire before the async events.
Other than that it is correct.


Next, I suggest that the following things in the spec be clarified:

1) After describing the async and defer attributes, the spec promises:
"The exact processing details for these attributes are described below."
I take this to mean "below, somewhere in section 4.3".  In fact,
however, the exact processing details are scattered throughout the spec,
and understanding the attributes requires understanding section 9, I
think. It would be nice to note this.
Done.


2) The last sentence of this paragraph:

The second is a flag indicating whether the element was
"parser-inserted". Initially, script elements must have this flag
unset. It is set by the HTML parser and is used to handle
document.write() calls.
made me think that the "parser-inserted" flag would only be set to true
for scripts that were emitted through document.write() calls.  That is,
I thought that the parser-inserted flag would be set only in unusual
cases rather than in the most common case.  This section should explain
the meaning of the parser-inserted flag. Instead it describes one of the
purposes of the flag, but that purpose is different than the purpose for
which it is used in this section.
I've tried to make it less confusing.


3) The algorithm for "running a script" adds scripts to "the list of
scripts that will execute as soon as possible".  And 9.2.6 spins the
event loop until this list is empty.  But I don't see anything in the
spec that removes items from this list.  That seems like an error in the
spec, not just a confusing bit.
Oops. Fixed.


Furthermore, the fact that this mechanism is specified as a "list"
rather than as a "set" implies some kind of sequential execution of the
scripts.  But I don't think any sequence is meant here.
Fixed.


On Mon, 8 Feb 2010, Steve Souders wrote:
I have some comments and questions about the ASYNC and DEFER attributes
of the SCRIPT tag based on reading this document:
http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html
<http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#script>

1. "If neither attribute is present, then the script is fetched and executed
immediately, before the user agent continues parsing the page."
     Thankfully, newer browsers are downloading scripts in parallel with other
resources. I presume the way this is done is they launch a request for a
script and continue to do "speculative" parsing looking for other resources
(images, stylesheets, other scripts, etc.) and launch those requests. But this
nice feature seems to be in conflict with the above text because the browser
continues parsing (albeit speculatively) before the script is executed. It
would be good to mention this optional behavior here, something along the
lines of browsers may want to do speculative parsing, but shouldn't create DOM
elements, etc. - only kickoff HTTP requests.
The spec says:

# Conformance requirements phrased as algorithms or specific steps may be
# implemented in any manner, so long as the end result is equivalent.

# For performance reasons, user agents may start fetching the script as
# soon as the attribute is set, instead, in the hope that the element will
# be inserted into the document. Either way, once the element is inserted
# into the document, the load must have started. If the UA performs such
# prefetching, but the element is never inserted in the document, or the
# src attribute is dynamically changed, then the user agent will not
# execute the script, and the fetching process will have been effectively
# wasted.

...which is intended to allow this. I suppose I could change the last
paragraph quoted above to allow downloads even before elements are
created, if you think that would be better.


2. "If one or both of the defer and async attributes are specified, the src
attribute must also be specified."
     It should be possible to specify DEFER without a SRC. The use case is a
page that has a sequence of SCRIPTs (with and without a SRC attribute) all of
which need to execute in order, but should do so without blocking the parser.
This happens a lot with ads, widgets, and analytics. A workaround is to use
callbacks to daisy-chain the calling sequence, but the complexity will lead
most 3rd party snippet providers to default to a normal SCRIPT tag (without
DEFER or ASYNC) resulting in blocking the parser and slow pages. It's
especially annoying for web site owners to have 3rd party content slowing down
their pages and blocking the content they've created.
     This appears to be a recent change perhaps prompted by Jonas Sicking's
comments that Mozilla found many web sites that specified DEFER without a SRC
and then called document.write (which pretty clearly indicates the developer
didn't mean to specify DEFER). If that's the motivation for this restriction,
we need to either find an alternative syntax or go ahead and allow DEFER
without SRC. Finding an alternative is the worse alternative (DEFER has the
exact behavior we want, so creating something with a different name that
behaves just like DEFER is confusing). If we do move forward with allowing
DEFER without SRC, then we need to specify what happens if it contains
document.write so that the entire document isn't overwritten. (I believe this
is addressed in section 3.5.) There's no good way to make DEFER do what it
should and have those pages who are using DEFER incorrectly work the way they
do now. With this path, at least those pages will have their content appear at
the bottom and not wipe out the entire page.
The reason for the spec being the way it is is indeed as you describe
(well, IIRC it has more to do with innerHTML than document.write(), but
it's similar). However, the problem is non-trivial. Getting compatibility
with legacy content while supporting defer="" on<script>  without src=""
appears to me to be hugely complicated.

It seems pretty easy to work around this limitation by just having
callbacks in the code, though, so I don't really see this as a huge
problem.


3. "[the 'parser-inserted' state] is set by the HTML parser and is used to
handle document.write() calls."
     In what way is this used to handle document.write() calls? Is it for
handling additional SCRIPTs added via document.write, or to make
document.write itself have different behavior? The answer should be added to
the spec somewhere. I searched for .write in this document and didn't find an
explanation.
I removed that comment. To answer your question, though, it's used to
ensure that script run in the right order which affects the insertion
point which affects the way document.write() works.


4. "If the element has a src attribute, [snip] the specified resource must
then be fetched, from the origin of the element's Document."
     If the script has DEFER, the request should not start until after parsing
is finished. Starting it earlier could block other (non-deferred) requests due
to a connection limit or limited bandwidth.
Browsers can prioritise when scripts are loaded, but I think it would be a
mistake to disallow browsers from fetching scripts earlier than load. (To
start with I think they're ignore the requirement.)


5. I don't see any rules for the order of executing scripts added to the
"list of scripts that will execute when the document has finished
parsing" and the "list of scripts that will execute as soon as
possible". DEFER scripts should execute in the order they appear in the
list. ASYNC scripts should be executed as soon as the response is
received.
The rules are implicit in how the lists (the list and the set, now) are
processed.


On Wed, 10 Feb 2010, Steve Souders wrote:
In the current text, it says "must then be fetched". In my suggestion I
say "should not start until after parsing". Saying "should" instead of
"must" leaves the opening for browsers that feel they can fetch
immediately without negatively impacting performance.
"Must be fetched" means it runs the "Fetch" algorithm, which explicitly
says that the download happens "at a time convenient to the user and the
user agent".


On Wed, 10 Feb 2010, Jonas Sicking wrote:
Instead, if the use cases are strong enough, I think we need to
introduce another mechanism for delaying a<script>  to get loaded until
after the 'load' event has fired. I think it's an interesting idea to
add a 'postonload' attribute to all resources, such as<script>,<img>
and<link rel=stylesheet>  (though the maybe the name could be better).
On Mon, 8 Feb 2010, Steve Souders wrote:
I'd like to propose the addition of a POSTONLOAD attribute to the SCRIPT
tag.

The behavior would be similar to DEFER, but instead of delaying
downloads until after parsing they would be delayed until after the
window's load event. Similar to DEFER, this new attribute would ensure
scripts were executed in the order they appear in the document, although
it could be combined with ASYNC to have them execute as soon as the
response is received.
This idea is interesting, but I think it's better for us to wait until
we've seen what browsers do with async="" before adding yet another
feature to<script>. If we add too much at once, browsers will have no
hope of implementing it all correctly. :-)

Given that it is possible to do this from script, how common is it for
people to do it from script? If it's very common, that would be a good
data point encouraging us to do this sooner rather than later.


On Thu, 11 Feb 2010, Mathias Sch�fer wrote:
In a JavaScript tutorial, I wanted to explain what DOMContentLoaded
actually does. But the tests I made revealed that there isn't a
consistent behavior across browsers with regard to stylesheets. In fact,
it's a total mess. These are the results of my tests:

http://molily.de/weblog/domcontentloaded

Please have a quick look at these findings (you can skip the
introduction part). My questions are:

1. Am I right that HTML5 will standardize Opera's pure DOMContentLoaded
model, never waiting for stylesheets? My assumption is that this will
break compatibility with the current Gecko and Webkit implementations.
Scripts can block the whole parser until style sheets have loaded, which
implicitly means the script will wait too, but other than that, yes, the
spec doesn't wait for style sheets for DOMContentLoaded.


2. Does the HTML5 parser specify that external stylesheets defer
external script execution? As far as I understand the specs, it doesn't.
It does, unless I made a mistake.


In Gecko and IE, the loading of stylesheets also defers the execution of
subsequent *inline* scripts. I haven't found a rule for that in the
HTML5 parsing algorithm either. Does it conform to the specs, is it
against the rules or a legitimate extension which is not covered by
HTML5?
The spec does require that. Search for "a style sheet blocking scripts".


On Wed, 10 Feb 2010, Boris Zbarsky wrote:
http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#running-a-script
step 8 the cases that talk about "a style sheet blocking scripts"
specify this.

I really wish those steps had individual IDs, and so did the cases
inside them.  It'd make it a lot easier to link to them!
Added. Let me know if you think anything else needs them. (I don't want to
automatically add them to every paragraph because the resulting bloat is
excessive.)


On Thu, 11 Feb 2010, Mathias Schäfer wrote:
The question is: Is a normal external script “parser-inserted” or not?
I assume the flag to be false, since that’s the default value and I
found “parser-inserted” to be true for XML parsing only
(#parsing-xhtml-documents). Correct?
I've changed the comment near the definition of the term to be clearer. I
hope that helps.


Just to translate from HTML5 speak into my own words. I’ve got ...

<link rel="stylesheet" href="...">
<script src="..."></script>

... and I would like to step through the parsing algorithm. This is my
understanding so far:

1. Run the script (#parsing-main-incdata, case “An end tag whose tag
name is "script"”)
You missed the<script>  start tag processing, which sets the
"parser-inserted" flag:

    
http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#scriptTag


That means, inline script execution should also wait for stylesheets to
load. Am I right in this reading?
Yes.

Reply via email to