Merge "resourceloader: Reduce memory cost of mw.config.set()"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 4 Sep 2018 18:09:29 +0000 (18:09 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 4 Sep 2018 18:09:29 +0000 (18:09 +0000)
1  2 
resources/src/startup/mediawiki.js

@@@ -1,7 -1,7 +1,7 @@@
  /**
   * Base library for MediaWiki.
   *
 - * Exposed globally as `mediaWiki` with `mw` as shortcut.
 + * Exposed globally as `mw`, with `mediaWiki` as alias.
   *
   * @class mw
   * @alternateClassName mediaWiki
                log.deprecate = !Object.defineProperty ? function ( obj, key, val ) {
                        obj[ key ] = val;
                } : function ( obj, key, val, msg, logName ) {
-                       var logged = new StringSet();
-                       logName = logName || key;
-                       msg = 'Use of "' + logName + '" is deprecated.' + ( msg ? ( ' ' + msg ) : '' );
-                       function uniqueTrace() {
-                               var trace = new Error().stack;
-                               if ( logged.has( trace ) ) {
-                                       return false;
+                       var stacks;
+                       function maybeLog() {
+                               var name,
+                                       trace = new Error().stack;
+                               if ( !stacks ) {
+                                       stacks = new StringSet();
+                               }
+                               if ( !stacks.has( trace ) ) {
+                                       stacks.add( trace );
+                                       name = logName || key;
+                                       mw.track( 'mw.deprecate', name );
+                                       mw.log.warn(
+                                               'Use of "' + name + '" is deprecated.' + ( msg ? ( ' ' + msg ) : '' )
+                                       );
                                }
-                               logged.add( trace );
-                               return true;
                        }
                        // Support: Safari 5.0
                        // Throws "not supported on DOM Objects" for Node or Element objects (incl. document)
                                        configurable: true,
                                        enumerable: true,
                                        get: function () {
-                                               if ( uniqueTrace() ) {
-                                                       mw.track( 'mw.deprecate', logName );
-                                                       mw.log.warn( msg );
-                                               }
+                                               maybeLog();
                                                return val;
                                        },
                                        set: function ( newVal ) {
-                                               if ( uniqueTrace() ) {
-                                                       mw.track( 'mw.deprecate', logName );
-                                                       mw.log.warn( msg );
-                                               }
+                                               maybeLog();
                                                val = newVal;
                                        }
                                } );
                                        // Allow multiple registration
                                        if ( typeof module === 'object' ) {
                                                resolveIndexedDependencies( module );
 +                                              // module is an array of arrays
                                                for ( i = 0; i < module.length; i++ ) {
                                                        // module is an array of module names
 -                                                      if ( typeof module[ i ] === 'string' ) {
 -                                                              mw.loader.register( module[ i ] );
 -                                                      // module is an array of arrays
 -                                                      } else if ( typeof module[ i ] === 'object' ) {
 -                                                              mw.loader.register.apply( mw.loader, module[ i ] );
 -                                                      }
 +                                                      mw.loader.register.apply( mw.loader, module[ i ] );
                                                }
                                                return;
                                        }
                                                mw.loader.register( name );
                                        }
                                        // Check for duplicate implementation
 -                                      if ( hasOwn.call( registry, name ) && registry[ name ].script !== undefined ) {
 +                                      if ( registry[ name ].script !== undefined ) {
                                                throw new Error( 'module already implemented: ' + name );
                                        }
                                        if ( version ) {
                                        init: function () {
                                                var raw, data;
  
 -                                              if ( mw.loader.store.enabled !== null ) {
 +                                              if ( this.enabled !== null ) {
                                                        // Init already ran
                                                        return;
                                                }
                                                        !mw.config.get( 'wgResourceLoaderStorageEnabled' )
                                                ) {
                                                        // Clear any previous store to free up space. (T66721)
 -                                                      mw.loader.store.clear();
 -                                                      mw.loader.store.enabled = false;
 +                                                      this.clear();
 +                                                      this.enabled = false;
                                                        return;
                                                }
                                                if ( mw.config.get( 'debug' ) ) {
                                                        // Disable module store in debug mode
 -                                                      mw.loader.store.enabled = false;
 +                                                      this.enabled = false;
                                                        return;
                                                }
  
                                                try {
                                                        // This a string we stored, or `null` if the key does not (yet) exist.
 -                                                      raw = localStorage.getItem( mw.loader.store.getStoreKey() );
 +                                                      raw = localStorage.getItem( this.getStoreKey() );
                                                        // If we get here, localStorage is available; mark enabled
 -                                                      mw.loader.store.enabled = true;
 +                                                      this.enabled = true;
                                                        // If null, JSON.parse() will cast to string and re-parse, still null.
                                                        data = JSON.parse( raw );
 -                                                      if ( data && typeof data.items === 'object' && data.vary === mw.loader.store.getVary() ) {
 -                                                              mw.loader.store.items = data.items;
 +                                                      if ( data && typeof data.items === 'object' && data.vary === this.getVary() ) {
 +                                                              this.items = data.items;
                                                                return;
                                                        }
                                                } catch ( e ) {
                                                //    We will disable the store below.
                                                if ( raw === undefined ) {
                                                        // localStorage failed; disable store
 -                                                      mw.loader.store.enabled = false;
 +                                                      this.enabled = false;
                                                }
                                        },
  
                                        get: function ( module ) {
                                                var key;
  
 -                                              if ( !mw.loader.store.enabled ) {
 +                                              if ( !this.enabled ) {
                                                        return false;
                                                }
  
                                                key = getModuleKey( module );
 -                                              if ( key in mw.loader.store.items ) {
 -                                                      mw.loader.store.stats.hits++;
 -                                                      return mw.loader.store.items[ key ];
 +                                              if ( key in this.items ) {
 +                                                      this.stats.hits++;
 +                                                      return this.items[ key ];
                                                }
 -                                              mw.loader.store.stats.misses++;
 +                                              this.stats.misses++;
                                                return false;
                                        },
  
                                        set: function ( module, descriptor ) {
                                                var args, key, src;
  
 -                                              if ( !mw.loader.store.enabled ) {
 +                                              if ( !this.enabled ) {
                                                        return;
                                                }
  
  
                                                if (
                                                        // Already stored a copy of this exact version
 -                                                      key in mw.loader.store.items ||
 +                                                      key in this.items ||
                                                        // Module failed to load
                                                        descriptor.state !== 'ready' ||
                                                        // Unversioned, private, or site-/user-specific
                                                }
  
                                                src = 'mw.loader.implement(' + args.join( ',' ) + ');';
 -                                              if ( src.length > mw.loader.store.MODULE_SIZE_MAX ) {
 +                                              if ( src.length > this.MODULE_SIZE_MAX ) {
                                                        return;
                                                }
 -                                              mw.loader.store.items[ key ] = src;
 -                                              mw.loader.store.update();
 +                                              this.items[ key ] = src;
 +                                              this.update();
                                        },
  
                                        /**
                                        prune: function () {
                                                var key, module;
  
 -                                              for ( key in mw.loader.store.items ) {
 +                                              for ( key in this.items ) {
                                                        module = key.slice( 0, key.indexOf( '@' ) );
                                                        if ( getModuleKey( module ) !== key ) {
 -                                                              mw.loader.store.stats.expired++;
 -                                                              delete mw.loader.store.items[ key ];
 -                                                      } else if ( mw.loader.store.items[ key ].length > mw.loader.store.MODULE_SIZE_MAX ) {
 +                                                              this.stats.expired++;
 +                                                              delete this.items[ key ];
 +                                                      } else if ( this.items[ key ].length > this.MODULE_SIZE_MAX ) {
                                                                // This value predates the enforcement of a size limit on cached modules.
 -                                                              delete mw.loader.store.items[ key ];
 +                                                              delete this.items[ key ];
                                                        }
                                                }
                                        },
                                         * Clear the entire module store right now.
                                         */
                                        clear: function () {
 -                                              mw.loader.store.items = {};
 +                                              this.items = {};
                                                try {
 -                                                      localStorage.removeItem( mw.loader.store.getStoreKey() );
 +                                                      localStorage.removeItem( this.getStoreKey() );
                                                } catch ( e ) {}
                                        },