[whatwg] scripts, defer, document.write and DOMContentLoaded

Jonas Sicking jonas at sicking.cc
Mon Jul 27 21:17:04 PDT 2009

On Mon, Jul 20, 2009 at 7:25 PM, Ian Hickson<ian at hixie.ch> wrote:
> On Tue, 7 Jul 2009, Jonas Sicking wrote:
>> What's tricky is that a document.write inside a deferred script in IE
>> will in some circumstances clear the current document, in other cases
>> append to it. Specifically it seems that if the page has ever set
>> .innerHTML on any node then document.write in the deferred script will
>> append to the current page. If .innerHTML has never been set, then it
>> will replace the current page.
> Actually what's going on is more subtle than that. When you set innerHTML,
> it's actually triggering the deferred scripts right there, if it has them
> loaded (e.g. inline scripts or cached scripts). If it doesn't have them
> loaded yet, it drops them on the floor and doesn't ever run them.
> I've specced this, except that the spec requires that not-yet-loaded
> scripts be loaded then run, rather than dropped, before innerHTML
> continues, so there's no race conditions.

Erm, I would really not like to do this. innerHTML is an very popular
method used by web developers, so adding unexpected (to say the least)
behavior like this I think will be a great source of developer bugs.
And as others have pointed out, making it wait on network traffic
synchronously is simply not acceptable.

>> * Don't fire DOMContentLoaded until all deferred scripts have executed.
>> * Possibly hold off firing DOMContentLoaded until any outstanding
>> scripts have finished loading and executing.
> I've done this. In fact, I've made it wait until all scripts that were
> pending when the parsing finished have been run.
> (You mentioned .readyState; I haven't changed that, since it makes the
> 'interactive' state far less useful if it only gets set once all the
> scripts have run but before the images have loaded. Being able to detect
> when or whether parsing has finished while running deferred scripts does
> seem useful. Hopefully it's not too much rope.)

Sounds ok. As long as .readyState is changed before any deferred
scripts are executed (in order to avoid race conditions).

>> * Always execute elements in the order they are inserted into the
>> Document, with exception of async and deferred scripts.
> I haven't done this, because people use document.appendChild() of external
> scripts specifically to have scripts run "ASAP" and not necessarily in
> order.

I'm always wary of adding race conditions, and I think that's exactly
what we're adding here. The use case of running scripts ASAP is
already supported by using the "async" attribute.

> In general, I am very wary of changing this part of the spec, as it was
> written with extreme care based on all the tests I could run, primarily on
> IE, but also on other browsers. The innerHTML thing, though... I'll admit
> I really didn't even remotely think that there could be something to test!

My experience implementing deferred scripts and shipping support in
firefox 3.5 is that IE behavior is not needed here. I'd like to see
data showing otherwise before making innerHTML significantly more
confusing to developers (or significantly less performant if we do the
sync network thing) given how commonly used it is.

We immediately noticed when document.write in deferred scripts blew
away the full document, even before shipping a beta. Once we made it
append to the end of the document we have not had a single problem
reported. This several weeks after final shipping of firefox 3.5.

/ Jonas

More information about the whatwg mailing list