jQuery(document).ready() bug with Google Chrome 4.0 beta

I came across a major issue with jQuery (1.3.2) and Google Chrome 4.0 beta today. I’d been testing my company’s web application (for which I’m the primary frontend developer) with Chrome 3.0x, and it was working fine. After a sudden influx of chrome bug reports from someone using 4, I updated to that. And suddenly, nearly nothing worked.

After a fair bit of futzing around in my code and the jQuery core library, I discovered that in chrome 4 in certain cases (probably in large apps), the DOMContentLoaded event was never sent to the core jQuery library. To test this, I inserted a couple of lines into the file you saw above:

3052  if ( document.addEventListener ) {
3053      // Use the handy event callback
[ins]     alert("jQ adding listener for DOMContentLoaded");
3054      document.addEventListener( "DOMContentLoaded", function(){
[ins]         alert("jQ received DOMContentLoaded event");
3055          document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
3056          jQuery.ready();
3057      }, false );

Both alerts show in FF, but only the first does in chrome. However, I found I could add my own and have them called.

Now, since the chances are you’re on this page because you googled for a workaround, here it is:

Google Chrome 4 beta jQuery document ready fix plugin

What this plugin does is first test to see if the browser is chrome 4, and if it is, then it adds another event listener for DOMContentLoaded, which will run even though the main jQuery one mysteriously does not. This calls jQuery.ready function (which is what is used to run through jQuery.readyList, the queued functions array).

We now have two chances for jQuery.ready to be called, therefore a potential race condition. To avoid this, I rewrote jQuery.ready() to null out  jQuery.readyList before cycling through the queued functions.

I still have no idea what’s causing Chrome 4 to fail on this. A test of document.readyState right after I added $(document).ready() shows that it is “loading”, so the problem isn’t that it finishes before adding the event handler or enqueueing the function.