From 07010d0b17d465890b94f96b2bdc767b7fcdf9a4 Mon Sep 17 00:00:00 2001 From: "Helder.wiki" Date: Tue, 23 Jul 2013 18:21:30 -0300 Subject: [PATCH] resourceloader: Return a promise from mw.loader.using() This implements support for: mw.loader.using( 'foo' ).done( callback ); Cleanup: - Validate array input using $.isArray - Simplify code Change-Id: I9e145cfde24f582b123707ed20cb0fca60fccb2c --- RELEASE-NOTES-1.23 | 1 + resources/mediawiki/mediawiki.js | 41 +++++++++++-------- .../resources/mediawiki/mediawiki.test.js | 26 ++++++++++++ 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/RELEASE-NOTES-1.23 b/RELEASE-NOTES-1.23 index cd445a7670..92e94ed65d 100644 --- a/RELEASE-NOTES-1.23 +++ b/RELEASE-NOTES-1.23 @@ -134,6 +134,7 @@ production. installer has been updated to use it. * Changes to content typography (fonts, line-height, etc.). See https://www.mediawiki.org/wiki/Typography_refresh for further information. +* ResourceLoader: mw.loader.using() now implements a Promise interface. === Bug fixes in 1.23 === * (bug 41759) The "updated since last visit" markers (on history pages, recent diff --git a/resources/mediawiki/mediawiki.js b/resources/mediawiki/mediawiki.js index 85e32e884b..d8a17f6269 100644 --- a/resources/mediawiki/mediawiki.js +++ b/resources/mediawiki/mediawiki.js @@ -1732,36 +1732,45 @@ var mw = ( function ( $, undefined ) { * * @param {string|Array} dependencies Module name or array of modules names the callback * dependends on to be ready before executing - * @param {Function} [ready] callback to execute when all dependencies are ready - * @param {Function} [error] callback to execute when if dependencies have a errors + * @param {Function} [ready] Callback to execute when all dependencies are ready + * @param {Function} [error] Callback to execute if one or more dependencies failed + * @return {jQuery.Promise} */ using: function ( dependencies, ready, error ) { - var tod = typeof dependencies; - // Validate input - if ( tod !== 'object' && tod !== 'string' ) { - throw new Error( 'dependencies must be a string or an array, not a ' + tod ); - } + var deferred = $.Deferred(); + // Allow calling with a single dependency as a string - if ( tod === 'string' ) { + if ( typeof dependencies === 'string' ) { dependencies = [ dependencies ]; + } else if ( !$.isArray( dependencies ) ) { + // Invalid input + throw new Error( 'Dependencies must be a string or an array' ); + } + + if ( ready ) { + deferred.done( ready ); } + if ( error ) { + deferred.fail( error ); + } + // Resolve entire dependency map dependencies = resolve( dependencies ); if ( allReady( dependencies ) ) { // Run ready immediately - if ( $.isFunction( ready ) ) { - ready(); - } + deferred.resolve(); } else if ( filter( ['error', 'missing'], dependencies ).length ) { // Execute error immediately if any dependencies have errors - if ( $.isFunction( error ) ) { - error( new Error( 'one or more dependencies have state "error" or "missing"' ), - dependencies ); - } + deferred.reject( + new Error( 'One or more dependencies failed to load' ), + dependencies + ); } else { // Not all dependencies are ready: queue up a request - request( dependencies, ready, error ); + request( dependencies, deferred.resolve, deferred.reject ); } + + return deferred.promise(); }, /** diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.test.js index 441fcbcc95..f5091f967b 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.test.js @@ -384,6 +384,32 @@ } ); } ); + QUnit.asyncTest( 'mw.loader.using( .. ).promise', 2, function ( assert ) { + var isAwesomeDone; + + mw.loader.testCallback = function () { + QUnit.start(); + assert.strictEqual( isAwesomeDone, undefined, 'Implementing module is.awesome: isAwesomeDone should still be undefined' ); + isAwesomeDone = true; + }; + + mw.loader.implement( 'test.promise', [QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/callMwLoaderTestCallback.js' )], {}, {} ); + + mw.loader.using( 'test.promise' ) + .done( function () { + + // /sample/awesome.js declares the "mw.loader.testCallback" function + // which contains a call to start() and ok() + assert.strictEqual( isAwesomeDone, true, 'test.promise module should\'ve caused isAwesomeDone to be true' ); + delete mw.loader.testCallback; + + } ) + .fail( function () { + QUnit.start(); + assert.ok( false, 'Error callback fired while loader.using "test.promise" module' ); + } ); + } ); + QUnit.asyncTest( 'mw.loader.implement( styles={ "css": [text, ..] } )', 2, function ( assert ) { var $element = $( '
' ).appendTo( '#qunit-fixture' ); -- 2.20.1