resourceloader: Never defer execution for top loading modules
authorRoan Kattouw <roan.kattouw@gmail.com>
Tue, 23 Jul 2013 01:18:01 +0000 (18:18 -0700)
committerTimo Tijhof <krinklemail@gmail.com>
Fri, 27 Sep 2013 17:56:09 +0000 (19:56 +0200)
There was a bug where if a module was in the top queue but had CSS,
its execution would be deferred until its CSS was ready. This would
cause the module's execution to occur after document ready and after
user scripts had run.

This is bad because top-loaded modules are supposed to be guaranteed
to run before document ready.

Fix this by skipping the wait-for-CSS logic when loading synchronously.
Top-loading modules' execution is now guaranteed to block loading the
rest of the page, but their CSS isn't guaranteed to be ready at this
point. Which is fine, because they shouldn't be measuring things in the
DOM before document ready anyway.

Change-Id: I5779cdef336be184741ad97ea84113eb7790dd39

resources/mediawiki/mediawiki.js

index 0bf4ec3..39093e3 100644 (file)
@@ -1026,30 +1026,37 @@ var mw = ( function ( $, undefined ) {
                                        mw.messages.set( registry[module].messages );
                                }
 
-                               // Make sure we don't run the scripts until all (potentially asynchronous)
-                               // stylesheet insertions have completed.
-                               ( function () {
-                                       var pending = 0;
-                                       checkCssHandles = function () {
-                                               // cssHandlesRegistered ensures we don't take off too soon, e.g. when
-                                               // one of the cssHandles is fired while we're still creating more handles.
-                                               if ( cssHandlesRegistered && pending === 0 && runScript ) {
-                                                       runScript();
-                                                       runScript = undefined; // Revoke
-                                               }
-                                       };
-                                       cssHandle = function () {
-                                               var check = checkCssHandles;
-                                               pending++;
-                                               return function () {
-                                                       if (check) {
-                                                               pending--;
-                                                               check();
-                                                               check = undefined; // Revoke
+                               if ( $.isReady || registry[module].async ) {
+                                       // Make sure we don't run the scripts until all (potentially asynchronous)
+                                       // stylesheet insertions have completed.
+                                       ( function () {
+                                               var pending = 0;
+                                               checkCssHandles = function () {
+                                                       // cssHandlesRegistered ensures we don't take off too soon, e.g. when
+                                                       // one of the cssHandles is fired while we're still creating more handles.
+                                                       if ( cssHandlesRegistered && pending === 0 && runScript ) {
+                                                               runScript();
+                                                               runScript = undefined; // Revoke
                                                        }
                                                };
-                                       };
-                               }() );
+                                               cssHandle = function () {
+                                                       var check = checkCssHandles;
+                                                       pending++;
+                                                       return function () {
+                                                               if (check) {
+                                                                       pending--;
+                                                                       check();
+                                                                       check = undefined; // Revoke
+                                                               }
+                                                       };
+                                               };
+                                       }() );
+                               } else {
+                                       // We are in blocking mode, and so we can't afford to wait for CSS
+                                       cssHandle = function () {};
+                                       // Run immediately
+                                       checkCssHandles = runScript;
+                               }
 
                                // Process styles (see also mw.loader.implement)
                                // * back-compat: { <media>: css }