Source code

Revision control

Copy as Markdown

Other Tools

/* 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;
}