Last Comment Bug 871719 - document.write of script tags after a Synchronous XHR will misplace the tags
: document.write of script tags after a Synchronous XHR will misplace the tags
Status: NEW
: regression
Product: Core
Classification: Components
Component: HTML: Parser (show other bugs)
: 14 Branch
: x86 Mac OS X
: -- normal (vote)
: ---
Assigned To: Nobody; OK to take it and work on it
:
: Andrew Overholt [:overholt]
Mentors:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2013-05-13 13:01 PDT by thanpolas
Modified: 2015-10-20 00:54 PDT (History)
3 users (show)
See Also:
Crash Signature:
(edit)
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---


Attachments

Description thanpolas 2013-05-13 13:01:15 PDT
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31

Steps to reproduce:

As a javascript file executes synchronously, it issues 5 "document.write()" commands to load 5 different script files using the <script> tag.

When the writes have performed the script continues to load another file using a Synchronous XHR call.

At the callback of the XHR a final "document.write()" is performed that calls a defined callback:

  document.write('<script>doStuff();</script>');


Actual results:

The order of the script tags has been misplaced, resulting in files 2 through 5 to load AFTER the 'doStuff' invocation and produce ReferenceError exceptions.

    <script src="script.js"></script>
    <script type="text/javascript" src="moduleA.js"></script>
    <script type="text/javascript">doStuff();</script>
    <script type="text/javascript" src="moduleB.js"></script>
    <script type="text/javascript" src="moduleC.js"></script>
    <script type="text/javascript" src="moduleD.js"></script>
    <script type="text/javascript" src="moduleE.js"></script>    



Expected results:

The script tags should be in order and vars defined in files 2 through 5 available when 'doStuff()' is invoked.

    <script src="script.js"></script>
    <script type="text/javascript" src="moduleA.js"></script>
    <script type="text/javascript" src="moduleB.js"></script>
    <script type="text/javascript" src="moduleC.js"></script>
    <script type="text/javascript" src="moduleD.js"></script>
    <script type="text/javascript" src="moduleE.js"></script>    
    <script type="text/javascript">doStuff();</script>
  
A showcase of the issue can be found in this plunk: http://run.plnkr.co/plunks/qcgwOGHh6yDDHBPUEtVT/
Comment 1 Loic 2013-05-13 17:27:56 PDT
Regression range:
m-c
good=2012-03-22
bad=2012-03-23
http://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=5c13fce74f83&tochange=ab2ff3b5611f
Comment 2 Alice0775 White 2013-05-13 19:22:27 PDT
At least, I can reproduce the behavior in Firefox6.0 intermittently. (It is necessary to remove the command that is not implemented in Fx6). I do not test in Firefox5 and earlier yet.
Comment 3 Alice0775 White 2013-05-13 20:27:28 PDT
And I can also reproduce in Firefox4 and 5 intermittently.

I think that you should need to add async=false in <script>.

See, https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/4?redirectlocale=en-US&redirectslug=Firefox_4_for_developers#Miscellaneous_DOM_changes

"<script> elements created using document.createElement() and inserted into a document now behave according to the HTML5 specification by default. Scripts with the src attribute execute as soon as available (without maintaining ordering) and scripts without the src attribute execute synchronously. To make script-inserted scripts that have the src attribute execute in the insertion order, set .async=false on them."
Comment 4 Loic 2013-05-14 01:16:09 PDT
Thanks, invalid bug probably.
Comment 5 thanpolas 2013-05-14 02:53:33 PDT
Alice "document.write()" is used, the "async" attribute is not applicable in this case.
Comment 6 Alice0775 White 2013-05-14 02:56:57 PDT
I mean in script.js
    out += ' async=false  src="' + pathPrefix + src + '">';
Comment 7 thanpolas 2013-05-14 02:59:07 PDT
"out" is a string which is used as the argument for "document.write". The "async" attribute does not apply to this case.
Comment 8 thanpolas 2013-05-14 03:05:04 PDT
I updated the script.js to use "async=false" and the case passes now.

Still i believe that's an issue, the default value for async should be "false" when using document.write(), a lot of infrastructure rely on this fact.

There's a distinctive difference between inserting script elements using document.createElement() at any point in time, and inserting script elements using document.write at parse time, before DomContentLoaded has fired.
Comment 9 Henri Sivonen (:hsivonen) 2013-05-14 06:16:28 PDT
(In reply to Alice0775 White from comment #6)
> I mean in script.js
>     out += ' async=false  src="' + pathPrefix + src + '">';

No, no. That sets async to true for a script given as markup. For parser-created scripts, the default is false. The dot in .async=false is not a typo. It only works as a DOM property for nodes created with document.createElement() (for which the default is true).
Comment 10 Henri Sivonen (:hsivonen) 2013-05-14 06:21:27 PDT
(In reply to thanpolas from comment #8)
> I updated the script.js to use "async=false" and the case passes now.

That's really weird. Maybe you ended up changing the timing.

Anyway, synchronous XHR can cause all sorts of oddities. It's supported, because legacy code relies on it. Never use it when writing new code.
Comment 11 thanpolas 2013-05-14 06:37:35 PDT
I removed the "async=false" so the issue gets illustrated again.

> Anyway, synchronous XHR can cause all sorts of oddities. It's supported, because legacy code relies on it. Never use it when writing new code.

As much as i'd like to avoid it, it is essential and required to what i do. 

Also, it's the first time that i learn that synchronous XHR is legacy. There is no such mention or hinting in MDN and to be frank, i'd like it to always be there.

Nevertheless, the issue is there, and it only appears in Firefox, all other browsers will properly handle this.
Comment 12 Ryan VanderMeulen [:RyanVM] 2015-10-15 19:17:56 PDT
Is this wontfix based on your comments?
Comment 13 Henri Sivonen (:hsivonen) 2015-10-20 00:54:41 PDT
(In reply to Ryan VanderMeulen [:RyanVM UTC-4] from comment #12)
> Is this wontfix based on your comments?

Low priority but not WONTFIX. That is, if someone figures out a reasonably non-invasive fix, we should probably take it.

(In reply to thanpolas from comment #11)
> Also, it's the first time that i learn that synchronous XHR is legacy. There is no such mention or hinting in MDN

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#open%28%29 now says "Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchronous requests on the main thread have been deprecated due to the negative effects to the user experience."

The spec (https://xhr.spec.whatwg.org/#the-open%28%29-method) says: "Synchronous XMLHttpRequest outside of workers is in the process of being removed from the web platform as it has detrimental effects to the end user's experience. (This is a long process that takes many years.) Developers must not pass false for the async argument when the JavaScript global environment is a document environment. User agents are strongly encouraged to warn about such usage in developer tools and may experiment with throwing an InvalidAccessError exception when it occurs. "

Note You need to log in before you can comment on or make changes to this bug.