Merge "Prepare for REL1_33 cut, labelling master as 1.34-alpha"
[lhc/web/wiklou.git] / resources / src / startup / mediawiki.js
index 28f57db..0a8dfb8 100644 (file)
         */
        function fnv132( str ) {
                var hash = 0x811C9DC5,
-                       i;
+                       i = 0;
 
                /* eslint-disable no-bitwise */
-               for ( i = 0; i < str.length; i++ ) {
+               for ( ; i < str.length; i++ ) {
                        hash += ( hash << 1 ) + ( hash << 4 ) + ( hash << 7 ) + ( hash << 8 ) + ( hash << 24 );
                        hash ^= str.charCodeAt( i );
                }
                 * @private
                 * @class
                 */
-               StringSet = window.Set || function StringSet() {
+               StringSet = window.Set || function () {
                        var set = Object.create( null );
-                       this.add = function ( value ) {
-                               set[ value ] = true;
-                       };
-                       this.has = function ( value ) {
-                               return value in set;
+                       return {
+                               add: function ( value ) {
+                                       set[ value ] = true;
+                               },
+                               has: function ( value ) {
+                                       return value in set;
+                               }
                        };
                };
        }
                         *             'dependencies': ['required.foo', 'bar.also', ...]
                         *             'group': 'somegroup', (or) null
                         *             'source': 'local', (or) 'anotherwiki'
-                        *             'skip': 'return !!window.Example', (or) null
+                        *             'skip': 'return !!window.Example', (or) null, (or) boolean result of skip
                         *             'module': export Object
                         *
                         *             // Set from execute() or mw.loader.state()
                         *             'state': 'registered', 'loaded', 'loading', 'ready', 'error', or 'missing'
                         *
                         *             // Optionally added at run-time by mw.loader.implement()
-                        *             'skipped': true
                         *             'script': closure, array of urls, or string
                         *             'style': { ... } (see #execute)
                         *             'messages': { 'key': 'value', ... }
 
                        /**
                         * @private
-                        * @param {Array} modules List of module names
+                        * @param {string[]} modules List of module names
                         * @return {string} Hash of concatenated version hashes.
                         */
                        function getCombinedVersion( modules ) {
                         * execute the module or job now.
                         *
                         * @private
-                        * @param {Array} modules Names of modules to be checked
+                        * @param {string[]} modules Names of modules to be checked
                         * @return {boolean} True if all modules are in state 'ready', false otherwise
                         */
                        function allReady( modules ) {
-                               var i;
-                               for ( i = 0; i < modules.length; i++ ) {
+                               var i = 0;
+                               for ( ; i < modules.length; i++ ) {
                                        if ( mw.loader.getState( modules[ i ] ) !== 'ready' ) {
                                                return false;
                                        }
                         * @return {boolean} True if no modules are in state 'error' or 'missing', false otherwise
                         */
                        function anyFailed( modules ) {
-                               var i, state;
-                               for ( i = 0; i < modules.length; i++ ) {
+                               var state,
+                                       i = 0;
+                               for ( ; i < modules.length; i++ ) {
                                        state = mw.loader.getState( modules[ i ] );
                                        if ( state === 'error' || state === 'missing' ) {
                                                return true;
                         *  dependencies, such that later modules depend on earlier modules. The array
                         *  contains the module names. If the array contains already some module names,
                         *  this function appends its result to the pre-existing array.
-                        * @param {StringSet} [unresolved] Used to track the current dependency
-                        *  chain, and to report loops in the dependency graph.
-                        * @throws {Error} If any unregistered module or a dependency loop is encountered
+                        * @param {StringSet} [unresolved] Used to detect loops in the dependency graph.
+                        * @throws {Error} If an unknown module or a circular dependency is encountered
                         */
                        function sortDependencies( module, resolved, unresolved ) {
-                               var i, deps, skip;
+                               var i, skip, deps;
 
                                if ( !( module in registry ) ) {
-                                       throw new Error( 'Unknown dependency: ' + module );
+                                       throw new Error( 'Unknown module: ' + module );
                                }
 
-                               if ( registry[ module ].skip !== null ) {
+                               if ( typeof registry[ module ].skip === 'string' ) {
                                        // eslint-disable-next-line no-new-func
-                                       skip = new Function( registry[ module ].skip );
-                                       registry[ module ].skip = null;
-                                       if ( skip() ) {
-                                               registry[ module ].skipped = true;
+                                       skip = ( new Function( registry[ module ].skip )() );
+                                       registry[ module ].skip = !!skip;
+                                       if ( skip ) {
                                                registry[ module ].dependencies = [];
                                                setAndPropagate( module, 'ready' );
                                                return;
                                        }
                                }
 
-                               if ( resolved.indexOf( module ) !== -1 ) {
-                                       // Module already resolved; nothing to do
-                                       return;
-                               }
                                // Create unresolved if not passed in
                                if ( !unresolved ) {
                                        unresolved = new StringSet();
                                }
 
-                               // Add base modules
-                               if ( baseModules.indexOf( module ) === -1 ) {
-                                       for ( i = 0; i < baseModules.length; i++ ) {
-                                               if ( resolved.indexOf( baseModules[ i ] ) === -1 ) {
-                                                       resolved.push( baseModules[ i ] );
-                                               }
-                                       }
-                               }
-
-                               // Tracks down dependencies
+                               // Track down dependencies
                                deps = registry[ module ].dependencies;
                                unresolved.add( module );
                                for ( i = 0; i < deps.length; i++ ) {
                                                sortDependencies( deps[ i ], resolved, unresolved );
                                        }
                                }
+
                                resolved.push( module );
                        }
 
                         * @throws {Error} If an unregistered module or a dependency loop is encountered
                         */
                        function resolve( modules ) {
-                               var i, resolved = [];
-                               for ( i = 0; i < modules.length; i++ ) {
+                               // Always load base modules
+                               var resolved = baseModules.slice(),
+                                       i = 0;
+                               for ( ; i < modules.length; i++ ) {
                                        sortDependencies( modules[ i ], resolved );
                                }
                                return resolved;
                         * @return {Array} List of dependencies.
                         */
                        function resolveStubbornly( modules ) {
-                               var i, saved, resolved = [];
-                               for ( i = 0; i < modules.length; i++ ) {
+                               var saved,
+                                       // Always load base modules
+                                       resolved = baseModules.slice(),
+                                       i = 0;
+                               for ( ; i < modules.length; i++ ) {
                                        saved = resolved.slice();
                                        try {
                                                sortDependencies( modules[ i ], resolved );
                                        if ( script.parentNode ) {
                                                script.parentNode.removeChild( script );
                                        }
-                                       script = null;
                                        if ( callback ) {
                                                callback();
                                                callback = null;
                                 * @private
                                 */
                                work: function () {
-                                       var q, batch, implementations, sourceModules;
-
-                                       batch = [];
+                                       var implementations, sourceModules,
+                                               batch = [],
+                                               q = 0;
 
                                        // Appends a list of modules from the queue to the batch
-                                       for ( q = 0; q < queue.length; q++ ) {
+                                       for ( ; q < queue.length; q++ ) {
                                                // Only load modules which are registered
                                                if ( queue[ q ] in registry && registry[ queue[ q ] ].state === 'registered' ) {
                                                        // Prevent duplicate entries
                                 *  "text/javascript"; if no type is provided, text/javascript is assumed.
                                 */
                                load: function ( modules, type ) {
-                                       var filtered, l;
+                                       var l;
 
                                        // Allow calling with a url or single dependency as a string
                                        if ( typeof modules === 'string' ) {
                                                modules = [ modules ];
                                        }
 
-                                       // Filter out top-level modules that are unknown or failed to load before.
-                                       filtered = modules.filter( function ( module ) {
-                                               var state = mw.loader.getState( module );
-                                               return state !== 'error' && state !== 'missing';
-                                       } );
-                                       // Resolve remaining list using the known dependency tree.
-                                       // This also filters out modules with unknown dependencies. (T36853)
-                                       filtered = resolveStubbornly( filtered );
-                                       // Some modules are not yet ready, add to module load queue.
-                                       enqueue( filtered, undefined, undefined );
+                                       // Resolve modules into flat list for internal queuing.
+                                       // This also filters out unknown modules and modules with
+                                       // unknown dependencies, allowing the rest to continue. (T36853)
+                                       enqueue( resolveStubbornly( modules ), undefined, undefined );
                                },
 
                                /**