X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=resources%2Fsrc%2Fmediawiki%2Fmediawiki.js;h=c8f5506833cac53eaf0bac6ef59b16118a84d45c;hb=4394d6cf8a7913e90df119e32f67dd51b8f2ddcb;hp=4516e206c21380f5dcc0ffbdc8f1524ef2e177ef;hpb=ca1ec03b8cbae5630e892e3b246efcb7e08ae922;p=lhc%2Fweb%2Fwiklou.git diff --git a/resources/src/mediawiki/mediawiki.js b/resources/src/mediawiki/mediawiki.js index 4516e206c2..c8f5506833 100644 --- a/resources/src/mediawiki/mediawiki.js +++ b/resources/src/mediawiki/mediawiki.js @@ -483,6 +483,12 @@ */ messages: new Map(), + /** + * Templates associated with a module + * @property {mw.Map} + */ + templates: new Map(), + /* Public Methods */ /** @@ -801,7 +807,8 @@ } /** - * Generates an ISO8601 "basic" string from a UNIX timestamp + * Convert UNIX timestamp to ISO8601 format + * @param {number} timestamp UNIX timestamp * @private */ function formatVersionNumber( timestamp ) { @@ -833,7 +840,7 @@ function sortDependencies( module, resolved, unresolved ) { var n, deps, len, skip; - if ( registry[module] === undefined ) { + if ( !hasOwn.call( registry, module ) ) { throw new Error( 'Unknown dependency: ' + module ); } @@ -947,7 +954,7 @@ // Build a list of modules which are in one of the specified states for ( s = 0; s < states.length; s += 1 ) { for ( m = 0; m < modules.length; m += 1 ) { - if ( registry[modules[m]] === undefined ) { + if ( !hasOwn.call( registry, modules[m] ) ) { // Module does not exist if ( states[s] === 'unregistered' ) { // OK, undefined @@ -1091,7 +1098,7 @@ var key, value, media, i, urls, cssHandle, checkCssHandles, cssHandlesRegistered = false; - if ( registry[module] === undefined ) { + if ( !hasOwn.call( registry, module ) ) { throw new Error( 'Module has not been registered yet: ' + module ); } else if ( registry[module].state === 'registered' ) { throw new Error( 'Module has not been requested from the server yet: ' + module ); @@ -1170,6 +1177,11 @@ mw.messages.set( registry[module].messages ); } + // Initialise templates + if ( registry[module].templates ) { + mw.templates.set( module, registry[module].templates ); + } + if ( $.isReady || registry[module].async ) { // Make sure we don't run the scripts until all (potentially asynchronous) // stylesheet insertions have completed. @@ -1354,6 +1366,34 @@ addScript( sourceLoadScript + '?' + $.param( request ) + '&*', null, async ); } + /** + * Resolve indexed dependencies. + * + * ResourceLoader uses an optimization to save space which replaces module names in + * dependency lists with the index of that module within the array of module + * registration data if it exists. The benefit is a significant reduction in the data + * size of the startup module. This function changes those dependency lists back to + * arrays of strings. + * + * @param {Array} modules Modules array + */ + function resolveIndexedDependencies( modules ) { + var i, iLen, j, jLen, module, dependency; + + // Expand indexed dependency names + for ( i = 0, iLen = modules.length; i < iLen; i++ ) { + module = modules[i]; + if ( module[2] ) { + for ( j = 0, jLen = module[2].length; j < jLen; j++ ) { + dependency = module[2][j]; + if ( typeof dependency === 'number' ) { + module[2][j] = modules[dependency][0]; + } + } + } + } + } + /* Public Members */ return { /** @@ -1394,7 +1434,7 @@ // Appends a list of modules from the queue to the batch for ( q = 0; q < queue.length; q += 1 ) { // Only request modules which are registered - if ( registry[queue[q]] !== undefined && registry[queue[q]].state === 'registered' ) { + if ( hasOwn.call( registry, queue[q] ) && registry[queue[q]].state === 'registered' ) { // Prevent duplicate entries if ( $.inArray( queue[q], batch ) === -1 ) { batch[batch.length] = queue[q]; @@ -1457,10 +1497,10 @@ for ( b = 0; b < batch.length; b += 1 ) { bSource = registry[batch[b]].source; bGroup = registry[batch[b]].group; - if ( splits[bSource] === undefined ) { + if ( !hasOwn.call( splits, bSource ) ) { splits[bSource] = {}; } - if ( splits[bSource][bGroup] === undefined ) { + if ( !hasOwn.call( splits[bSource], bGroup ) ) { splits[bSource][bGroup] = []; } bSourceGroup = splits[bSource][bGroup]; @@ -1513,7 +1553,7 @@ prefix = modules[i].substr( 0, lastDotIndex ); suffix = modules[i].slice( lastDotIndex + 1 ); - bytesAdded = moduleMap[prefix] !== undefined + bytesAdded = hasOwn.call( moduleMap, prefix ) ? suffix.length + 3 // '%2C'.length == 3 : modules[i].length + 3; // '%7C'.length == 3 @@ -1527,7 +1567,7 @@ async = true; l = currReqBaseLength + 9; } - if ( moduleMap[prefix] === undefined ) { + if ( !hasOwn.call( moduleMap, prefix ) ) { moduleMap[prefix] = []; } moduleMap[prefix].push( suffix ); @@ -1556,7 +1596,7 @@ * * @param {string} id Short string representing a source wiki, used internally for * registered modules to indicate where they should be loaded from (usually lowercase a-z). - * @param {Object|string} loadUrl load.php url, may be an object for backwards-compatability + * @param {Object|string} loadUrl load.php url, may be an object for backwards-compatibility * @return {boolean} */ addSource: function ( id, loadUrl ) { @@ -1569,7 +1609,7 @@ return true; } - if ( sources[id] !== undefined ) { + if ( hasOwn.call( sources, id ) ) { throw new Error( 'source already registered: ' + id ); } @@ -1586,7 +1626,12 @@ * Register a module, letting the system know about it and its * properties. Startup modules contain calls to this function. * - * @param {string} module Module name + * When using multiple module registration by passing an array, dependencies that + * are specified as references to modules within the array will be resolved before + * the modules are registered. + * + * @param {string|Array} module Module name or array of arrays, each containing + * a list of arguments compatible with this method * @param {number} version Module version number as a timestamp (falls backs to 0) * @param {string|Array|Function} dependencies One string or array of strings of module * names on which this module depends, or a function that returns that array. @@ -1595,16 +1640,17 @@ * @param {string} [skip=null] Script body of the skip function */ register: function ( module, version, dependencies, group, source, skip ) { - var m; + var i, len; // Allow multiple registration if ( typeof module === 'object' ) { - for ( m = 0; m < module.length; m += 1 ) { + resolveIndexedDependencies( module ); + for ( i = 0, len = module.length; i < len; i++ ) { // module is an array of module names - if ( typeof module[m] === 'string' ) { - mw.loader.register( module[m] ); + if ( typeof module[i] === 'string' ) { + mw.loader.register( module[i] ); // module is an array of arrays - } else if ( typeof module[m] === 'object' ) { - mw.loader.register.apply( mw.loader, module[m] ); + } else if ( typeof module[i] === 'object' ) { + mw.loader.register.apply( mw.loader, module[i] ); } } return; @@ -1613,7 +1659,7 @@ if ( typeof module !== 'string' ) { throw new Error( 'module must be a string, not a ' + typeof module ); } - if ( registry[module] !== undefined ) { + if ( hasOwn.call( registry, module ) ) { throw new Error( 'module already registered: ' + module ); } // List the module as registered @@ -1660,8 +1706,9 @@ * whether it's safe to extend the stylesheet (see #canExpandStylesheetWith). * * @param {Object} msgs List of key/value pairs to be added to mw#messages. + * @param {Object} [templates] List of key/value pairs to be added to mw#templates. */ - implement: function ( module, script, style, msgs ) { + implement: function ( module, script, style, msgs, templates ) { // Validate input if ( typeof module !== 'string' ) { throw new Error( 'module must be a string, not a ' + typeof module ); @@ -1675,18 +1722,23 @@ if ( !$.isPlainObject( msgs ) ) { throw new Error( 'msgs must be an object, not a ' + typeof msgs ); } + if ( templates !== undefined && !$.isPlainObject( templates ) ) { + throw new Error( 'templates must be an object, not a ' + typeof templates ); + } // Automatically register module - if ( registry[module] === undefined ) { + if ( !hasOwn.call( registry, module ) ) { mw.loader.register( module ); } // Check for duplicate implementation - if ( registry[module] !== undefined && registry[module].script !== undefined ) { + if ( hasOwn.call( registry, module ) && registry[module].script !== undefined ) { throw new Error( 'module already implemented: ' + module ); } // Attach components registry[module].script = script; registry[module].style = style; registry[module].messages = msgs; + // Templates are optional (for back-compat) + registry[module].templates = templates || {}; // The module may already have been marked as erroneous if ( $.inArray( registry[module].state, ['error', 'missing'] ) === -1 ) { registry[module].state = 'loaded'; @@ -1710,6 +1762,7 @@ * @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} + * @since 1.23 this returns a promise */ using: function ( dependencies, ready, error ) { var deferred = $.Deferred(); @@ -1802,8 +1855,8 @@ // an array of unrelated modules, whereas the modules passed to // using() are related and must all be loaded. for ( filtered = [], m = 0; m < modules.length; m += 1 ) { - module = registry[modules[m]]; - if ( module !== undefined ) { + if ( hasOwn.call( registry, modules[m] ) ) { + module = registry[modules[m]]; if ( $.inArray( module.state, ['error', 'missing'] ) === -1 ) { filtered[filtered.length] = modules[m]; } @@ -1842,7 +1895,7 @@ } return; } - if ( registry[module] === undefined ) { + if ( !hasOwn.call( registry, module ) ) { mw.loader.register( module ); } if ( $.inArray( state, ['ready', 'error', 'missing'] ) !== -1 @@ -1859,27 +1912,29 @@ /** * Get the version of a module. * - * @param {string} module Name of module to get version for + * @param {string} module Name of module * @return {string|null} The version, or null if the module (or its version) is not * in the registry. */ getVersion: function ( module ) { - if ( registry[module] !== undefined && registry[module].version !== undefined ) { - return formatVersionNumber( registry[module].version ); + if ( !hasOwn.call( registry, module ) || registry[module].version === undefined ) { + return null; } - return null; + return formatVersionNumber( registry[module].version ); }, /** * Get the state of a module. * - * @param {string} module Name of module to get state for + * @param {string} module Name of module + * @return {string|null} The state, or null if the module (or its version) is not + * in the registry. */ getState: function ( module ) { - if ( registry[module] !== undefined && registry[module].state !== undefined ) { - return registry[module].state; + if ( !hasOwn.call( registry, module ) || registry[module].state === undefined ) { + return null; } - return null; + return registry[module].state; }, /** @@ -1962,7 +2017,7 @@ * @return {string|null} Module key or null if module does not exist */ getModuleKey: function ( module ) { - return typeof registry[module] === 'object' ? + return hasOwn.call( registry, module ) ? ( module + '@' + registry[module].version ) : null; }, @@ -1985,8 +2040,15 @@ return; } - if ( !mw.config.get( 'wgResourceLoaderStorageEnabled' ) || mw.config.get( 'debug' ) ) { - // Disabled by configuration, or because debug mode is set + if ( !mw.config.get( 'wgResourceLoaderStorageEnabled' ) ) { + // Disabled by configuration. + // Clear any previous store to free up space. (T66721) + mw.loader.store.clear(); + mw.loader.store.enabled = false; + return; + } + if ( mw.config.get( 'debug' ) ) { + // Disable module store in debug mode mw.loader.store.enabled = false; return; } @@ -2057,7 +2119,8 @@ // Unversioned, private, or site-/user-specific ( !descriptor.version || $.inArray( descriptor.group, [ 'private', 'user', 'site' ] ) !== -1 ) || // Partial descriptor - $.inArray( undefined, [ descriptor.script, descriptor.style, descriptor.messages ] ) !== -1 + $.inArray( undefined, [ descriptor.script, descriptor.style, + descriptor.messages, descriptor.templates ] ) !== -1 ) { // Decline to store return false; @@ -2070,7 +2133,8 @@ String( descriptor.script ) : JSON.stringify( descriptor.script ), JSON.stringify( descriptor.style ), - JSON.stringify( descriptor.messages ) + JSON.stringify( descriptor.messages ), + JSON.stringify( descriptor.templates ) ]; // Attempted workaround for a possible Opera bug (bug 57567). // This regex should never match under sane conditions.