Document.write is ignored before DOMContentLoaded while waiting for high latency script loading
I've tried many different ways to tell this question to google and others with no luck. I'm not even sure if the title of this question reflects the nuance of the problem. I'll try to explain, then show the experiment. I hope someone (s) can point to some explanation of what is going on.
- until the end of the BODY, you have a script (A) that programmatically injects a script element (using my preferred technique, document.createElement) into the document that links to the remote script (B)
- remote-script B executes document.write of any content (eg "hello world")
- to the end of BODY and right after script A you have a script (C) that links to a remote-script that takes a while to load (e.g. 1s)
What happens is that A does, inserts B into the document, and starts loading the resource. While B is loading, C will execute and wait, due to the delay. While C is waiting, B is loaded and executed; we haven't gotten to DOMContentLoaded yet; document.readyState is still "loading". Document.write from B is ignored; squeezing like we're after DOMContentLoaded. C finishes loading and executes.
- Source: http://jsfiddle.net/jaknowlden/pwHG8/
- Try it straight out: http://jsfiddle.net/jaknowlden/pwHG8/show/
- Waterfall: MANUAL LINE [cl.ly/423P2M1d0r0e0k3h370g]
- Remote script: MANUAL LINK [thumblemonks.com/js/stackoverflow-script-b.js]
I am using Cuzillion to create a delay. If you look at the waterfall image, you will also see the console.log message, which shows that everything is being executed before the DOM hits the "interactive" readyState (ie DOMContentLoaded).
What I expect as output in the browser:
TOP hello, world hello again, world BOTTOM
What I get as output:
TOP hello, world BOTTOM
In my experiment, you will notice that I added another script between what we will define as A and C. Call it A 'I suppose; it shows that if you add dynamically a script that has text (i.e. not deleted script) that contains document.write, doc.write in 'WILL works.
Also, dummy.js and CSS files come from the JSFiddle. They are not criminals; I can recreate this problem anywhere.
Things I know:
- if you replace C IMG no problem
- if you replace C with IFRAME no problem
- if you move A after C there is no problem
Perhaps there is a well-founded reason for this. It should be, since all the browsers I've tested seem to behave in a similar way. What I would like to know why? Any explanations, hints and / or pointers are appreciated. Even hints like "It's in the spec, dyke :)" I have thick skin; I can handle this.
DISCLAIMER: I hate document.write. My intention is not to support or support its use in any way. However, given the nature of my work, I have to work on it for now, and this weirdness has come over me. Thus, I would like to avoid comments on the line "you should not use document.write", because that is what I already believe in :)
source to share
Executing document.write from scripts loaded with async is not supported in HTML5, precisely because it's simple: you don't know if your script will run before or after DOMContentLoaded. See http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#ignore-destructive-writes-counter and http://www.whatwg.org/specs/web- apps / current-work / multipage / elements.html # dom-document-write step 2 and http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#execute- the-script-block step 3. The thing is, working with writing if the script beats the race to DOMContentLoaded, but ignored if it loses race would be rather strange and would cause the pages to sometimes work and sometimes not depended on network conditions.
source to share
SEC7112: Script from https://raw.github.com/gist/2141272/1a6bf0111ce10d55e628e3736a9d381d82e8a780/external-with-docwrite.js was blocked due to mime type mismatch
It's your problem. Script is passed as
source to share