resourceloader: Convert inline statements to queued functions
authorTimo Tijhof <krinklemail@gmail.com>
Mon, 27 Jul 2015 23:40:52 +0000 (16:40 -0700)
committerOri.livneh <ori@wikimedia.org>
Thu, 30 Jul 2015 18:22:46 +0000 (18:22 +0000)
Instead of having inline statements be plain statements wrapped
in an if-conditional block, convert them to inline functions
pushed into a queue.

The queue is kept in-memory until the startup module is loaded
at which point it transforms into a function that is immediately
invoked.

This is a prerequisite to making the top queue asynchronous.
Until then these functions will just run immediately as they
occur in the HTML after the startup module.

This is based on the previously reverted commit e86e5f8460.

Bug: T107399
Change-Id: Ifb38efca219c10ab973ad4c4ebb21c6a4239b005

includes/OutputPage.php
includes/resourceloader/ResourceLoader.php
resources/src/startup.js
tests/phpunit/includes/OutputPageTest.php

index e2caf80..f9f2470 100644 (file)
@@ -3005,13 +3005,6 @@ class OutputPage extends ContextSource {
                // Separate user.tokens as otherwise caching will be allowed (T84960)
                $links[] = $this->makeResourceLoaderLink( 'user.tokens', ResourceLoaderModule::TYPE_COMBINED );
 
-               // "Scripts only" modules marked for top inclusion
-               $styleModules = $this->getModuleScripts( true, 'top' );
-               $links[] = $this->makeResourceLoaderLink(
-                       $this->getModuleScripts( true, 'top' ),
-                       ResourceLoaderModule::TYPE_SCRIPTS
-               );
-
                // Modules requests - let the client calculate dependencies and batch requests as it likes
                // Only load modules that have marked themselves for loading at the top
                $modules = $this->getModules( true, 'top' );
@@ -3021,6 +3014,12 @@ class OutputPage extends ContextSource {
                        );
                }
 
+               // "Scripts only" modules marked for top inclusion
+               $links[] = $this->makeResourceLoaderLink(
+                       $this->getModuleScripts( true, 'top' ),
+                       ResourceLoaderModule::TYPE_SCRIPTS
+               );
+
                if ( $this->getConfig()->get( 'ResourceLoaderExperimentalAsyncLoading' ) ) {
                        $links[] = $this->getScriptsForBottomQueue( true );
                }
index 7875048..9b57ff3 100644 (file)
@@ -1372,7 +1372,7 @@ MESSAGE;
         * @return string
         */
        public static function makeLoaderConditionalScript( $script ) {
-               return "if(window.mw){\n" . trim( $script ) . "\n}";
+               return "var RLQ = RLQ || []; RLQ.push( function () {\n" . trim( $script ) . "\n} );";
        }
 
        /**
index ac42854..1332459 100644 (file)
@@ -26,7 +26,7 @@ performance.mark( 'mediaWikiStartUp' );
  */
 
 /*jshint unused: false, evil: true */
-/*globals mw, $VARS, $CODE */
+/*globals mw, RLQ: true, $VARS, $CODE */
 function isCompatible( ua ) {
        if ( ua === undefined ) {
                ua = navigator.userAgent;
@@ -76,6 +76,16 @@ function startUp() {
 
        $CODE.registrations();
 
+       window.RLQ = window.RLQ || [];
+       while ( RLQ.length ) {
+               RLQ.shift()();
+       }
+       RLQ = {
+               push: function ( fn ) {
+                       fn();
+               }
+       };
+
        mw.config.set( $VARS.configuration );
 }
 
index 7dddf77..bee44b9 100644 (file)
@@ -141,10 +141,11 @@ class OutputPageTest extends MediaWikiTestCase {
                        // Load module script only
                        array(
                                array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS ),
-                               '<script>if(window.mw){
-document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.foo\u0026amp;only=scripts\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");
-}</script>
-'
+                               "<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
+                                       . 'document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?'
+                                       . 'debug=false\u0026amp;lang=en\u0026amp;modules=test.foo\u0026amp;only'
+                                       . '=scripts\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");'
+                                       . "\n} );</script>\n"
                        ),
                        array(
                                // Don't condition wrap raw modules (like the startup module)
@@ -156,26 +157,24 @@ document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\
                        // This also tests the order the modules are put into the url
                        array(
                                array( array( 'test.baz', 'test.foo', 'test.bar' ), ResourceLoaderModule::TYPE_STYLES ),
+
                                '<link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.bar%2Cbaz%2Cfoo&amp;only=styles&amp;skin=fallback&amp;*">
 '
                        ),
                        // Load private module (only=scripts)
                        array(
                                array( 'test.quux', ResourceLoaderModule::TYPE_SCRIPTS ),
-                               '<script>if(window.mw){
-mw.test.baz({token:123});mw.loader.state({"test.quux":"ready"});
-
-}</script>
-'
+                               "<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
+                                       . "mw.test.baz({token:123});mw.loader.state({\"test.quux\":\"ready\"});\n"
+                                       . "\n} );</script>\n"
                        ),
                        // Load private module (combined)
                        array(
                                array( 'test.quux', ResourceLoaderModule::TYPE_COMBINED ),
-                               '<script>if(window.mw){
-mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n"]});
-
-}</script>
-'
+                               "<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
+                                       . "mw.loader.implement(\"test.quux\",function($,jQuery){"
+                                       . "mw.test.baz({token:123});},{\"css\":[\".mw-icon{transition:none}\\n"
+                                       . "\"]});\n\n} );</script>\n"
                        ),
                        // Load module script with ESI
                        array(
@@ -203,13 +202,12 @@ mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"
                        // Load two modules in separate groups
                        array(
                                array( array( 'test.group.foo', 'test.group.bar' ), ResourceLoaderModule::TYPE_COMBINED ),
-                               '<script>if(window.mw){
-document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.group.bar\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");
-}</script>
-<script>if(window.mw){
-document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.group.foo\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");
-}</script>
-'
+                               "<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
+                                       . 'document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.group.bar\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");'
+                                       . "\n} );</script>\n"
+                                       . "<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
+                                       . 'document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.group.foo\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");'
+                                       . "\n} );</script>\n"
                        ),
                );
        }
@@ -303,4 +301,3 @@ class NullMessageBlobStore extends MessageBlobStore {
        public function clear() {
        }
 }
-