Unexpected asynchronous script execution
17:14
I spent today debugging strange JavaScript behaviour in Firefox. The scenario was as follows:
The main interface of the app I’m working on loads document fragments on demand. These fragments contain script blocks. We use jQuery to load these fragments.
When jQuery.append
ing a new fragment into the DOM jQuery cleverly extracts all script nodes from the fragment and then synchronously executes them in the order they appear, regardless if their source is external or inline, and only after all scripts have been evaluated returns. A blocking operation, which in our case is what we want.
The script handling the main interface (and pulling in the needed bits) depends on this behaviour —(which might be silly and could be avoided by redesigning the architecture, but that’s a different story)— and today it broke for no apparent reason. After some hours of peeking and poking I found the culprit to be Facebooks’ loader script which appends more scripts with external sources into the DOM. The fact that the script came from Facebook is irrelevant here, the injected script nodes aren’t1.
Safari and Chrome handles this elegantly, leaving jQuery’s behaviour unchanged, but in Firefox it caused jQuery to return prematurely. In Firefox, it looks as if the dynamically injected externally sourced script node is forcing asynchronous evaluation to all dynamically injected script nodes, including the ones with inline source code.
The solution was simple enough: keep the Facebook share script at the bottom, but locating the issue was a pain. Whether or not this is a Firefox bug, I don’t know, but I couldn’t find anything on the issue so I thought I’d give it my 2 cents.
A simple demo, for those who are curious. Latest production version to date of all mentioned browsers were used in testing.