Bug 28328

Summary: javascript execution sequence.
Product: WebKit Reporter: Derk-Jan Hartman <hartman.wiki>
Component: DOMAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: ahmad.saleem792, ap, beidson, bfulgham, eric, marcus, mjs, oliver, pkasting, rniwa, sam, simonjam
Priority: P2    
Version: 525.x (Safari 3.2)   
Hardware: Mac (Intel)   
OS: OS X 10.5   
URL: http://nerget.com/bugs/bug28328/index.html

Description Derk-Jan Hartman 2009-08-14 15:50:55 PDT
I see a race condition in the following case.

Master script in head.

This master script changes the DOM (adding spans and divs) after DOMContentLoaded.
I import a second script AFTER changing the DOM. with this:

function importScriptURI(url) {
	var s = document.createElement('script');
	s.setAttribute('src',url);
	s.setAttribute('type','text/javascript');
	document.getElementsByTagName('head')[0].appendChild(s);
	return s;
}

This second script needs to change and see the added DOM elements in order to function.
This works just fine on Firefox, but on Safari, it seems that execution of both the master and the "child" javascript are started in paralel. Sometimes, the new dom elements are seen by the child script, sometimes they are missing. It might be that there is a workaround, but I have not been able to find any. This can be a very difficult issue to trigger, and slower computers, high load or very large and complicated multi level javascript inclusions seem often required to be able to actually observe the problem. (On wikipedia, in a complicated situation I see it maybe 1 in 15 page loads.)
Comment 1 Oliver Hunt 2009-08-14 16:01:34 PDT
This causes issues with the MS ES5 conformance test
Comment 2 Alexey Proskuryakov 2009-08-14 22:02:41 PDT
This needs test cases. The only case that I know that may _potentially_ result in something that looks like parallel script execution is something that happens during a sync operation (alert, XMLHttpRequest etc).
Comment 3 Oliver Hunt 2009-08-14 22:17:51 PDT
Here's a testcase -- firefox executes all the created script tags in the order that they are attached to the document -- http://nerget.com/bugs/bug28328/index.html
Comment 4 Derk-Jan Hartman 2009-08-15 03:51:28 PDT
(In reply to comment #3)
> Here's a testcase -- firefox executes all the created script tags in the order
> that they are attached to the document --
> http://nerget.com/bugs/bug28328/index.html

This isn't even THAT much of a problem, this would be acceptable in many cases. HOWEVER, if inclusion of script #2 is conditional upon the execution path of script #1, then you still see this "arbitrary" execution order. The execution of script #2 is started before the DOM work of script #1 is available to script #2, even though the addition of script #2 is a DOM change in itself.
Comment 5 Oliver Hunt 2009-08-15 11:30:21 PDT
(In reply to comment #4)
> (In reply to comment #3)
> > Here's a testcase -- firefox executes all the created script tags in the order
> > that they are attached to the document --
> > http://nerget.com/bugs/bug28328/index.html
> 
> This isn't even THAT much of a problem, this would be acceptable in many cases.
> HOWEVER, if inclusion of script #2 is conditional upon the execution path of
> script #1, then you still see this "arbitrary" execution order. The execution
> of script #2 is started before the DOM work of script #1 is available to script
> #2, even though the addition of script #2 is a DOM change in itself.

The firefox behaviour was being given as an example of correct behaviour -- webkit executes the attached scripts in order of load completion it seems.  This makes us different from all other browsers, and this behaviour has already bitten me while working on one of my js demos.
Comment 6 Alexey Proskuryakov 2009-08-15 22:52:54 PDT
Oliver, it doesn't seem that the issue you are describing is at all related to what was reported here.
Comment 7 Alexey Proskuryakov 2009-12-29 22:27:50 PST
This sounds like a duplicate of bug 28783, but the randomness reported here is a separate twist.
Comment 8 Peter Kasting 2010-01-06 14:25:29 PST
Someone reported http://code.google.com/p/chromium/issues/detail?id=31701 which sounds something like this.  They attached a testcase there that may be useful here.
Comment 9 Peter Kasting 2010-01-06 14:46:33 PST
The person who filed the Chromium bug is a Googler whose project is impacted by this issue.  Not sure who the right people are for script execution scheduling (adding two that Mike Belshe suggested), or if this is just a dupe of bug 28783, but it'd be nice to fix.
Comment 10 Maciej Stachowiak 2010-01-06 16:16:18 PST
For what it's worth, a possible workaround is to put a "load" event handler on the first script element and not start the second script until it fires.

Since this has come up multiple times as a compatibility issue, we should fix it though.
Comment 11 James Simonsen 2010-12-02 15:03:41 PST
There are two separate issues here.

I'm particularly interested in the randomness in the original report. Would you happen to still have a test case for that? Do you remember if any of the scripts were inline?

The other test cases cited here aren't actually bugs according to HTML5. HTML5 doesn't guarantee dynamically added external scripts will be executed in order.

(In reply to comment #3)
> Here's a testcase -- firefox executes all the created script tags in the order that they are attached to the document -- http://nerget.com/bugs/bug28328/index.html

This can be fixed using async=false from: https://bugs.webkit.org/show_bug.cgi?id=50115

(In reply to comment #8)
> Someone reported http://code.google.com/p/chromium/issues/detail?id=31701 which sounds something like this.  They attached a testcase there that may be useful here.

This example is exactly like the one here: https://bugs.webkit.org/show_bug.cgi?id=28783. As mentioned by Maciej, the load handler is the best way to address it.
Comment 12 Ahmad Saleem 2022-08-16 16:03:58 PDT
Based on attached test case from URL Field, please refer to results across browsers:

*** Safari Technology Preview 151 ***

Loading 0.js
Loading 1.js
Loading 2.js
Loading 3.js
Loading 4.js
Loading 5.js
Loading 6.js
Loading 7.js
Loading 8.js
2nd script tag
1
2
3
5
4
6
7
8
9
0

Remained same in refresh on second load.

*** Safari 15.6 on macOS 12.5 ***

In Private Window - First Load:

Loading 0.js
Loading 1.js
Loading 2.js
Loading 3.js
Loading 4.js
Loading 5.js
Loading 6.js
Loading 7.js
Loading 8.js
2nd script tag
2
7
3
5
4
1
6
9
8
0

Refresh - Second Load:

Loading 0.js
Loading 1.js
Loading 2.js
Loading 3.js
Loading 4.js
Loading 5.js
Loading 6.js
Loading 7.js
Loading 8.js
2nd script tag
1
2
3
4
5
6
7
8
9

*** Chrome Canary 106 ***

In Private Mode - First Load:

Loading 0.js
Loading 1.js
Loading 2.js
Loading 3.js
Loading 4.js
Loading 5.js
Loading 6.js
Loading 7.js
Loading 8.js
2nd script tag
5
2
1
3
6
4
7
8
9
0

Second - Refresh:

Loading 0.js
Loading 1.js
Loading 2.js
Loading 3.js
Loading 4.js
Loading 5.js
Loading 6.js
Loading 7.js
Loading 8.js
2nd script tag
0
1
2
3
4
5
6
7
8
9

*** Firefox Nightly 105 ***

In Private Window - First Load:

 Loading 0.js
Loading 1.js
Loading 2.js
Loading 3.js
Loading 4.js
Loading 5.js
Loading 6.js
Loading 7.js
Loading 8.js
2nd script tag
1
2
3
4
5
6
9
8
7
0

Second Load - Refresh:

 Loading 0.js
Loading 1.js
Loading 2.js
Loading 3.js
Loading 4.js
Loading 5.js
Loading 6.js
Loading 7.js
Loading 8.js
2nd script tag
0
1
2
3
4
5
6
7
8
9

_____

I am not sure on web-spec but just wanted to share updated test results. Thanks!