* @alternateClassName mediaWiki
* @singleton
*/
-/* global $VARS */
+/* global $VARS, $CODE */
( function () {
'use strict';
* @return {string} Hash of concatenated version hashes.
*/
function getCombinedVersion( modules ) {
- var hashes = modules.map( function ( module ) {
- return registry[ module ].version;
- } );
- return fnv132( hashes.join( '' ) );
+ var hashes = modules.reduce( function ( result, module ) {
+ return result + registry[ module ].version;
+ }, '' );
+ return fnv132( hashes );
}
/**
}
registry[ module ].state = 'executing';
+ $CODE.profileExecuteStart();
runScript = function () {
var script, markModuleReady, nestedAddScript;
+ $CODE.profileScriptStart();
script = registry[ module ].script;
markModuleReady = function () {
+ $CODE.profileScriptEnd();
registry[ module ].state = 'ready';
handlePending( module );
};
// Use mw.track instead of mw.log because these errors are common in production mode
// (e.g. undefined variable), and mw.log is only enabled in debug mode.
registry[ module ].state = 'error';
+ $CODE.profileScriptEnd();
mw.trackError( 'resourceloader.exception', {
exception: e, module:
module, source: 'module-execute'
}
}
+ // End profiling of execute()-self before we call checkCssHandles(),
+ // which (sometimes asynchronously) calls runScript(), which we want
+ // to measure separately without overlap.
+ $CODE.profileExecuteEnd();
+
// Kick off.
cssHandlesRegistered = true;
checkCssHandles();
* @param {string[]} batch
*/
function batchRequest( batch ) {
- var reqBase, splits, maxQueryLength, b, bSource, bGroup, bSourceGroup,
+ var reqBase, splits, maxQueryLength, b, bSource, bGroup,
source, group, i, modules, sourceLoadScript,
currReqBase, currReqBaseLength, moduleMap, currReqModules, l,
lastDotIndex, prefix, suffix, bytesAdded;
maxQueryLength = mw.config.get( 'wgResourceLoaderMaxQueryLength', 2000 );
// Split module list by source and by group.
- splits = {};
+ splits = Object.create( null );
for ( b = 0; b < batch.length; b++ ) {
bSource = registry[ batch[ b ] ].source;
bGroup = registry[ batch[ b ] ].group;
- if ( !hasOwn.call( splits, bSource ) ) {
- splits[ bSource ] = {};
+ if ( !splits[ bSource ] ) {
+ splits[ bSource ] = Object.create( null );
}
- if ( !hasOwn.call( splits[ bSource ], bGroup ) ) {
+ if ( !splits[ bSource ][ bGroup ] ) {
splits[ bSource ][ bGroup ] = [];
}
- bSourceGroup = splits[ bSource ][ bGroup ];
- bSourceGroup.push( batch[ b ] );
+ splits[ bSource ][ bGroup ].push( batch[ b ] );
}
for ( source in splits ) {
-
sourceLoadScript = sources[ source ];
for ( group in splits[ source ] ) {
// We may need to split up the request to honor the query string length limit,
// so build it piece by piece.
l = currReqBaseLength;
- moduleMap = {}; // { prefix: [ suffixes ] }
+ moduleMap = Object.create( null ); // { prefix: [ suffixes ] }
currReqModules = [];
for ( i = 0; i < modules.length; i++ ) {
// If lastDotIndex is -1, substr() returns an empty string
prefix = modules[ i ].substr( 0, lastDotIndex );
suffix = modules[ i ].slice( lastDotIndex + 1 );
- bytesAdded = hasOwn.call( moduleMap, prefix ) ?
+ bytesAdded = moduleMap[ prefix ] ?
suffix.length + 3 : // '%2C'.length == 3
modules[ i ].length + 3; // '%7C'.length == 3
doRequest();
// .. and start again.
l = currReqBaseLength;
- moduleMap = {};
+ moduleMap = Object.create( null );
currReqModules = [];
mw.track( 'resourceloader.splitRequest', { maxQueryLength: maxQueryLength } );
}
- if ( !hasOwn.call( moduleMap, prefix ) ) {
+ if ( !moduleMap[ prefix ] ) {
moduleMap[ prefix ] = [];
}
l += bytesAdded;
module: {
exports: {}
},
- version: version !== undefined ? String( version ) : '',
+ version: String( version || '' ),
dependencies: deps || [],
group: typeof group === 'string' ? group : null,
source: typeof source === 'string' ? source : 'local',
/**
* Change the state of one or more modules.
*
- * @param {string|Object} module Module name or object of module name/state pairs
- * @param {string} state State name
+ * @param {Object} modules Object of module name/state pairs
*/
- state: function ( module, state ) {
- var m;
-
- if ( typeof module === 'object' ) {
- for ( m in module ) {
- mw.loader.state( m, module[ m ] );
+ state: function ( modules ) {
+ var module, state;
+ for ( module in modules ) {
+ state = modules[ module ];
+ if ( !hasOwn.call( registry, module ) ) {
+ mw.loader.register( module );
+ }
+ registry[ module ].state = state;
+ if ( state === 'ready' || state === 'error' || state === 'missing' ) {
+ // Make sure pending modules depending on this one get executed if their
+ // dependencies are now fulfilled!
+ handlePending( module );
}
- return;
- }
- if ( !hasOwn.call( registry, module ) ) {
- mw.loader.register( module );
- }
- registry[ module ].state = state;
- if ( state === 'ready' || state === 'error' || state === 'missing' ) {
- // Make sure pending modules depending on this one get executed if their
- // dependencies are now fulfilled!
- handlePending( module );
}
},