From 3b4a7cbd582ffb6d0fc7f9ec2781fe1cafb2c935 Mon Sep 17 00:00:00 2001 From: Evad37 Date: Sat, 2 Feb 2019 13:42:00 +0800 Subject: [PATCH] resourceloader: Add getScript() method for loading scripts with callback Provides a friendly wrapper for loading scripts using $.ajax(). Returns a promise when the script dependency -- a single script url -- has been loaded. This matches how mw.loader.load is able to load a script url, and how mw.loader.using will return a promised that is resolved when dependecies are loaded, or rejected if there is an error. Added as a separate function mw.loader.getScript(), rather than adding this functionality to using(), as it is a separate use case, less confusing for users, and there is no shared or duplicated code between loading a script and loading one or more named modules. Bug: T27962 Change-Id: I13be426d03261a2d0c6a1631af94a9f9af58394b --- .../src/mediawiki.base/mediawiki.base.js | 37 +++++++++++++++++-- .../mediawiki.loader.getScript.example.js | 1 + .../mediawiki/mediawiki.loader.test.js | 21 +++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 tests/qunit/data/mediawiki.loader.getScript.example.js diff --git a/resources/src/mediawiki.base/mediawiki.base.js b/resources/src/mediawiki.base/mediawiki.base.js index 107ab33fb6..9016c7c274 100644 --- a/resources/src/mediawiki.base/mediawiki.base.js +++ b/resources/src/mediawiki.base/mediawiki.base.js @@ -644,7 +644,7 @@ var deferred = $.Deferred(); // Allow calling with a single dependency as a string - if ( typeof dependencies === 'string' ) { + if ( !Array.isArray( dependencies ) ) { dependencies = [ dependencies ]; } @@ -662,13 +662,42 @@ return deferred.reject( e ).promise(); } - mw.loader.enqueue( dependencies, function () { - deferred.resolve( mw.loader.require ); - }, deferred.reject ); + mw.loader.enqueue( + dependencies, + function () { deferred.resolve( mw.loader.require ); }, + deferred.reject + ); return deferred.promise(); }; + /** + * Load a script by URL. + * + * Example: + * + * mw.loader.getScript( + * 'https://example.org/x-1.0.0.js' + * ) + * .then( function () { + * // Script succeeded. You can use X now. + * }, function ( e ) { + * // Script failed. X is not avaiable + * mw.log.error( e.message ); // => "Failed to load script" + * } ); + * } ); + * + * @member mw.loader + * @param {string} url Script URL + * @return {jQuery.Promise} Resolved when the script is loaded + */ + mw.loader.getScript = function ( url ) { + return $.ajax( url, { dataType: 'script', cache: true } ) + .catch( function () { + throw new Error( 'Failed to load script' ); + } ); + }; + // Alias $j to jQuery for backwards compatibility // @deprecated since 1.23 Use $ or jQuery instead mw.log.deprecate( window, '$j', $, 'Use $ or jQuery instead.' ); diff --git a/tests/qunit/data/mediawiki.loader.getScript.example.js b/tests/qunit/data/mediawiki.loader.getScript.example.js new file mode 100644 index 0000000000..e5e4759d1c --- /dev/null +++ b/tests/qunit/data/mediawiki.loader.getScript.example.js @@ -0,0 +1 @@ +mw.getScriptExampleScriptLoaded = true; diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js index cb028a93a1..8b06bd6e1f 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js @@ -24,6 +24,7 @@ // exposed for cross-file mocks. delete mw.loader.testCallback; delete mw.loader.testFail; + delete mw.getScriptExampleScriptLoaded; } } ) ); @@ -1097,4 +1098,24 @@ } ); } ); + QUnit.test( '.getScript() - success', function ( assert ) { + var scriptUrl = QUnit.fixurl( + mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/mediawiki.loader.getScript.example.js' + ); + + return mw.loader.getScript( scriptUrl ).then( + function () { + assert.strictEqual( mw.getScriptExampleScriptLoaded, true, 'Data attached to a global object is available' ); + } + ); + } ); + + QUnit.test( '.getScript() - failure', function ( assert ) { + assert.rejects( + mw.loader.getScript( 'https://example.test/not-found' ), + /Failed to load script/, + 'Descriptive error message' + ); + } ); + }() ); -- 2.20.1