Last Comment Bug 785243 - script execution order is incorrect if a script contains a sync xhr call
: script execution order is incorrect if a script contains a sync xhr call
Status: UNCONFIRMED
DUPEME
:
Product: Core
Classification: Components
Component: DOM: Core & HTML (show other bugs)
: 14 Branch
: x86 Mac OS X
: -- normal (vote)
: ---
Assigned To: Nobody; OK to take it and work on it
:
Mentors:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2012-08-23 15:03 PDT by sameershah25
Modified: 2012-08-23 16:08 PDT (History)
3 users (show)
See Also:
Crash Signature:
(edit)
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---


Attachments

Description sameershah25 2012-08-23 15:03:08 PDT
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.82 Safari/537.1

Steps to reproduce:

I have 2 javascript files. Lets call it script1.js and script2.js. I want to make sure that they execute in order(script1.js first and then script2.js). So I set async attribute to false for both of them. However in a particular scenario this is not happening. 

Here is the javascript method that insert the script tags

function loadJavascript() {
                var script1 = document.createElement("script");
                script1.async=false;
                script1.src = "/html/js/script1.js";
				script1.finished = false;
                script1.onload = script1.onreadystatechange = function() {
					if ((script1.readyState && script1.readyState != "complete" && script1.readyState != "loaded") || script1.finished) return;
					script1.onload = script1.onreadystatechange = null;
					console.log("script1 finished executing");
					script1.finished =true;
				};

                var script2 = document.createElement("script");
                script2.async=false;
                script2.src = "/html/js/script2.js";
				script2.finished = false;
				script2.onload = script2.onreadystatechange = function() {
					if ((script2.readyState && script2.readyState != "complete" && script2.readyState != "loaded") || script2.finished) return;
					script2.onload = script2.onreadystatechange = null;
					console.log("script2 finished executing");
					script2.finished =true;
				};
				var head = document.head;
                head.appendChild(script1);
                head.appendChild(script2);
        }
 
script1.js

(function(){
	console.log("script1 evaluating");
	var http = new XMLHttpRequest();
	http.open('GET', '/html/js/script3.js', false);
	var data = http.send(null);
    eval(http.responseText); 
})();

script2.js

(function(){
	console.log("script2 evaluating");
})();

script3.js

(function(){
})();


Actual results:

First time the execution order was correct. I see following thing in firebug

script1 evaluating
GET http://10.194.176.9/html/js/script3.js
script1 finished executing
script2 evaluating
script2 finished executing

However second time onwards once all the scripts are cached I always see the following order. Here you will see the execution order of script2 and script1 is reversed.

script1 evaluating
GET http://10.194.176.9/html/js/script3.js
script2 evaluating
script2 finished executing
script1 finished executing



Expected results:

The execution order of script1 and script2 should not have reversed as I am using async=false.
Comment 1 Olli Pettay [:smaug] (high review load, please consider other reviewers) 2012-08-23 15:43:46 PDT
(Sync XHR should be avoided because it is bad for the UX.)
Comment 2 sameershah25 2012-08-23 15:51:18 PDT
(In reply to Olli Pettay [:smaug] from comment #1)
> (Sync XHR should be avoided because it is bad for the UX.)

I agree that sync calls should be avoided. But we are using dojo 1.6 heavily in our project which uses sync xhr calls to download the scripts when dojo.require is called. We can't upgrade to higher versions of dojo (which uses AMD) yet because it will require some time to resolve all the regressions. Thus we can't avoid these sync calls. I have presented here minimal code so it could be easily debugged.
Comment 3 Boris Zbarsky [:bz] (Out June 25-July 6) 2012-08-23 15:54:09 PDT
There's nothing to debug, really: sync XHR spins the event loop, so events (including async script execution and whatnot) can fire under a sync XHR call....
Comment 4 sameershah25 2012-08-23 16:08:15 PDT
(In reply to Boris Zbarsky (:bz) from comment #3)
> There's nothing to debug, really: sync XHR spins the event loop, so events
> (including async script execution and whatnot) can fire under a sync XHR
> call....

Please pardon my ignorance. I didn't understand when you said "spins the event loop". I was expecting that when a synchronous xhr request is sent, execution blocks until the request is done. But in firefox instead it starts evaluating the
next script in the order which seems to be incorrect as current script execution is not yet finished.

The above works perfectly fine in google chrome as expected.

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