From 1e95ba963d25f314d7118e5d4196260d269f1d2f Mon Sep 17 00:00:00 2001 From: Gurzau Raul Date: Fri, 13 Jul 2018 20:02:32 +0300 Subject: [PATCH] Backed out changeset 24a8cf2131d1 (bug 1384236) for failing at extensions/test/xpcshell/test_webextension_langpack.js on a CLOSED TREE --- intl/l10n/L10nRegistry.jsm | 85 +++++++++++++++++++---------- intl/l10n/Localization.jsm | 1 + intl/l10n/MessageContext.jsm | 3 +- intl/l10n/test/test_l10nregistry.js | 17 ++++-- intl/l10n/test/test_localization.js | 3 + intl/l10n/test/test_pseudo.js | 2 + 6 files changed, 75 insertions(+), 36 deletions(-) diff --git a/intl/l10n/L10nRegistry.jsm b/intl/l10n/L10nRegistry.jsm index f0e1a8575626..021099b1223d 100644 --- a/intl/l10n/L10nRegistry.jsm +++ b/intl/l10n/L10nRegistry.jsm @@ -1,6 +1,6 @@ const { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm", {}); const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {}); -const { MessageContext, FluentResource } = ChromeUtils.import("resource://gre/modules/MessageContext.jsm", {}); +const { MessageContext } = ChromeUtils.import("resource://gre/modules/MessageContext.jsm", {}); ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]); @@ -76,8 +76,10 @@ XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]); * and will produce a new set of permutations placing the language pack provided resources * at the top. */ + const L10nRegistry = { sources: new Map(), + ctxCache: new Map(), bootstrap: null, /** @@ -93,27 +95,8 @@ const L10nRegistry = { await this.bootstrap; } const sourcesOrder = Array.from(this.sources.keys()).reverse(); - const pseudoNameFromPref = Services.prefs.getStringPref("intl.l10n.pseudo", ""); for (const locale of requestedLangs) { - for (const fetchPromises of generateResourceSetsForLocale(locale, sourcesOrder, resourceIds)) { - const ctxPromise = Promise.all(fetchPromises).then( - dataSets => { - const ctx = new MessageContext(locale, { - ...MSG_CONTEXT_OPTIONS, - transform: PSEUDO_STRATEGIES[pseudoNameFromPref], - }); - for (const data of dataSets) { - if (data === null) { - return null; - } - ctx.addResource(data); - } - return ctx; - }, - () => null - ); - yield await ctxPromise; - } + yield * generateContextsForLocale(locale, sourcesOrder, resourceIds); } }, @@ -143,6 +126,7 @@ const L10nRegistry = { throw new Error(`Source with name "${source.name}" is not registered.`); } this.sources.set(source.name, source); + this.ctxCache.clear(); Services.locale.setAvailableLocales(this.getAvailableLocales()); }, @@ -174,6 +158,21 @@ const L10nRegistry = { }, }; +/** + * A helper function for generating unique context ID used for caching + * MessageContexts. + * + * @param {String} locale + * @param {Array} sourcesOrder + * @param {Array} resourceIds + * @returns {String} + */ +function generateContextID(locale, sourcesOrder, resourceIds) { + const sources = sourcesOrder.join(","); + const ids = resourceIds.join(","); + return `${locale}|${sources}|${ids}`; +} + /** * This function generates an iterator over MessageContexts for a single locale * for a given list of resourceIds for all possible combinations of sources. @@ -188,7 +187,7 @@ const L10nRegistry = { * @param {Array} [resolvedOrder] * @returns {AsyncIterator} */ -function* generateResourceSetsForLocale(locale, sourcesOrder, resourceIds, resolvedOrder = []) { +async function* generateContextsForLocale(locale, sourcesOrder, resourceIds, resolvedOrder = []) { const resolvedLength = resolvedOrder.length; const resourcesLength = resourceIds.length; @@ -209,11 +208,14 @@ function* generateResourceSetsForLocale(locale, sourcesOrder, resourceIds, resol // If the number of resolved sources equals the number of resources, // create the right context and return it if it loads. if (resolvedLength + 1 === resourcesLength) { - yield generateResourceSet(locale, order, resourceIds); + const ctx = await generateContext(locale, order, resourceIds); + if (ctx !== null) { + yield ctx; + } } else if (resolvedLength < resourcesLength) { // otherwise recursively load another generator that walks over the // partially resolved list of sources. - yield * generateResourceSetsForLocale(locale, sourcesOrder, resourceIds, order); + yield * generateContextsForLocale(locale, sourcesOrder, resourceIds, order); } } } @@ -344,10 +346,35 @@ const PSEUDO_STRATEGIES = { * @param {Array} resourceIds * @returns {Promise} */ -function generateResourceSet(locale, sourcesOrder, resourceIds) { - return resourceIds.map((resourceId, i) => { +function generateContext(locale, sourcesOrder, resourceIds) { + const ctxId = generateContextID(locale, sourcesOrder, resourceIds); + if (L10nRegistry.ctxCache.has(ctxId)) { + return L10nRegistry.ctxCache.get(ctxId); + } + + const fetchPromises = resourceIds.map((resourceId, i) => { return L10nRegistry.sources.get(sourcesOrder[i]).fetchFile(locale, resourceId); }); + + const ctxPromise = Promise.all(fetchPromises).then( + dataSets => { + const pseudoNameFromPref = Services.prefs.getStringPref("intl.l10n.pseudo", ""); + const ctx = new MessageContext(locale, { + ...MSG_CONTEXT_OPTIONS, + transform: PSEUDO_STRATEGIES[pseudoNameFromPref], + }); + for (const data of dataSets) { + if (data === null) { + return null; + } + ctx.addMessages(data); + } + return ctx; + }, + () => null + ); + L10nRegistry.ctxCache.set(ctxId, ctxPromise); + return ctxPromise; } /** @@ -427,9 +454,7 @@ class FileSource { if (this.cache[fullPath] === false) { return Promise.reject(`The source has no resources for path "${fullPath}"`); } - // `true` means that the file is indexed, but hasn't - // been fetched yet. - if (this.cache[fullPath] !== true) { + if (this.cache[fullPath].then) { return this.cache[fullPath]; } } else if (this.indexed) { @@ -437,7 +462,7 @@ class FileSource { } return this.cache[fullPath] = L10nRegistry.load(fullPath).then( data => { - return this.cache[fullPath] = FluentResource.fromString(data); + return this.cache[fullPath] = data; }, err => { this.cache[fullPath] = false; diff --git a/intl/l10n/Localization.jsm b/intl/l10n/Localization.jsm index 2a0c0c4ae27e..d7d997a28b22 100644 --- a/intl/l10n/Localization.jsm +++ b/intl/l10n/Localization.jsm @@ -263,6 +263,7 @@ class Localization { case "nsPref:changed": switch (data) { case "intl.l10n.pseudo": + L10nRegistry.ctxCache.clear(); this.onChange(); } break; diff --git a/intl/l10n/MessageContext.jsm b/intl/l10n/MessageContext.jsm index 270fe82adae1..f7b18f90eb83 100644 --- a/intl/l10n/MessageContext.jsm +++ b/intl/l10n/MessageContext.jsm @@ -1908,5 +1908,4 @@ class MessageContext { } this.MessageContext = MessageContext; -this.FluentResource = FluentResource; -var EXPORTED_SYMBOLS = ["MessageContext", "FluentResource"]; +var EXPORTED_SYMBOLS = ["MessageContext"]; diff --git a/intl/l10n/test/test_l10nregistry.js b/intl/l10n/test/test_l10nregistry.js index 0acc2389c1f9..7fd8e82bde77 100644 --- a/intl/l10n/test/test_l10nregistry.js +++ b/intl/l10n/test/test_l10nregistry.js @@ -40,6 +40,7 @@ add_task(async function test_empty_resourceids() { // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); }); /** @@ -56,6 +57,7 @@ add_task(async function test_empty_sources() { // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); }); /** @@ -78,6 +80,7 @@ add_task(async function test_methods_calling() { // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); }); /** @@ -115,6 +118,7 @@ add_task(async function test_has_one_source() { // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); }); /** @@ -171,6 +175,7 @@ add_task(async function test_has_two_sources() { // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); }); /** @@ -198,6 +203,7 @@ add_task(async function test_indexed() { // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); }); /** @@ -238,6 +244,7 @@ add_task(async function test_override() { // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); }); /** @@ -275,6 +282,7 @@ add_task(async function test_updating() { // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); }); /** @@ -340,6 +348,7 @@ add_task(async function test_removing() { // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); }); /** @@ -369,16 +378,15 @@ add_task(async function test_missing_file() { // returns a single context let ctxs = L10nRegistry.generateContexts(["en-US"], ["test.ftl", "test2.ftl"]); - (await ctxs.next()); // [platform, platform] - both present - (await ctxs.next()); // [platform, app] - second missing - (await ctxs.next()); // [app, platform] - both present - (await ctxs.next()); // [app, app] - second missing + (await ctxs.next()); + (await ctxs.next()); equal((await ctxs.next()).done, true); // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); }); /** @@ -439,5 +447,6 @@ add_task(async function test_parallel_io() { // cleanup L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); L10nRegistry.load = originalLoad; }); diff --git a/intl/l10n/test/test_localization.js b/intl/l10n/test/test_localization.js index 0f9c9d857652..b251ad43291c 100644 --- a/intl/l10n/test/test_localization.js +++ b/intl/l10n/test/test_localization.js @@ -43,6 +43,7 @@ add_task(async function test_methods_calling() { equal(values[1], "[en] Value3"); L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); L10nRegistry.load = originalLoad; Services.locale.setRequestedLocales(originalRequested); }); @@ -89,6 +90,7 @@ key = { PLATFORM() -> `${ known_platforms[AppConstants.platform].toUpperCase() } Value`)); L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); L10nRegistry.load = originalLoad; }); @@ -136,6 +138,7 @@ add_task(async function test_add_remove_resourceIds() { equal(values[1], "Value2"); L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); L10nRegistry.load = originalLoad; Services.locale.setRequestedLocales(originalRequested); }); diff --git a/intl/l10n/test/test_pseudo.js b/intl/l10n/test/test_pseudo.js index bfa3d2d9f9a1..e81e053cb019 100644 --- a/intl/l10n/test/test_pseudo.js +++ b/intl/l10n/test/test_pseudo.js @@ -94,6 +94,7 @@ add_task(async function test_accented_works() { } L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); L10nRegistry.load = originalValues.load; Services.locale.setRequestedLocales(originalValues.requested); }); @@ -125,6 +126,7 @@ add_task(async function test_unavailable_strategy_works() { Services.prefs.setStringPref("intl.l10n.pseudo", ""); L10nRegistry.sources.clear(); + L10nRegistry.ctxCache.clear(); L10nRegistry.load = originalValues.load; Services.locale.setRequestedLocales(originalValues.requested); });