mw.loader: Use native Set where possible instead of string keys
authorTimo Tijhof <krinklemail@gmail.com>
Thu, 22 Sep 2016 23:07:54 +0000 (00:07 +0100)
committerTimo Tijhof <krinklemail@gmail.com>
Thu, 22 Sep 2016 23:07:54 +0000 (00:07 +0100)
Total time spent in sortDependencies
(Chrome Canary, unthrottled, MacBook Pro, MediaWiki-Vagrant)
* Before: 0.53ms
* After: 0.3ms

Bug: T146432
Change-Id: I65e2b0efbd080adab003b5c9605405ea0ae5380d

resources/src/mediawiki/mediawiki.js

index 89bb83b..2c7343f 100644 (file)
@@ -11,7 +11,7 @@
 ( function ( $ ) {
        'use strict';
 
-       var mw,
+       var mw, StringSet,
                hasOwn = Object.prototype.hasOwnProperty,
                slice = Array.prototype.slice,
                trackCallbacks = $.Callbacks( 'memory' ),
                return hash;
        }
 
+       StringSet = window.Set || ( function () {
+               /**
+                * @private
+                * @class
+                */
+               function StringSet() {
+                       this.set = {};
+               }
+               StringSet.prototype.add = function ( value ) {
+                       this.set[ value ] = true;
+               };
+               StringSet.prototype.has = function ( value ) {
+                       return this.set.hasOwnProperty( value );
+               };
+               return StringSet;
+       }() );
+
        /**
         * Create an object that can be read from or written to from methods that allow
         * interaction both with single and multiple properties at once.
                        log.deprecate = !Object.defineProperty ? function ( obj, key, val ) {
                                obj[ key ] = val;
                        } : function ( obj, key, val, msg ) {
-                               /*globals Set */
                                msg = 'Use of "' + key + '" is deprecated.' + ( msg ? ( ' ' + msg ) : '' );
-                               var logged, loggedIsSet, uniqueTrace;
-                               if ( window.Set ) {
-                                       logged = new Set();
-                                       loggedIsSet = true;
-                               } else {
-                                       logged = {};
-                                       loggedIsSet = false;
-                               }
-                               uniqueTrace = function () {
+                               var logged = new StringSet();
+                               function uniqueTrace() {
                                        var trace = new Error().stack;
-                                       if ( loggedIsSet ) {
-                                               if ( logged.has( trace ) ) {
-                                                       return false;
-                                               }
-                                               logged.add( trace );
-                                               return true;
-                                       } else {
-                                               if ( logged.hasOwnProperty( trace ) ) {
-                                                       return false;
-                                               }
-                                               logged[ trace ] = 1;
-                                               return true;
+                                       if ( logged.has( trace ) ) {
+                                               return false;
                                        }
-                               };
+                                       logged.add( trace );
+                                       return true;
+                               }
                                Object.defineProperty( obj, key, {
                                        configurable: true,
                                        enumerable: 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 {Object} [unresolved] Hash used to track the current dependency
-                        *  chain; used to report loops in the dependency graph.
+                        * @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
                         */
                        function sortDependencies( module, resolved, unresolved ) {
                                }
                                // Create unresolved if not passed in
                                if ( !unresolved ) {
-                                       unresolved = {};
+                                       unresolved = new StringSet();
                                }
                                // Tracks down dependencies
                                deps = registry[ module ].dependencies;
                                for ( i = 0; i < deps.length; i++ ) {
                                        if ( $.inArray( deps[ i ], resolved ) === -1 ) {
-                                               if ( unresolved[ deps[ i ] ] ) {
+                                               if ( unresolved.has( deps[ i ] ) ) {
                                                        throw new Error( mw.format(
                                                                'Circular reference detected: $1 -> $2',
                                                                module,
                                                        ) );
                                                }
 
-                                               // Add to unresolved
-                                               unresolved[ module ] = true;
+                                               unresolved.add(  module );
                                                sortDependencies( deps[ i ], resolved, unresolved );
                                        }
                                }