loge.hixie.ch

Hixie's Natural Log

2006-08-10 07:31 UTC Tag Soup: appendChild() of a script that calls document.write()

Imagine a script:

<script>
  var element = document.createElement('script');
  element.src = 'test.js';
  document.body.appendChild(element);
</script>

This script appends an element to the DOM. The element is itself a script element, which refers to an external script. Imagine that the external script is the following:

document.write("TEST")

What will happen? What should I put in the spec?

Try this out.

Internet Explorer
The text "TEST" will be inserted into the document whenever the tokeniser happens to be. Most notably, in this case, inside an attribute. Non-deterministic behaviour that depends on packet boundaries. We can't put this in the spec.
Firefox
The text "TEST" will be inserted into the document whenever the tokeniser happens to be, except if it's in the middle of the token, in which case it'll insert it before that token, then reparse. Non-deterministic behaviour that depends on packet boundaries. We can't put this in the spec.
Opera
The script blocks the parser until it's executed, so the text gets inserted immediately after the original block. Not asynchronous. Since IE is asynchronous on this, it is likely that most uses of this construct are looking for asynchronous loading. So we can't use this on the spec.
Safari
I can't quite work out what Safari does, exactly; in this particular test it doesn't write the content anywhere at all as far as I can tell. Not clear what is happening, so we can't use this for the spec.

This isn't academic. Dojo does this, for example (see bootstrap2.js). A lot of other pages do this. Most pages do it after the load event has fired, at which point it's well defined, but there are some that do it while the page is loading. I have no idea what the spec should say. I think probably the best thing to do is to say that document.write() in this situation implies a document.open(), much as we're saying for document.write() being called from setTimeout() functions or event handlers. But no browser does this today, so will that break pages?