From 73e24f255c932136b45efcb9e13ab41f2987b55d Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Tue, 7 Aug 2018 18:28:44 +0100 Subject: [PATCH 1/1] startup: Add support for module-requirement to RLQ * Add more inline documentation. * Use [0] instead of needless 'length'. (Optimisation) * Don't lazy-create NORLQ as empty array only to dereference it two statements later. (Optimisation) * Add support for a secondary signature to RLQ.push. The existing signature is a plain callback function that is execute immediately after startup. The new signature is an array of `[ string|Array, Function ]` where the first value is required module(s), and the second value is the callback function. startup.js will leave the second form in the array, processing them instead in 'mediawiki.base'. This change is needed before I17cd13dffebd6a (T192623), which will remove the undocumented behaviour of RLQ callbacks firing only after base modules arrive, which means we need to provide authors of inline scripts an alternate means of scheduling callbacks for after 'jquery' and/or 'mediawiki.base' arrive. Bug: T192623 Change-Id: Ica7bb9c3bdb77d96ca2e01530a76f7ca448acdb8 --- resources/src/startup/startup.js | 39 ++++++++++--------- .../mediawiki/mediawiki.base.test.js | 16 ++++++++ 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/resources/src/startup/startup.js b/resources/src/startup/startup.js index 7a50d94358..c609852a24 100644 --- a/resources/src/startup/startup.js +++ b/resources/src/startup/startup.js @@ -3,7 +3,7 @@ * * - Beware: This file MUST parse without errors on even the most ancient of browsers! */ - +/* eslint-disable vars-on-top, no-unmodified-loop-condition */ /* global mw, isCompatible, $VARS, $CODE */ /** @@ -79,17 +79,17 @@ window.isCompatible = function ( str ) { ); }; -// Conditional script injection ( function () { var NORLQ, script; + // Handle Grade C if ( !isCompatible() ) { - // Undo class swapping in case of an unsupported browser. - // See ResourceLoaderClientHtml::getDocumentAttributes(). + // Undo speculative Grade A class. See ResourceLoaderClientHtml::getDocumentAttributes(). document.documentElement.className = document.documentElement.className .replace( /(^|\s)client-js(\s|$)/, '$1client-nojs$2' ); - NORLQ = window.NORLQ || []; - while ( NORLQ.length ) { + // Process any callbacks for Grade C + NORLQ = window.NORLQ; + while ( NORLQ && NORLQ[ 0 ] ) { NORLQ.shift()(); } window.NORLQ = { @@ -98,9 +98,8 @@ window.isCompatible = function ( str ) { } }; - // Clear and disable the other queue + // Clear and disable the Grade A queue window.RLQ = { - // No-op push: function () {} }; @@ -117,22 +116,26 @@ window.isCompatible = function ( str ) { mw.config.set( $VARS.configuration ); - // Must be after mw.config.set because these callbacks may use mw.loader which - // needs to have values 'skin', 'debug' etc. from mw.config. - // eslint-disable-next-line vars-on-top - var RLQ = window.RLQ || []; - while ( RLQ.length ) { - RLQ.shift()(); - } + // Process callbacks for Grade A + // Must be after registrations and mw.config.set, which mw.loader depends on. + var queue = window.RLQ; window.RLQ = { push: function ( fn ) { - fn(); + if ( typeof fn === 'function' ) { + fn(); + } else { + // This callback has a requirement. + mw.loader.using( fn[ 0 ], fn[ 1 ] ); + } } }; + while ( queue && queue[ 0 ] ) { + // Re-use our push() + window.RLQ.push( queue.shift() ); + } - // Clear and disable the other queue + // Clear and disable the Grade C queue window.NORLQ = { - // No-op push: function () {} }; } diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.base.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.base.test.js index c4159531ec..65765f2df5 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.base.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.base.test.js @@ -123,4 +123,20 @@ ); } ); + QUnit.test( 'RLQ.push', function ( assert ) { + /* global RLQ */ + var loaded = 0, + done = assert.async(); + mw.loader.testCallback = function () { + loaded++; + delete mw.loader.testCallback; + }; + mw.loader.implement( 'test.rlq-push', [ QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/mwLoaderTestCallback.js' ) ] ); + + RLQ.push( [ 'test.rlq-push', function () { + assert.strictEqual( loaded, 1, 'Load the required module' ); + done(); + } ] ); + } ); + }( mediaWiki ) ); -- 2.20.1