/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * PluralRules internal properties. * * Spec: ECMAScript 402 API, PluralRules, 13.3.3. */ var pluralRulesInternalProperties = { localeData: pluralRulesLocaleData, relevantExtensionKeys: [], }; function pluralRulesLocaleData() { // PluralRules don't support any extension keys. return {}; } /** * Compute an internal properties object from |lazyPluralRulesData|. */ function resolvePluralRulesInternals(lazyPluralRulesData) { assert(IsObject(lazyPluralRulesData), "lazy data not an object?"); var internalProps = std_Object_create(null); var PluralRules = pluralRulesInternalProperties; // Compute effective locale. // Step 10. var localeData = PluralRules.localeData; // Step 11. const r = ResolveLocale( "PluralRules", lazyPluralRulesData.requestedLocales, lazyPluralRulesData.opt, PluralRules.relevantExtensionKeys, localeData ); // Step 12. internalProps.locale = r.locale; // Step 8. internalProps.type = lazyPluralRulesData.type; // Step 9. internalProps.minimumIntegerDigits = lazyPluralRulesData.minimumIntegerDigits; if ("minimumFractionDigits" in lazyPluralRulesData) { assert( "maximumFractionDigits" in lazyPluralRulesData, "min/max frac digits mismatch" ); internalProps.minimumFractionDigits = lazyPluralRulesData.minimumFractionDigits; internalProps.maximumFractionDigits = lazyPluralRulesData.maximumFractionDigits; } if ("minimumSignificantDigits" in lazyPluralRulesData) { assert( "maximumSignificantDigits" in lazyPluralRulesData, "min/max sig digits mismatch" ); internalProps.minimumSignificantDigits = lazyPluralRulesData.minimumSignificantDigits; internalProps.maximumSignificantDigits = lazyPluralRulesData.maximumSignificantDigits; } // Intl.NumberFormat v3 Proposal internalProps.roundingPriority = lazyPluralRulesData.roundingPriority; // Step 13 (lazily computed on first access). internalProps.pluralCategories = null; return internalProps; } /** * Returns an object containing the PluralRules internal properties of |obj|. */ function getPluralRulesInternals(obj) { assert(IsObject(obj), "getPluralRulesInternals called with non-object"); assert( intl_GuardToPluralRules(obj) !== null, "getPluralRulesInternals called with non-PluralRules" ); var internals = getIntlObjectInternals(obj); assert( internals.type === "PluralRules", "bad type escaped getIntlObjectInternals" ); var internalProps = maybeInternalProperties(internals); if (internalProps) { return internalProps; } internalProps = resolvePluralRulesInternals(internals.lazyData); setInternalProperties(internals, internalProps); return internalProps; } /** * Initializes an object as a PluralRules. * * This method is complicated a moderate bit by its implementing initialization * as a *lazy* concept. Everything that must happen now, does -- but we defer * all the work we can until the object is actually used as a PluralRules. * This later work occurs in |resolvePluralRulesInternals|; steps not noted * here occur there. * * Spec: ECMAScript 402 API, PluralRules, 13.1.1. */ function InitializePluralRules(pluralRules, locales, options) { assert(IsObject(pluralRules), "InitializePluralRules called with non-object"); assert( intl_GuardToPluralRules(pluralRules) !== null, "InitializePluralRules called with non-PluralRules" ); // Lazy PluralRules data has the following structure: // // { // requestedLocales: List of locales, // type: "cardinal" / "ordinal", // // opt: // opt object computer in InitializePluralRules // { // localeMatcher: "lookup" / "best fit", // } // // minimumIntegerDigits: integer ∈ [1, 21], // // // optional, mutually exclusive with the significant-digits option // minimumFractionDigits: integer ∈ [0, 20], // maximumFractionDigits: integer ∈ [0, 20], // // // optional, mutually exclusive with the fraction-digits option // minimumSignificantDigits: integer ∈ [1, 21], // maximumSignificantDigits: integer ∈ [1, 21], // // roundingPriority: "auto" / "lessPrecision" / "morePrecision", // } // // Note that lazy data is only installed as a final step of initialization, // so every PluralRules lazy data object has *all* these properties, never a // subset of them. const lazyPluralRulesData = std_Object_create(null); // Step 1. let requestedLocales = CanonicalizeLocaleList(locales); lazyPluralRulesData.requestedLocales = requestedLocales; // Steps 2-3. if (options === undefined) { options = std_Object_create(null); } else { options = ToObject(options); } // Step 4. let opt = new_Record(); lazyPluralRulesData.opt = opt; // Steps 5-6. let matcher = GetOption( options, "localeMatcher", "string", ["lookup", "best fit"], "best fit" ); opt.localeMatcher = matcher; // Step 7. const type = GetOption( options, "type", "string", ["cardinal", "ordinal"], "cardinal" ); lazyPluralRulesData.type = type; // Step 9. SetNumberFormatDigitOptions(lazyPluralRulesData, options, 0, 3, "standard"); // Step 15. // // We've done everything that must be done now: mark the lazy data as fully // computed and install it. initializeIntlObject(pluralRules, "PluralRules", lazyPluralRulesData); } /** * Returns the subset of the given locale list for which this locale list has a * matching (possibly fallback) locale. Locales appear in the same order in the * returned list as in the input list. * * Spec: ECMAScript 402 API, PluralRules, 13.3.2. */ function Intl_PluralRules_supportedLocalesOf(locales /*, options*/) { var options = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Step 1. var availableLocales = "PluralRules"; // Step 2. let requestedLocales = CanonicalizeLocaleList(locales); // Step 3. return SupportedLocales(availableLocales, requestedLocales, options); } /** * Returns a String value representing the plural category matching * the number passed as value according to the * effective locale and the formatting options of this PluralRules. * * Spec: ECMAScript 402 API, PluralRules, 13.4.3. */ function Intl_PluralRules_select(value) { // Step 1. let pluralRules = this; // Steps 2-3. if ( !IsObject(pluralRules) || (pluralRules = intl_GuardToPluralRules(pluralRules)) === null ) { return callFunction( intl_CallPluralRulesMethodIfWrapped, this, value, "Intl_PluralRules_select" ); } // Step 4. let n = ToNumber(value); // Ensure the PluralRules internals are resolved. getPluralRulesInternals(pluralRules); // Step 5. return intl_SelectPluralRule(pluralRules, n); } /** * Returns a String value representing the plural category matching the input * number range according to the effective locale and the formatting options * of this PluralRules. */ function Intl_PluralRules_selectRange(start, end) { // Step 1. var pluralRules = this; // Step 2. if ( !IsObject(pluralRules) || (pluralRules = intl_GuardToPluralRules(pluralRules)) === null ) { return callFunction( intl_CallPluralRulesMethodIfWrapped, this, start, end, "Intl_PluralRules_selectRange" ); } // Step 3. if (start === undefined || end === undefined) { ThrowTypeError( JSMSG_UNDEFINED_NUMBER, start === undefined ? "start" : "end", "PluralRules", "selectRange" ); } // Step 4. var x = ToNumber(start); // Step 5. var y = ToNumber(end); // Step 6. return intl_SelectPluralRuleRange(pluralRules, x, y); } /** * Returns the resolved options for a PluralRules object. * * Spec: ECMAScript 402 API, PluralRules, 13.4.4. */ function Intl_PluralRules_resolvedOptions() { // Step 1. var pluralRules = this; // Steps 2-3. if ( !IsObject(pluralRules) || (pluralRules = intl_GuardToPluralRules(pluralRules)) === null ) { return callFunction( intl_CallPluralRulesMethodIfWrapped, this, "Intl_PluralRules_resolvedOptions" ); } var internals = getPluralRulesInternals(pluralRules); // Steps 4-5. var result = { locale: internals.locale, type: internals.type, minimumIntegerDigits: internals.minimumIntegerDigits, }; // Min/Max fraction digits are either both present or not present at all. assert( hasOwn("minimumFractionDigits", internals) === hasOwn("maximumFractionDigits", internals), "minimumFractionDigits is present iff maximumFractionDigits is present" ); if (hasOwn("minimumFractionDigits", internals)) { DefineDataProperty( result, "minimumFractionDigits", internals.minimumFractionDigits ); DefineDataProperty( result, "maximumFractionDigits", internals.maximumFractionDigits ); } // Min/Max significant digits are either both present or not present at all. assert( hasOwn("minimumSignificantDigits", internals) === hasOwn("maximumSignificantDigits", internals), "minimumSignificantDigits is present iff maximumSignificantDigits is present" ); if (hasOwn("minimumSignificantDigits", internals)) { DefineDataProperty( result, "minimumSignificantDigits", internals.minimumSignificantDigits ); DefineDataProperty( result, "maximumSignificantDigits", internals.maximumSignificantDigits ); } // Step 6. var internalsPluralCategories = internals.pluralCategories; if (internalsPluralCategories === null) { internalsPluralCategories = intl_GetPluralCategories(pluralRules); internals.pluralCategories = internalsPluralCategories; } var pluralCategories = []; for (var i = 0; i < internalsPluralCategories.length; i++) { DefineDataProperty(pluralCategories, i, internalsPluralCategories[i]); } // Step 7. DefineDataProperty(result, "pluralCategories", pluralCategories); #ifdef NIGHTLY_BUILD DefineDataProperty(result, "roundingPriority", internals.roundingPriority); #endif // Step 8. return result; }