/* 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/. */ /** * Intl.DisplayNames internal properties. */ function displayNamesLocaleData() { // Intl.DisplayNames doesn't support any extension keys. return {}; } var displayNamesInternalProperties = { localeData: displayNamesLocaleData, relevantExtensionKeys: [], }; function mozDisplayNamesLocaleData() { return { ca: intl_availableCalendars, default: { ca: intl_defaultCalendar, }, }; } var mozDisplayNamesInternalProperties = { localeData: mozDisplayNamesLocaleData, relevantExtensionKeys: ["ca"], }; /** * Intl.DisplayNames ( [ locales [ , options ] ] ) * * Compute an internal properties object from |lazyDisplayNamesData|. */ function resolveDisplayNamesInternals(lazyDisplayNamesData) { assert(IsObject(lazyDisplayNamesData), "lazy data not an object?"); var internalProps = std_Object_create(null); var mozExtensions = lazyDisplayNamesData.mozExtensions; var DisplayNames = mozExtensions ? mozDisplayNamesInternalProperties : displayNamesInternalProperties; // Compute effective locale. // Step 7. var localeData = DisplayNames.localeData; // Step 10. var r = ResolveLocale( "DisplayNames", lazyDisplayNamesData.requestedLocales, lazyDisplayNamesData.opt, DisplayNames.relevantExtensionKeys, localeData ); // Step 12. internalProps.style = lazyDisplayNamesData.style; // Step 14. var type = lazyDisplayNamesData.type; internalProps.type = type; // Step 16. internalProps.fallback = lazyDisplayNamesData.fallback; // Step 17. internalProps.locale = r.locale; // Step 25. if (type === "language") { internalProps.languageDisplay = lazyDisplayNamesData.languageDisplay; } if (mozExtensions) { internalProps.calendar = r.ca; } // The caller is responsible for associating |internalProps| with the right // object using |setInternalProperties|. return internalProps; } /** * Returns an object containing the DisplayNames internal properties of |obj|. */ function getDisplayNamesInternals(obj) { assert(IsObject(obj), "getDisplayNamesInternals called with non-object"); assert( intl_GuardToDisplayNames(obj) !== null, "getDisplayNamesInternals called with non-DisplayNames" ); var internals = getIntlObjectInternals(obj); assert( internals.type === "DisplayNames", "bad type escaped getIntlObjectInternals" ); // If internal properties have already been computed, use them. var internalProps = maybeInternalProperties(internals); if (internalProps) { return internalProps; } // Otherwise it's time to fully create them. internalProps = resolveDisplayNamesInternals(internals.lazyData); setInternalProperties(internals, internalProps); return internalProps; } /** * Intl.DisplayNames ( [ locales [ , options ] ] ) * * Initializes an object as a DisplayNames. * * 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 DisplayNames. * This later work occurs in |resolveDisplayNamesInternals|; steps not noted * here occur there. */ function InitializeDisplayNames(displayNames, locales, options, mozExtensions) { assert( IsObject(displayNames), "InitializeDisplayNames called with non-object" ); assert( intl_GuardToDisplayNames(displayNames) !== null, "InitializeDisplayNames called with non-DisplayNames" ); // Lazy DisplayNames data has the following structure: // // { // requestedLocales: List of locales, // // opt: // opt object computed in InitializeDisplayNames // { // localeMatcher: "lookup" / "best fit", // // ca: string matching a Unicode extension type, // optional // } // // localeMatcher: "lookup" / "best fit", // // style: "narrow" / "short" / "abbreviated" / "long", // // type: "language" / "region" / "script" / "currency" / "weekday" / // "month" / "quarter" / "dayPeriod" / "dateTimeField" // // fallback: "code" / "none", // // // field present only if type === "language": // languageDisplay: "dialect" / "standard", // // mozExtensions: true / false, // } // // Note that lazy data is only installed as a final step of initialization, // so every DisplayNames lazy data object has *all* these properties, never a // subset of them. var lazyDisplayNamesData = std_Object_create(null); // Step 3. var requestedLocales = CanonicalizeLocaleList(locales); lazyDisplayNamesData.requestedLocales = requestedLocales; // Step 4. if (!IsObject(options)) { ThrowTypeError( JSMSG_OBJECT_REQUIRED, options === null ? "null" : typeof options ); } // Step 5. var opt = new_Record(); lazyDisplayNamesData.opt = opt; lazyDisplayNamesData.mozExtensions = mozExtensions; // Steps 7-8. var matcher = GetOption( options, "localeMatcher", "string", ["lookup", "best fit"], "best fit" ); opt.localeMatcher = matcher; if (mozExtensions) { var calendar = GetOption( options, "calendar", "string", undefined, undefined ); if (calendar !== undefined) { calendar = intl_ValidateAndCanonicalizeUnicodeExtensionType( calendar, "calendar", "ca" ); } opt.ca = calendar; } // Step 10. var style; if (mozExtensions) { style = GetOption( options, "style", "string", ["narrow", "short", "abbreviated", "long"], "long" ); } else { style = GetOption( options, "style", "string", ["narrow", "short", "long"], "long" ); } // Step 11. lazyDisplayNamesData.style = style; // Step 12. var type; if (mozExtensions) { type = GetOption( options, "type", "string", [ "language", "region", "script", "currency", "calendar", "dateTimeField", "weekday", "month", "quarter", "dayPeriod", ], undefined ); } else { type = GetOption( options, "type", "string", ["language", "region", "script", "currency", "calendar", "dateTimeField"], undefined ); } // Step 13. if (type === undefined) { ThrowTypeError(JSMSG_UNDEFINED_TYPE); } // Step 14. lazyDisplayNamesData.type = type; // Step 15. var fallback = GetOption( options, "fallback", "string", ["code", "none"], "code" ); // Step 16. lazyDisplayNamesData.fallback = fallback; // Step 24. var languageDisplay = GetOption( options, "languageDisplay", "string", ["dialect", "standard"], "dialect" ); // Step 25. if (type === "language") { lazyDisplayNamesData.languageDisplay = languageDisplay; } // We've done everything that must be done now: mark the lazy data as fully // computed and install it. initializeIntlObject(displayNames, "DisplayNames", lazyDisplayNamesData); } /** * 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. */ function Intl_DisplayNames_supportedLocalesOf(locales /*, options*/) { var options = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Step 1. var availableLocales = "DisplayNames"; // Step 2. var requestedLocales = CanonicalizeLocaleList(locales); // Step 3. return SupportedLocales(availableLocales, requestedLocales, options); } /** * Returns the resolved options for a DisplayNames object. */ function Intl_DisplayNames_of(code) { // Step 1. var displayNames = this; // Steps 2-3. if ( !IsObject(displayNames) || (displayNames = intl_GuardToDisplayNames(displayNames)) === null ) { return callFunction( intl_CallDisplayNamesMethodIfWrapped, this, "Intl_DisplayNames_of" ); } code = ToString(code); var internals = getDisplayNamesInternals(displayNames); // Unpack the internals object to avoid a slow runtime to selfhosted JS call // in |intl_ComputeDisplayName()|. var { locale, calendar = "", style, type, languageDisplay = "", fallback, } = internals; // Steps 5-10. return intl_ComputeDisplayName( displayNames, locale, calendar, style, languageDisplay, fallback, type, code ); } /** * Returns the resolved options for a DisplayNames object. */ function Intl_DisplayNames_resolvedOptions() { // Step 1. var displayNames = this; // Steps 2-3. if ( !IsObject(displayNames) || (displayNames = intl_GuardToDisplayNames(displayNames)) === null ) { return callFunction( intl_CallDisplayNamesMethodIfWrapped, this, "Intl_DisplayNames_resolvedOptions" ); } var internals = getDisplayNamesInternals(displayNames); // Steps 4-5. var options = { locale: internals.locale, style: internals.style, type: internals.type, fallback: internals.fallback, }; // languageDisplay is only present for language display names. assert( hasOwn("languageDisplay", internals) === (internals.type === "language"), "languageDisplay is present iff type is 'language'" ); if (hasOwn("languageDisplay", internals)) { DefineDataProperty(options, "languageDisplay", internals.languageDisplay); } if (hasOwn("calendar", internals)) { DefineDataProperty(options, "calendar", internals.calendar); } // Step 6. return options; }