Arlolra has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/151068

Change subject: Use a map for the interwikiMap
......................................................................

Use a map for the interwikiMap

 * Avoid building it on each request.

Bug: 63370
Change-Id: I0e0cae162d6448799a1ca2c1c44ec08aff753fac
---
M lib/ext.core.LinkHandler.js
M lib/linter.js
M lib/mediawiki.ApiRequest.js
M lib/mediawiki.ParsoidConfig.js
M lib/mediawiki.WikiConfig.js
M lib/mediawiki.parser.environment.js
M lib/wts.LinkHandler.js
M tests/parserTests.js
8 files changed, 93 insertions(+), 68 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/services/parsoid 
refs/changes/68/151068/1

diff --git a/lib/ext.core.LinkHandler.js b/lib/ext.core.LinkHandler.js
index 01f9e38..e734377 100644
--- a/lib/ext.core.LinkHandler.js
+++ b/lib/ext.core.LinkHandler.js
@@ -81,7 +81,7 @@
                var nsPrefix = hrefBits[1];
                info.prefix = nsPrefix;
                var nnn = Util.normalizeNamespaceName( nsPrefix.trim() ),
-                       interwikiInfo = env.conf.wiki.interwikiMap[nnn],
+                       interwikiInfo = env.conf.wiki.interwikiMap.get(nnn),
                        // check for interwiki / language links
                        ns = env.conf.wiki.namespaceIds[nnn];
                // console.warn( nsPrefix, ns, interwikiInfo );
diff --git a/lib/linter.js b/lib/linter.js
index fa8a669..d0cf5d2 100644
--- a/lib/linter.js
+++ b/lib/linter.js
@@ -56,7 +56,7 @@
         msg.wiki = wiki;
         msg.page = logData._env.page.name;
         msg.revision = logData._env.page.meta.revision.revid;
-        msg.wikiurl = 
logData._env.conf.parsoid.interwikiMap[wiki].split('/w/')[0];
+        msg.wikiurl = 
logData._env.conf.parsoid.interwikiMap.get(wiki).split('/w/')[0];
 
         if (dsr) {
             msg.dsr = dsr;
diff --git a/lib/mediawiki.ApiRequest.js b/lib/mediawiki.ApiRequest.js
index 78c56dc..a41c7a0 100644
--- a/lib/mediawiki.ApiRequest.js
+++ b/lib/mediawiki.ApiRequest.js
@@ -297,8 +297,8 @@
                        title = interwiki.title;
                        regex = new RegExp( '^' + interwiki.iw + ':' );
                        title = title.replace( regex, '' );
-                       iwstr = 
this.env.conf.wiki.interwikiMap[interwiki.iw].url ||
-                               
this.env.conf.parsoid.interwikiMap[interwiki.iw].url ||
+                       iwstr = 
this.env.conf.wiki.interwikiMap.get(interwiki.iw).url ||
+                               
this.env.conf.parsoid.interwikiMap.get(interwiki.iw).url ||
                                '/' + interwiki.iw + '/' + '$1';
                        location = iwstr.replace( '$1', title );
                        error = new DoesNotExistError( 'The page at ' + 
this.title +
diff --git a/lib/mediawiki.ParsoidConfig.js b/lib/mediawiki.ParsoidConfig.js
index 886544b..dff8889 100644
--- a/lib/mediawiki.ParsoidConfig.js
+++ b/lib/mediawiki.ParsoidConfig.js
@@ -4,10 +4,60 @@
  */
 "use strict";
 
+require('./core-upgrade.js');
 var Cite = require('./ext.Cite.js').Cite;
 var Util = require('./mediawiki.Util.js').Util;
 
 var wikipedias = 
"en|de|fr|nl|it|pl|es|ru|ja|pt|zh|sv|vi|uk|ca|no|fi|cs|hu|ko|fa|id|tr|ro|ar|sk|eo|da|sr|lt|ms|eu|he|sl|bg|kk|vo|war|hr|hi|et|az|gl|simple|nn|la|th|el|new|roa-rup|oc|sh|ka|mk|tl|ht|pms|te|ta|be-x-old|ceb|br|be|lv|sq|jv|mg|cy|lb|mr|is|bs|yo|an|hy|fy|bpy|lmo|pnb|ml|sw|bn|io|af|gu|zh-yue|ne|nds|ku|ast|ur|scn|su|qu|diq|ba|tt|my|ga|cv|ia|nap|bat-smg|map-bms|wa|kn|als|am|bug|tg|gd|zh-min-nan|yi|vec|hif|sco|roa-tara|os|arz|nah|uz|sah|mn|sa|mzn|pam|hsb|mi|li|ky|si|co|gan|glk|ckb|bo|fo|bar|bcl|ilo|mrj|fiu-vro|nds-nl|tk|vls|se|gv|ps|rue|dv|nrm|pag|koi|pa|rm|km|kv|udm|csb|mhr|fur|mt|wuu|lij|ug|lad|pi|zea|sc|bh|zh-classical|nov|ksh|or|ang|kw|so|nv|xmf|stq|hak|ay|frp|frr|ext|szl|pcd|ie|gag|haw|xal|ln|rw|pdc|pfl|krc|crh|eml|ace|gn|to|ce|kl|arc|myv|dsb|vep|pap|bjn|as|tpi|lbe|wo|mdf|jbo|kab|av|sn|cbk-zam|ty|srn|kbd|lo|ab|lez|mwl|ltg|ig|na|kg|tet|za|kaa|nso|zu|rmy|cu|tn|chr|got|sm|bi|mo|bm|iu|chy|ik|pih|ss|sd|pnt|cdo|ee|ha|ti|bxr|om|ks|ts|ki|ve|sg|rn|dz|cr|lg|ak|tum|fj|st|tw|ch|ny|ff|xh|ng|ii|cho|mh|aa|kj|ho|mus|kr|hz|tyv|min";
+
+var interwikiMap = new Map();
+wikipedias.split('|').forEach(function(lang) {
+       var dbLangPrefix = lang.replace(/-/g, '_');
+       [ 'wikipedia', 'wikivoyage', 'wikibooks', 'wikisource', 'wikinews',
+         'wikiquote', 'wikiversity', 'wiktionary'
+       ].forEach(function(suffix) {
+               interwikiMap.set(
+                       dbLangPrefix + suffix.replace('pedia', ''),
+                       'http://' + lang + '.' + suffix + '.org/w/api.php'
+               );
+       });
+});
+
+// Add mediawiki.org, commons and localhost too
+interwikiMap.set('mediawikiwiki', 'http://www.mediawiki.org/w/api.php');
+interwikiMap.set('commonswiki', 'http://commons.wikimedia.org/w/api.php');
+interwikiMap.set('localhost', 'http://localhost/wiki/api.php');
+
+// Subclass a Map to avoid overwriting defaults
+// Maybe just let that happen ... it only seems to occur
+// from localSettings
+function IMap() { Map.call(this); }
+Object.setPrototypeOf(IMap, Map);
+IMap.prototype = Object.create(Map.prototype, {
+       constructor: { value: IMap },
+       get: {
+               writeable: false,
+               value: function(key) {
+                       return this.has(key)
+                               ? Map.prototype.get.call(this, key)
+                               : interwikiMap.get(key);
+               }
+       },
+       keys: {
+               writeable: false,
+               value: function() {
+                       // This return an array because the es6-shim doesn't
+                       // expose Iterators.
+                       var keys = Array.from(Map.prototype.keys.call(this));
+                       interwikiMap.forEach(function(val, key) {
+                               if ( keys.indexOf(key) < 0 ) {
+                                       keys.push(key);
+                               }
+                       });
+                       return keys;
+               }
+       }
+});
 
 /**
  * @class
@@ -22,44 +72,20 @@
  * @param {Object} options Any options we want to set over the defaults. Will 
not overwrite things set by the localSettings.setup function. See the class 
properties for more information.
  */
 function ParsoidConfig( localSettings, options ) {
-       var self = this;
-       this.interwikiMap = {};
-
        // 'enwiki' etc for per-wiki proxy. Used by setInterwiki.
-       this.apiProxyURIs = {};
+       this.apiProxyURIs = new Map();
 
        // The default api proxy, overridden by apiProxyURIs entries
        this.defaultAPIProxyURI = undefined;
 
-       // XXX: move to prototype to avoid reconstructing this for each request?
-       wikipedias.split( '|' ).forEach(function(lang) {
-               // Wikipedia
-               var dbLangPrefix = lang.replace(/-/g, '_');
-               self.interwikiMap[dbLangPrefix + 'wiki'] = 'http://' + lang +
-                               '.wikipedia.org/w/api.php';
-
-               // Wiktionary
-               self.interwikiMap[dbLangPrefix + 'wiktionary'] = 'http://' + 
lang +
-                               '.wiktionary.org/w/api.php';
-
-               // Wikivoyage, Wikibooks, Wikisource, Wikinews, Wikiquote & 
Wikiversity
-               // all follow the same pattern
-               ['voyage', 'books', 'source', 'news', 'quote', 'versity']
-                       .forEach(function(suffix) {
-                               self.interwikiMap[dbLangPrefix + 'wiki' + 
suffix] = 'http://' +
-                                       lang + '.wiki' + suffix + 
'.org/w/api.php';
-                       });
-       });
-
-       // Add mediawiki.org too
-       this.interwikiMap.mediawikiwiki = 'http://www.mediawiki.org/w/api.php';
-       // Also commons
-       this.interwikiMap.commonswiki = 
'http://commons.wikimedia.org/w/api.php';
-
-       // Add localhost too
-       this.interwikiMap.localhost = 'http://localhost/wiki/api.php';
-
-       this.interwikiRegexp = Object.keys( this.interwikiMap ).join( '|' );
+       this.interwikiMap = new IMap();
+       var it = interwikiMap.keys();
+       var key = it.next();
+       this.interwikiRegexp = key.value;
+       while ( !key.done ) {
+               this.interwikiRegexp += "|" + key.value;
+               key = it.next();
+       }
 
        if ( localSettings && localSettings.setup ) {
                localSettings.setup( this );
@@ -93,11 +119,10 @@
  * back to ParsoidConfig.defaultAPIProxyURI if undefined (default value).
  */
 ParsoidConfig.prototype.setInterwiki = function ( prefix, apiURI, apiProxyURI 
) {
-       this.interwikiMap[prefix] = apiURI;
-       if (apiProxyURI !== undefined) {
-               this.apiProxyURIs[prefix] = apiProxyURI;
+       this.interwikiMap.set(prefix, apiURI);
+       if ( apiProxyURI !== undefined ) {
+               this.apiProxyURIs.set(prefix, apiProxyURI);
        }
-
        if ( this.interwikiRegexp.match( '\\|' + prefix + '\\|' ) === null ) {
                this.interwikiRegexp += '|' + prefix;
        }
@@ -111,7 +136,7 @@
  * @param {string} prefix
  */
 ParsoidConfig.prototype.removeInterwiki = function ( prefix ) {
-       delete this.interwikiMap[prefix];
+       this.interwikiMap.delete(prefix, null);
        this.interwikiRegexp = this.interwikiRegexp.replace(
                new RegExp( '(^|\\|)' + prefix + '(\\||$)' ), function() {
                        return arguments[0] === ("|" + prefix + "|") ? "|" : '';
diff --git a/lib/mediawiki.WikiConfig.js b/lib/mediawiki.WikiConfig.js
index 5e1299e..b44c2e4 100644
--- a/lib/mediawiki.WikiConfig.js
+++ b/lib/mediawiki.WikiConfig.js
@@ -121,32 +121,32 @@
 
        // The interwikiMap maps prefixes to the corresponding information
        // gathered from the api query (prefix, language, url, local)
-       this.interwikiMap = {};
+       this.interwikiMap = new Map();
        var interwikimap = resultConf.interwikimap;
-       var interwikiKeys = Object.keys(interwikimap);
-       for ( var index = 0; index < interwikiKeys.length; index++ ) {
-               var key = interwikimap[index].prefix;
-               this.interwikiMap[key] = interwikimap[index];
-               if (!/\$1/.test(this.interwikiMap[key].url)) {
+       Object.keys(interwikimap).forEach(function(key) {
+               var interwiki = interwikimap[key];
+               conf.interwikiMap.set(interwiki.prefix, interwiki);
+               if ( !/\$1/.test(interwiki.url) ) {
                        // Fix up broken interwiki hrefs that are missing a $1 
placeholder
                        // Just append the placeholder at the end.
                        // This makes sure that the InterWikiMatcher below adds 
one match
                        // group per URI, and that interwiki links work as 
expected.
-                       this.interwikiMap[key].url += '$1';
+                       interwiki.url += '$1';
                }
-       }
+       });
 
        var cachedMatcher = null;
        this.InterWikiMatcher = function () {
                if (cachedMatcher) {
                        return cachedMatcher;
                }
-               var keys = Object.keys(conf.interwikiMap),
+               var keys = [],
                        patterns = [];
-               keys.forEach(function(key) {
-                       var url = conf.interwikiMap[key].url;
+               conf.interwikiMap.forEach(function(val, key) {
+                       keys.push(key);
+                       var url = val.url;
                        var protocolRelative = url.startsWith('//');
-                       if (conf.interwikiMap[key].protorel !== undefined) {
+                       if (val.protorel !== undefined) {
                                url = url.replace( /^https?:/, '' );
                                protocolRelative = true;
                        }
@@ -169,7 +169,7 @@
                                        if (groups[i] !== undefined) {
                                                // The interwiki prefix: 'en', 
'de' etc
                                                var key = keys[i];
-                                               if 
(conf.interwikiMap[key].language) {
+                                               if 
(conf.interwikiMap.get(key).language) {
                                                        // Escape language 
interwikis with a colon
                                                        key = ':' + key;
                                                }
diff --git a/lib/mediawiki.parser.environment.js 
b/lib/mediawiki.parser.environment.js
index 69b78b1..24927ca 100644
--- a/lib/mediawiki.parser.environment.js
+++ b/lib/mediawiki.parser.environment.js
@@ -277,7 +277,7 @@
  * Figure out the proxy URI to use for API requests for a given wiki
  */
 MWParserEnvironment.prototype.getAPIProxyURI = function (prefix) {
-       var apiProxyURI = this.conf.parsoid.apiProxyURIs[prefix];
+       var apiProxyURI = this.conf.parsoid.apiProxyURIs.get(prefix);
        if (apiProxyURI === undefined) {
                // No specific api proxy set. Fall back to generic API proxy.
                apiProxyURI = this.conf.parsoid.defaultAPIProxyURI;
@@ -315,7 +315,7 @@
                return;
        }
 
-       var uri = this.conf.parsoid.interwikiMap[prefix];
+       var uri = this.conf.parsoid.interwikiMap.get(prefix);
        if (!uri) {
                // SSS: Ugh! Looks like parser tests use a prefix
                // that is not part of the interwikiMap -- so we
@@ -324,7 +324,7 @@
                // interwikiMap need updating or is this use-case
                // valid outside of parserTests??
                this.log("error","Did not find api uri for " + prefix + "; 
defaulting to en");
-               uri = this.conf.parsoid.interwikiMap.en;
+               uri = this.conf.parsoid.interwikiMap.get("en");
        }
 
        this.conf.parsoid.apiURI = uri;
@@ -387,7 +387,7 @@
                var nsMatch = name.match( /^([a-zA-Z\-]+):/ ),
                        ns = nsMatch && nsMatch[1] || '';
                if( ns !== '' && ns !== name ) {
-                       if ( self.conf.parsoid.interwikiMap[ns.toLowerCase()] ) 
{
+                       if ( 
self.conf.parsoid.interwikiMap.get(ns.toLowerCase()) ) {
                                forceNS += ns + ':';
                                name = name.substr( nsMatch[0].length );
                                splitNS();
diff --git a/lib/wts.LinkHandler.js b/lib/wts.LinkHandler.js
index f2f6484..1707997 100644
--- a/lib/wts.LinkHandler.js
+++ b/lib/wts.LinkHandler.js
@@ -284,8 +284,8 @@
                                                // Check if the old prefix 
mapped to the same URL as
                                                // the new one. Use the old one 
if that's the case.
                                                // Example: [[w:Foo]] vs. 
[[:en:Foo]]
-                                               
(env.conf.wiki.interwikiMap[oldPrefix[1].toLowerCase().trim().replace(/^:/, 
'')] || {}).url ===
-                                               
(env.conf.wiki.interwikiMap[interWikiMatch[0].toLowerCase().replace(/^:/, '')] 
|| {}).url
+                                               
(env.conf.wiki.interwikiMap.get(oldPrefix[1].toLowerCase().trim().replace(/^:/, 
'')) || {}).url ===
+                                               
(env.conf.wiki.interwikiMap.get(interWikiMatch[0].toLowerCase().replace(/^:/, 
'')) || {}).url
                                                ))
                                {
                                        // Reuse old prefix capitalization
diff --git a/tests/parserTests.js b/tests/parserTests.js
index 2bc90fd..b6b06ba 100755
--- a/tests/parserTests.js
+++ b/tests/parserTests.js
@@ -1617,7 +1617,7 @@
 
        var i, key,
                parsoidConfig = new ParsoidConfig( null, options ),
-               iwmap = Object.keys( parsoidConfig.interwikiMap );
+               iwmap = parsoidConfig.interwikiMap.keys();
 
        // Set tracing and debugging before the env. object is
        // constructed since tracing backends are registered there.
@@ -1628,7 +1628,7 @@
 
        for ( i = 0; i < iwmap.length; i++ ) {
                key = iwmap[i];
-               parsoidConfig.interwikiMap[key] = mockAPIServerURL;
+               parsoidConfig.interwikiMap.set(key, mockAPIServerURL);
        }
 
        // Create a new parser environment
@@ -1917,12 +1917,12 @@
                                                                }
                                                        };
                                                        
Object.keys(iwl).forEach(function(key) {
-                                                               
wikiConf.interwikiMap[key] =
-                                                                       
wikiConf.interwikiMap[key] ?
-                                                                       
Util.clone(wikiConf.interwikiMap[key]) :
-                                                                       {};
+                                                               
wikiConf.interwikiMap.set(key,
+                                                                       
wikiConf.interwikiMap.has(key) ?
+                                                                       
Util.clone(wikiConf.interwikiMap.get(key)) :
+                                                                       {});
                                                                
Object.keys(iwl[key]).forEach(function(f) {
-                                                                       
wikiConf.interwikiMap[key][f] = iwl[key][f];
+                                                                       
wikiConf.interwikiMap.get(key)[f] = iwl[key][f];
                                                                });
                                                        });
                                                        // Add 'MemoryAlpha' 
namespace (bug 51680)

-- 
To view, visit https://gerrit.wikimedia.org/r/151068
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0e0cae162d6448799a1ca2c1c44ec08aff753fac
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/services/parsoid
Gerrit-Branch: master
Gerrit-Owner: Arlolra <abrea...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to