/* 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/. */ /** * ListFormat internal properties. */ var listFormatInternalProperties = { localeData: function() // eslint-disable-line object-shorthand { // ListFormat don't support any extension keys. return {}; }, relevantExtensionKeys: [] }; /** * Intl.ListFormat ( [ locales [ , options ] ] ) * * Compute an internal properties object from |lazyListFormatData|. */ function resolveListFormatInternals(lazyListFormatData) { assert(IsObject(lazyListFormatData), "lazy data not an object?"); var internalProps = std_Object_create(null); var ListFormat = listFormatInternalProperties; // Compute effective locale. // Step 9. var localeData = ListFormat.localeData; // Step 10. var r = ResolveLocale("ListFormat", lazyListFormatData.requestedLocales, lazyListFormatData.opt, ListFormat.relevantExtensionKeys, localeData); // Step 11. internalProps.locale = r.locale; // Step 13. internalProps.type = lazyListFormatData.type; // Step 15. internalProps.style = lazyListFormatData.style; // Steps 16-23 (not applicable in our implementation). // The caller is responsible for associating |internalProps| with the right // object using |setInternalProperties|. return internalProps; } /** * Returns an object containing the ListFormat internal properties of |obj|. */ function getListFormatInternals(obj) { assert(IsObject(obj), "getListFormatInternals called with non-object"); assert(GuardToListFormat(obj) !== null, "getListFormatInternals called with non-ListFormat"); var internals = getIntlObjectInternals(obj); assert(internals.type === "ListFormat", "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 = resolveListFormatInternals(internals.lazyData); setInternalProperties(internals, internalProps); return internalProps; } /** * Intl.ListFormat ( [ locales [ , options ] ] ) * * Initializes an object as a ListFormat. * * 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 ListFormat. * This later work occurs in |resolveListFormatInternals|; steps not noted * here occur there. */ function InitializeListFormat(listFormat, locales, options, supportsTypeAndStyle) { assert(IsObject(listFormat), "InitializeListFormat called with non-object"); assert(GuardToListFormat(listFormat) !== null, "InitializeListFormat called with non-ListFormat"); // Lazy ListFormat data has the following structure: // // { // requestedLocales: List of locales, // type: "conjunction" / "disjunction" / "unit", // style: "long" / "short" / "narrow", // // opt: // opt object computed in InitializeListFormat // { // localeMatcher: "lookup" / "best fit", // } // } // // Note that lazy data is only installed as a final step of initialization, // so every ListFormat lazy data object has *all* these properties, never a // subset of them. var lazyListFormatData = std_Object_create(null); // Step 3. var requestedLocales = CanonicalizeLocaleList(locales); lazyListFormatData.requestedLocales = requestedLocales; // Steps 4-5. if (options === undefined) options = std_Object_create(null); else options = ToObject(options); // Step 6. var opt = new Record(); lazyListFormatData.opt = opt; // Steps 7-8. let matcher = GetOption(options, "localeMatcher", "string", ["lookup", "best fit"], "best fit"); opt.localeMatcher = matcher; // Compute formatting options. // Supporting all "type" and "style" options requires draft APIs in ICU 67, // which may not be available when compiling against a system ICU. // Steps 12-13. var type = GetOption(options, "type", "string", supportsTypeAndStyle ? ["conjunction", "disjunction", "unit"] : ["conjunction"], "conjunction"); lazyListFormatData.type = type; // Steps 14-15. var style = GetOption(options, "style", "string", supportsTypeAndStyle ? ["long", "short", "narrow"] : ["long"], "long"); lazyListFormatData.style = style; // We've done everything that must be done now: mark the lazy data as fully // computed and install it. initializeIntlObject(listFormat, "ListFormat", lazyListFormatData); } /** * 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_ListFormat_supportedLocalesOf(locales /*, options*/) { var options = arguments.length > 1 ? arguments[1] : undefined; // Step 1. var availableLocales = "ListFormat"; // Step 2. var requestedLocales = CanonicalizeLocaleList(locales); // Step 3. return SupportedLocales(availableLocales, requestedLocales, options); } /** * StringListFromIterable ( iterable ) */ function StringListFromIterable(iterable, methodName) { // Step 1. if (iterable === undefined) { return []; } // Step 3. var list = []; // Steps 2, 4-5. for (var element of allowContentIter(iterable)) { // Step 5.b.ii. if (typeof element !== "string") { ThrowTypeError(JSMSG_NOT_EXPECTED_TYPE, methodName, "string", typeof element); } // Step 5.b.iii. _DefineDataProperty(list, list.length, element); } // Step 6. return list; } /** * Intl.ListFormat.prototype.format ( list ) */ function Intl_ListFormat_format(list) { // Step 1. var listFormat = this; // Steps 2-3. if (!IsObject(listFormat) || (listFormat = GuardToListFormat(listFormat)) === null) { return callFunction(CallListFormatMethodIfWrapped, this, list, "Intl_ListFormat_format"); } // Step 4. var stringList = StringListFromIterable(list, "format"); // We can directly return if |stringList| contains less than two elements. if (stringList.length < 2) { return stringList.length === 0 ? "" : stringList[0]; } // Ensure the ListFormat internals are resolved. getListFormatInternals(listFormat); // Step 5. return intl_FormatList(listFormat, stringList, /* formatToParts = */ false); } /** * Intl.ListFormat.prototype.formatToParts ( list ) */ function Intl_ListFormat_formatToParts(list) { // Step 1. var listFormat = this; // Steps 2-3. if (!IsObject(listFormat) || (listFormat = GuardToListFormat(listFormat)) === null) { return callFunction(CallListFormatMethodIfWrapped, this, list, "Intl_ListFormat_formatToParts"); } // Step 4. var stringList = StringListFromIterable(list, "formatToParts"); // We can directly return if |stringList| contains less than two elements. if (stringList.length < 2) { return stringList.length === 0 ? [] : [{type: "element", value: stringList[0]}]; } // Ensure the ListFormat internals are resolved. getListFormatInternals(listFormat); // Step 5. return intl_FormatList(listFormat, stringList, /* formatToParts = */ true); } /** * Returns the resolved options for a ListFormat object. */ function Intl_ListFormat_resolvedOptions() { // Step 1. var listFormat = this; // Steps 2-3. if (!IsObject(listFormat) || (listFormat = GuardToListFormat(listFormat)) === null) { return callFunction(CallListFormatMethodIfWrapped, this, "Intl_ListFormat_resolvedOptions"); } var internals = getListFormatInternals(listFormat); // Steps 4-5. var result = { locale: internals.locale, type: internals.type, style: internals.style, }; // Step 6. return result; }