From ffd904022b8fce05cd99f4d5be86f0844f94294c Mon Sep 17 00:00:00 2001 From: Ed Sanders Date: Thu, 30 Apr 2015 17:03:30 +0100 Subject: [PATCH] Remove unless, and almost-useless closures in response cache Change-Id: Ie02caefe3d8c43b6b1e6b523fb07042f5ae6db37 --- .../ve-mw/init/ve.init.mw.ApiResponseCache.js | 313 +++++++++--------- .../ve-mw/init/ve.init.mw.ImageInfoCache.js | 74 ++--- modules/ve-mw/init/ve.init.mw.LinkCache.js | 224 +++++++------ 3 files changed, 302 insertions(+), 309 deletions(-) diff --git a/modules/ve-mw/init/ve.init.mw.ApiResponseCache.js b/modules/ve-mw/init/ve.init.mw.ApiResponseCache.js index 084a668ece..636cf1d693 100644 --- a/modules/ve-mw/init/ve.init.mw.ApiResponseCache.js +++ b/modules/ve-mw/init/ve.init.mw.ApiResponseCache.js @@ -4,188 +4,185 @@ * @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ -( function () { - var hasOwn = Object.prototype.hasOwnProperty; - /** - * MediaWiki API batch queue. - * - * Used to queue up lists of items centrally to get information about in batches - * of requests. - * - * @class - * @extends OO.EventEmitter - * @constructor - */ - ve.init.mw.ApiResponseCache = function VeInitMwApiResponseCache() { - // Mixin constructor - OO.EventEmitter.call( this ); +/** + * MediaWiki API batch queue. + * + * Used to queue up lists of items centrally to get information about in batches + * of requests. + * + * @class + * @extends OO.EventEmitter + * @constructor + */ +ve.init.mw.ApiResponseCache = function VeInitMwApiResponseCache() { + // Mixin constructor + OO.EventEmitter.call( this ); - // Keys are titles, values are deferreds - this.deferreds = {}; + // Keys are titles, values are deferreds + this.deferreds = {}; - // Keys are page names, values are link data objects - // This is kept for synchronous retrieval of cached values via #getCached - this.cacheValues = {}; + // Keys are page names, values are link data objects + // This is kept for synchronous retrieval of cached values via #getCached + this.cacheValues = {}; - // Array of page titles queued to be looked up - this.queue = []; + // Array of page titles queued to be looked up + this.queue = []; - this.schedule = ve.debounce( this.processQueue.bind( this ), 0 ); - }; + this.schedule = ve.debounce( this.processQueue.bind( this ), 0 ); +}; - /* Inheritance */ +/* Inheritance */ - OO.mixinClass( ve.init.mw.ApiResponseCache, OO.EventEmitter ); +OO.mixinClass( ve.init.mw.ApiResponseCache, OO.EventEmitter ); - /* Static methods */ +/* Static methods */ - /** - * Process each page in the response of an API request - * - * @abstract - * @static - * @method - * @param {Object} page The page object - * @return {Object|undefined} Any relevant info that we want to cache and return. - */ - ve.init.mw.ApiResponseCache.static.processPage = null; +/** + * Process each page in the response of an API request + * + * @abstract + * @static + * @method + * @param {Object} page The page object + * @return {Object|undefined} Any relevant info that we want to cache and return. + */ +ve.init.mw.ApiResponseCache.static.processPage = null; - /** - * Normalize the title of the response - * - * @param {string} title Title - * @return {string} Normalized title - */ - ve.init.mw.ApiResponseCache.static.normalizeTitle = function ( title ) { - var titleObj = mw.Title.newFromText( title ); - if ( !titleObj ) { - return title; - } - return titleObj.getPrefixedText(); - }; +/** + * Normalize the title of the response + * + * @param {string} title Title + * @return {string} Normalized title + */ +ve.init.mw.ApiResponseCache.static.normalizeTitle = function ( title ) { + var titleObj = mw.Title.newFromText( title ); + if ( !titleObj ) { + return title; + } + return titleObj.getPrefixedText(); +}; - /* Methods */ +/* Methods */ - /** - * Look up data about a title. If the data about this title is already in the cache, this - * returns an already-resolved promise. Otherwise, it returns a pending promise and schedules - * an request to retrieve the data. - * @param {string} title Title - * @returns {jQuery.Promise} Promise that will be resolved with the data once it's available - */ - ve.init.mw.ApiResponseCache.prototype.get = function ( title ) { - if ( typeof title !== 'string' ) { - // Don't bother letting things like undefined or null make it all the way through, - // just reject them here. Otherwise they'll cause problems or exceptions at random - // other points in this file. - return $.Deferred().reject().promise(); - } - title = this.constructor.static.normalizeTitle( title ); - if ( !hasOwn.call( this.deferreds, title ) ) { - this.deferreds[title] = $.Deferred(); - this.queue.push( title ); - this.schedule(); - } - return this.deferreds[title].promise(); - }; +/** + * Look up data about a title. If the data about this title is already in the cache, this + * returns an already-resolved promise. Otherwise, it returns a pending promise and schedules + * an request to retrieve the data. + * @param {string} title Title + * @returns {jQuery.Promise} Promise that will be resolved with the data once it's available + */ +ve.init.mw.ApiResponseCache.prototype.get = function ( title ) { + if ( typeof title !== 'string' ) { + // Don't bother letting things like undefined or null make it all the way through, + // just reject them here. Otherwise they'll cause problems or exceptions at random + // other points in this file. + return $.Deferred().reject().promise(); + } + title = this.constructor.static.normalizeTitle( title ); + if ( !Object.prototype.hasOwnProperty.call( this.deferreds, title ) ) { + this.deferreds[title] = $.Deferred(); + this.queue.push( title ); + this.schedule(); + } + return this.deferreds[title].promise(); +}; - /** - * Look up data about a page in the cache. If the data about this page is already in the cache, - * this returns that data. Otherwise, it returns undefined. - * - * @param {string} name Normalized page title - * @returns {Object|undefined} Cache data for this name. - */ - ve.init.mw.ApiResponseCache.prototype.getCached = function ( name ) { +/** + * Look up data about a page in the cache. If the data about this page is already in the cache, + * this returns that data. Otherwise, it returns undefined. + * + * @param {string} name Normalized page title + * @returns {Object|undefined} Cache data for this name. + */ +ve.init.mw.ApiResponseCache.prototype.getCached = function ( name ) { + if ( Object.prototype.hasOwnProperty.call( this.cacheValues, name ) ) { + return this.cacheValues[name]; + } +}; + +/** + * Fired when a new entry is added to the cache. + * + * @event add + * @param {Object} entries Cache entries that were added. Object mapping names to data objects. + */ + +/** + * Add entries to the cache. + * + * @param {Object} entries Object keyed by page title, with the values being data objects + * @fires add + */ +ve.init.mw.ApiResponseCache.prototype.set = function ( entries ) { + var name, hasOwn = Object.prototype.hasOwnProperty; + for ( name in entries ) { if ( hasOwn.call( this.cacheValues, name ) ) { - return this.cacheValues[name]; + continue; } - }; - - /** - * Fired when a new entry is added to the cache. - * - * @event add - * @param {Object} entries Cache entries that were added. Object mapping names to data objects. - */ - - /** - * Add entries to the cache. - * - * @param {Object} entries Object keyed by page title, with the values being data objects - * @fires add - */ - ve.init.mw.ApiResponseCache.prototype.set = function ( entries ) { - var name; - for ( name in entries ) { - if ( hasOwn.call( this.cacheValues, name ) ) { - continue; - } - if ( !hasOwn.call( this.deferreds, name ) ) { - this.deferreds[name] = $.Deferred(); - } - this.deferreds[name].resolve( entries[name] ); - this.cacheValues[name] = entries[name]; + if ( !hasOwn.call( this.deferreds, name ) ) { + this.deferreds[name] = $.Deferred(); } - this.emit( 'add', Object.keys( entries ) ); - }; + this.deferreds[name].resolve( entries[name] ); + this.cacheValues[name] = entries[name]; + } + this.emit( 'add', Object.keys( entries ) ); +}; - /** - * Get an API request promise to deal with a list of titles - * - * @abstract - * @method - * @param subqueue - * @return {jQuery.Promise} - */ - ve.init.mw.ApiResponseCache.prototype.getRequestPromise = null; +/** + * Get an API request promise to deal with a list of titles + * + * @abstract + * @method + * @param subqueue + * @return {jQuery.Promise} + */ +ve.init.mw.ApiResponseCache.prototype.getRequestPromise = null; - /** - * Perform any scheduled API requests. - * - * @private - * @fires add - */ - ve.init.mw.ApiResponseCache.prototype.processQueue = function () { - var subqueue, queue, - cache = this; +/** + * Perform any scheduled API requests. + * + * @private + * @fires add + */ +ve.init.mw.ApiResponseCache.prototype.processQueue = function () { + var subqueue, queue, + cache = this; - function rejectSubqueue( rejectQueue ) { - var i, len; - for ( i = 0, len = rejectQueue.length; i < len; i++ ) { - cache.deferreds[rejectQueue[i]].reject(); - } + function rejectSubqueue( rejectQueue ) { + var i, len; + for ( i = 0, len = rejectQueue.length; i < len; i++ ) { + cache.deferreds[rejectQueue[i]].reject(); } + } - function processResult( data ) { - var pageid, page, processedPage, - pages = ( data.query && data.query.pages ) || data.pages, - processed = {}; + function processResult( data ) { + var pageid, page, processedPage, + pages = ( data.query && data.query.pages ) || data.pages, + processed = {}; - if ( pages ) { - for ( pageid in pages ) { - page = pages[pageid]; - processedPage = cache.constructor.static.processPage( page ); - if ( processedPage !== undefined ) { - processed[page.title] = processedPage; - } + if ( pages ) { + for ( pageid in pages ) { + page = pages[pageid]; + processedPage = cache.constructor.static.processPage( page ); + if ( processedPage !== undefined ) { + processed[page.title] = processedPage; } - cache.set( processed ); } + cache.set( processed ); } + } - queue = this.queue; - this.queue = []; - while ( queue.length ) { - subqueue = queue.splice( 0, 50 ).map( this.constructor.static.normalizeTitle ); - this.getRequestPromise( subqueue ) - .then( processResult ) + queue = this.queue; + this.queue = []; + while ( queue.length ) { + subqueue = queue.splice( 0, 50 ).map( this.constructor.static.normalizeTitle ); + this.getRequestPromise( subqueue ) + .then( processResult ) - // Reject everything in subqueue; this will only reject the ones - // that weren't already resolved above, because .reject() on an - // already resolved Deferred is a no-op. - .then( rejectSubqueue.bind( null, subqueue ) ); - } - }; -}() ); + // Reject everything in subqueue; this will only reject the ones + // that weren't already resolved above, because .reject() on an + // already resolved Deferred is a no-op. + .then( rejectSubqueue.bind( null, subqueue ) ); + } +}; diff --git a/modules/ve-mw/init/ve.init.mw.ImageInfoCache.js b/modules/ve-mw/init/ve.init.mw.ImageInfoCache.js index d22459234c..036be4b094 100644 --- a/modules/ve-mw/init/ve.init.mw.ImageInfoCache.js +++ b/modules/ve-mw/init/ve.init.mw.ImageInfoCache.js @@ -4,48 +4,46 @@ * @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ -( function () { - /** - * Get information about images. - * @class - * @extends ve.init.mw.ApiResponseCache - * @constructor - */ - ve.init.mw.ImageInfoCache = function VeInitMwImageInfoCache() { - ve.init.mw.ImageInfoCache.super.call( this ); - }; - /* Inheritance */ +/** + * Get information about images. + * @class + * @extends ve.init.mw.ApiResponseCache + * @constructor + */ +ve.init.mw.ImageInfoCache = function VeInitMwImageInfoCache() { + ve.init.mw.ImageInfoCache.super.call( this ); +}; - OO.inheritClass( ve.init.mw.ImageInfoCache, ve.init.mw.ApiResponseCache ); +/* Inheritance */ - /* Static methods */ +OO.inheritClass( ve.init.mw.ImageInfoCache, ve.init.mw.ApiResponseCache ); - /** - * @inheritdoc - */ - ve.init.mw.ImageInfoCache.static.processPage = function ( page ) { - if ( page.imageinfo ) { - return page.imageinfo[0]; - } - }; +/* Static methods */ - /* Methods */ +/** + * @inheritdoc + */ +ve.init.mw.ImageInfoCache.static.processPage = function ( page ) { + if ( page.imageinfo ) { + return page.imageinfo[0]; + } +}; - /** - * @inheritdoc - */ - ve.init.mw.ImageInfoCache.prototype.getRequestPromise = function ( subqueue ) { - return new mw.Api().get( - { - action: 'query', - prop: 'imageinfo', - indexpageids: '1', - iiprop: 'size|mediatype', - titles: subqueue.join( '|' ) - }, - { type: 'POST' } - ); - }; +/* Methods */ -}() ); +/** + * @inheritdoc + */ +ve.init.mw.ImageInfoCache.prototype.getRequestPromise = function ( subqueue ) { + return new mw.Api().get( + { + action: 'query', + prop: 'imageinfo', + indexpageids: '1', + iiprop: 'size|mediatype', + titles: subqueue.join( '|' ) + }, + { type: 'POST' } + ); +}; diff --git a/modules/ve-mw/init/ve.init.mw.LinkCache.js b/modules/ve-mw/init/ve.init.mw.LinkCache.js index 95b589f168..a4af6401ec 100644 --- a/modules/ve-mw/init/ve.init.mw.LinkCache.js +++ b/modules/ve-mw/init/ve.init.mw.LinkCache.js @@ -4,125 +4,123 @@ * @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ -( function () { - /** - * Caches information about titles. - * @class - * @extends ve.init.mw.ApiResponseCache - * @constructor - */ - ve.init.mw.LinkCache = function VeInitMwLinkCache() { - ve.init.mw.LinkCache.super.call( this ); - // Keys are page names, values are link data objects - // This is kept for synchronous retrieval of cached values via #getCached - this.cacheValues = {}; +/** + * Caches information about titles. + * @class + * @extends ve.init.mw.ApiResponseCache + * @constructor + */ +ve.init.mw.LinkCache = function VeInitMwLinkCache() { + ve.init.mw.LinkCache.super.call( this ); + + // Keys are page names, values are link data objects + // This is kept for synchronous retrieval of cached values via #getCached + this.cacheValues = {}; +}; + +/* Inheritance */ + +OO.inheritClass( ve.init.mw.LinkCache, ve.init.mw.ApiResponseCache ); + +/* Static methods */ + +/** + * Get the icon name to use for a particular link type + * + * @param {Object} linkData Link data + * @return {string} Icon name + */ +ve.init.mw.LinkCache.static.getIconForLink = function ( linkData ) { + if ( linkData.missing ) { + return 'page-not-found'; + } + if ( linkData.redirect ) { + return 'page-redirect'; + } + if ( linkData.disambiguation ) { + return 'page-disambiguation'; + } + return 'page-existing'; +}; + +/** + * @inheritdoc + */ +ve.init.mw.LinkCache.static.processPage = function ( page ) { + return { + missing: page.missing !== undefined, + redirect: page.redirect !== undefined, + disambiguation: ve.getProp( page, 'pageprops', 'disambiguation' ) !== undefined, + imageUrl: ve.getProp( page, 'thumbnail', 'source' ), + description: ve.getProp( page, 'terms', 'description' ) }; +}; - /* Inheritance */ +/* Methods */ - OO.inheritClass( ve.init.mw.LinkCache, ve.init.mw.ApiResponseCache ); - - /* Static methods */ - - /** - * Get the icon name to use for a particular link type - * - * @param {Object} linkData Link data - * @return {string} Icon name - */ - ve.init.mw.LinkCache.static.getIconForLink = function ( linkData ) { - if ( linkData.missing ) { - return 'page-not-found'; - } - if ( linkData.redirect ) { - return 'page-redirect'; - } - if ( linkData.disambiguation ) { - return 'page-disambiguation'; - } - return 'page-existing'; - }; - - /** - * @inheritdoc - */ - ve.init.mw.LinkCache.static.processPage = function ( page ) { - return { - missing: page.missing !== undefined, - redirect: page.redirect !== undefined, - disambiguation: ve.getProp( page, 'pageprops', 'disambiguation' ) !== undefined, - imageUrl: ve.getProp( page, 'thumbnail', 'source' ), - description: ve.getProp( page, 'terms', 'description' ) - }; - }; - - /* Methods */ - - /** - * Requests information about the title, then adds classes to the provided element as appropriate. - * - * @param {string} title - * @param {jQuery} $element Element to style - */ - ve.init.mw.LinkCache.prototype.styleElement = function ( title, $element ) { - this.get( title ).done( function ( data ) { - if ( data.missing ) { - $element.addClass( 'new' ); - } else { - // Provided by core MediaWiki, no styles by default. - if ( data.redirect ) { - $element.addClass( 'mw-redirect' ); - } - // Should be provided by the Disambiguator extension, but no one has yet written a suitably - // performant patch to do it. It is instead implemented in JavaScript in on-wiki gadgets. - if ( data.disambiguation ) { - $element.addClass( 'mw-disambig' ); - } +/** + * Requests information about the title, then adds classes to the provided element as appropriate. + * + * @param {string} title + * @param {jQuery} $element Element to style + */ +ve.init.mw.LinkCache.prototype.styleElement = function ( title, $element ) { + this.get( title ).done( function ( data ) { + if ( data.missing ) { + $element.addClass( 'new' ); + } else { + // Provided by core MediaWiki, no styles by default. + if ( data.redirect ) { + $element.addClass( 'mw-redirect' ); + } + // Should be provided by the Disambiguator extension, but no one has yet written a suitably + // performant patch to do it. It is instead implemented in JavaScript in on-wiki gadgets. + if ( data.disambiguation ) { + $element.addClass( 'mw-disambig' ); } - } ); - }; - - /** - * Enable or disable automatic assumption of existence. - * - * While enabled, any get() for a title that's not already in the cache will return - * { missing: false } and write that to the cache. - * - * @param {boolean} assume Assume all uncached titles exist - */ - ve.init.mw.LinkCache.prototype.setAssumeExistence = function ( assume ) { - this.assumeExistence = !!assume; - }; - - /** - * @inheritdoc - */ - ve.init.mw.LinkCache.prototype.get = function ( title ) { - var data = {}; - if ( this.assumeExistence ) { - data[this.constructor.static.normalizeTitle( title )] = { missing: false }; - this.set( data ); } + } ); +}; - // Parent method - return ve.init.mw.LinkCache.super.prototype.get.call( this, title ); - }; +/** + * Enable or disable automatic assumption of existence. + * + * While enabled, any get() for a title that's not already in the cache will return + * { missing: false } and write that to the cache. + * + * @param {boolean} assume Assume all uncached titles exist + */ +ve.init.mw.LinkCache.prototype.setAssumeExistence = function ( assume ) { + this.assumeExistence = !!assume; +}; - /** - * @inheritdoc - */ - ve.init.mw.LinkCache.prototype.getRequestPromise = function ( subqueue ) { - return new mw.Api().get( { - action: 'query', - gpslimit: 10, - prop: 'info|pageprops|pageimages|pageterms', - pithumbsize: 80, - pilimit: 10, - wbptterms: 'description', - ppprop: 'disambiguation', - titles: subqueue.join( '|' ) - } ); - }; +/** + * @inheritdoc + */ +ve.init.mw.LinkCache.prototype.get = function ( title ) { + var data = {}; + if ( this.assumeExistence ) { + data[this.constructor.static.normalizeTitle( title )] = { missing: false }; + this.set( data ); + } -}() ); + // Parent method + return ve.init.mw.LinkCache.super.prototype.get.call( this, title ); +}; + +/** + * @inheritdoc + */ +ve.init.mw.LinkCache.prototype.getRequestPromise = function ( subqueue ) { + return new mw.Api().get( { + action: 'query', + gpslimit: 10, + prop: 'info|pageprops|pageimages|pageterms', + pithumbsize: 80, + pilimit: 10, + wbptterms: 'description', + ppprop: 'disambiguation', + titles: subqueue.join( '|' ) + } ); +};