1
0
mirror of https://github.com/roytam1/UXP.git synced 2026-05-29 16:58:28 +00:00

Bug 1287677 - Add mozIntl.getDisplayNames API

This commit is contained in:
janekptacijarabaci
2018-03-30 18:58:51 +02:00
committed by Roy Tam
parent cac5c5adc7
commit 5381ebe25c
9 changed files with 718 additions and 0 deletions
+381
View File
@@ -102,6 +102,18 @@ Char16ToUChar(char16_t* chars)
MOZ_CRASH("Char16ToUChar: Intl API disabled");
}
inline char16_t*
UCharToChar16(UChar* chars)
{
MOZ_CRASH("UCharToChar16: Intl API disabled");
}
inline const char16_t*
UCharToChar16(const UChar* chars)
{
MOZ_CRASH("UCharToChar16: Intl API disabled");
}
static int32_t
u_strlen(const UChar* s)
{
@@ -356,6 +368,27 @@ enum UCalendarDateFields {
UCAL_DAY_OF_MONTH = UCAL_DATE
};
enum UCalendarMonths {
UCAL_JANUARY,
UCAL_FEBRUARY,
UCAL_MARCH,
UCAL_APRIL,
UCAL_MAY,
UCAL_JUNE,
UCAL_JULY,
UCAL_AUGUST,
UCAL_SEPTEMBER,
UCAL_OCTOBER,
UCAL_NOVEMBER,
UCAL_DECEMBER,
UCAL_UNDECIMBER
};
enum UCalendarAMPMs {
UCAL_AM,
UCAL_PM
};
static UCalendar*
ucal_open(const UChar* zoneID, int32_t len, const char* locale,
UCalendarType type, UErrorCode* status)
@@ -420,6 +453,13 @@ ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* statu
MOZ_CRASH("ucal_getDefaultTimeZone: Intl API disabled");
}
enum UDateTimePatternField {
UDATPG_YEAR_FIELD,
UDATPG_MONTH_FIELD,
UDATPG_WEEK_OF_YEAR_FIELD,
UDATPG_DAY_FIELD,
};
typedef void* UDateTimePatternGenerator;
static UDateTimePatternGenerator*
@@ -436,6 +476,14 @@ udatpg_getBestPattern(UDateTimePatternGenerator* dtpg, const UChar* skeleton,
MOZ_CRASH("udatpg_getBestPattern: Intl API disabled");
}
static const UChar *
udatpg_getAppendItemName(const UDateTimePatternGenerator *dtpg,
UDateTimePatternField field,
int32_t *pLength)
{
MOZ_CRASH("udatpg_getAppendItemName: Intl API disabled");
}
static void
udatpg_close(UDateTimePatternGenerator* dtpg)
{
@@ -488,10 +536,46 @@ enum UDateFormatField {
};
enum UDateFormatStyle {
UDAT_FULL,
UDAT_LONG,
UDAT_MEDIUM,
UDAT_SHORT,
UDAT_DEFAULT = UDAT_MEDIUM,
UDAT_PATTERN = -2,
UDAT_IGNORE = UDAT_PATTERN
};
enum UDateFormatSymbolType {
UDAT_ERAS,
UDAT_MONTHS,
UDAT_SHORT_MONTHS,
UDAT_WEEKDAYS,
UDAT_SHORT_WEEKDAYS,
UDAT_AM_PMS,
UDAT_LOCALIZED_CHARS,
UDAT_ERA_NAMES,
UDAT_NARROW_MONTHS,
UDAT_NARROW_WEEKDAYS,
UDAT_STANDALONE_MONTHS,
UDAT_STANDALONE_SHORT_MONTHS,
UDAT_STANDALONE_NARROW_MONTHS,
UDAT_STANDALONE_WEEKDAYS,
UDAT_STANDALONE_SHORT_WEEKDAYS,
UDAT_STANDALONE_NARROW_WEEKDAYS,
UDAT_QUARTERS,
UDAT_SHORT_QUARTERS,
UDAT_STANDALONE_QUARTERS,
UDAT_STANDALONE_SHORT_QUARTERS,
UDAT_SHORTER_WEEKDAYS,
UDAT_STANDALONE_SHORTER_WEEKDAYS,
UDAT_CYCLIC_YEARS_WIDE,
UDAT_CYCLIC_YEARS_ABBREVIATED,
UDAT_CYCLIC_YEARS_NARROW,
UDAT_ZODIAC_NAMES_WIDE,
UDAT_ZODIAC_NAMES_ABBREVIATED,
UDAT_ZODIAC_NAMES_NARROW
};
static int32_t
udat_countAvailable()
{
@@ -563,6 +647,13 @@ udat_close(UDateFormat* format)
MOZ_CRASH("udat_close: Intl API disabled");
}
static int32_t
udat_getSymbols(const UDateFormat *fmt, UDateFormatSymbolType type, int32_t symbolIndex,
UChar *result, int32_t resultLength, UErrorCode *status)
{
MOZ_CRASH("udat_getSymbols: Intl API disabled");
}
#endif
@@ -2921,6 +3012,296 @@ js::intl_GetCalendarInfo(JSContext* cx, unsigned argc, Value* vp)
return true;
}
template<size_t N>
inline bool
MatchPart(const char** pattern, const char (&part)[N])
{
if (strncmp(*pattern, part, N - 1))
return false;
*pattern += N - 1;
return true;
}
bool
js::intl_ComputeDisplayNames(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 3);
// 1. Assert: locale is a string.
MOZ_ASSERT(args[0].isString());
// 2. Assert: style is a string.
MOZ_ASSERT(args[1].isString());
// 3. Assert: keys is an Array.
MOZ_ASSERT(args[2].isObject());
JSAutoByteString locale(cx, args[0].toString());
if (!locale)
return false;
JSAutoByteString style(cx, args[1].toString());
if (!style)
return false;
RootedArrayObject keys(cx, &args[2].toObject().as<ArrayObject>());
if (!keys)
return false;
// 4. Let result be ArrayCreate(0).
RootedArrayObject result(cx, NewDenseUnallocatedArray(cx, keys->length()));
if (!result)
return false;
UErrorCode status = U_ZERO_ERROR;
UDateFormat* fmt =
udat_open(UDAT_DEFAULT, UDAT_DEFAULT, icuLocale(locale.ptr()),
nullptr, 0, nullptr, 0, &status);
if (U_FAILURE(status)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
return false;
}
ScopedICUObject<UDateFormat, udat_close> datToClose(fmt);
// UDateTimePatternGenerator will be needed for translations of date and
// time fields like "month", "week", "day" etc.
UDateTimePatternGenerator* dtpg = udatpg_open(icuLocale(locale.ptr()), &status);
if (U_FAILURE(status)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
return false;
}
ScopedICUObject<UDateTimePatternGenerator, udatpg_close> datPgToClose(dtpg);
RootedValue keyValue(cx);
RootedString keyValStr(cx);
RootedValue wordVal(cx);
Vector<char16_t, INITIAL_CHAR_BUFFER_SIZE> chars(cx);
if (!chars.resize(INITIAL_CHAR_BUFFER_SIZE))
return false;
// 5. For each element of keys,
for (uint32_t i = 0; i < keys->length(); i++) {
/**
* We iterate over keys array looking for paths that we have code
* branches for.
*
* For any unknown path branch, the wordVal will keep NullValue and
* we'll throw at the end.
*/
if (!GetElement(cx, keys, keys, i, &keyValue))
return false;
JSAutoByteString pattern;
keyValStr = keyValue.toString();
if (!pattern.encodeUtf8(cx, keyValStr))
return false;
wordVal.setNull();
// 5.a. Perform an implementation dependent algorithm to map a key to a
// corresponding display name.
const char* pat = pattern.ptr();
if (!MatchPart(&pat, "dates")) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
if (!MatchPart(&pat, "/")) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
if (MatchPart(&pat, "fields")) {
if (!MatchPart(&pat, "/")) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
UDateTimePatternField fieldType;
if (MatchPart(&pat, "year")) {
fieldType = UDATPG_YEAR_FIELD;
} else if (MatchPart(&pat, "month")) {
fieldType = UDATPG_MONTH_FIELD;
} else if (MatchPart(&pat, "week")) {
fieldType = UDATPG_WEEK_OF_YEAR_FIELD;
} else if (MatchPart(&pat, "day")) {
fieldType = UDATPG_DAY_FIELD;
} else {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
// This part must be the final part with no trailing data.
if (*pat != '\0') {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
int32_t resultSize;
const UChar* value = udatpg_getAppendItemName(dtpg, fieldType, &resultSize);
if (U_FAILURE(status)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
return false;
}
JSString* word = NewStringCopyN<CanGC>(cx, UCharToChar16(value), resultSize);
if (!word)
return false;
wordVal.setString(word);
} else if (MatchPart(&pat, "gregorian")) {
if (!MatchPart(&pat, "/")) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
UDateFormatSymbolType symbolType;
int32_t index;
if (MatchPart(&pat, "months")) {
if (!MatchPart(&pat, "/")) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
if (equal(style, "narrow")) {
symbolType = UDAT_STANDALONE_NARROW_MONTHS;
} else if (equal(style, "short")) {
symbolType = UDAT_STANDALONE_SHORT_MONTHS;
} else {
MOZ_ASSERT(equal(style, "long"));
symbolType = UDAT_STANDALONE_MONTHS;
}
if (MatchPart(&pat, "january")) {
index = UCAL_JANUARY;
} else if (MatchPart(&pat, "february")) {
index = UCAL_FEBRUARY;
} else if (MatchPart(&pat, "march")) {
index = UCAL_MARCH;
} else if (MatchPart(&pat, "april")) {
index = UCAL_APRIL;
} else if (MatchPart(&pat, "may")) {
index = UCAL_MAY;
} else if (MatchPart(&pat, "june")) {
index = UCAL_JUNE;
} else if (MatchPart(&pat, "july")) {
index = UCAL_JULY;
} else if (MatchPart(&pat, "august")) {
index = UCAL_AUGUST;
} else if (MatchPart(&pat, "september")) {
index = UCAL_SEPTEMBER;
} else if (MatchPart(&pat, "october")) {
index = UCAL_OCTOBER;
} else if (MatchPart(&pat, "november")) {
index = UCAL_NOVEMBER;
} else if (MatchPart(&pat, "december")) {
index = UCAL_DECEMBER;
} else {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
} else if (MatchPart(&pat, "weekdays")) {
if (!MatchPart(&pat, "/")) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
if (equal(style, "narrow")) {
symbolType = UDAT_STANDALONE_NARROW_WEEKDAYS;
} else if (equal(style, "short")) {
symbolType = UDAT_STANDALONE_SHORT_WEEKDAYS;
} else {
MOZ_ASSERT(equal(style, "long"));
symbolType = UDAT_STANDALONE_WEEKDAYS;
}
if (MatchPart(&pat, "monday")) {
index = UCAL_MONDAY;
} else if (MatchPart(&pat, "tuesday")) {
index = UCAL_TUESDAY;
} else if (MatchPart(&pat, "wednesday")) {
index = UCAL_WEDNESDAY;
} else if (MatchPart(&pat, "thursday")) {
index = UCAL_THURSDAY;
} else if (MatchPart(&pat, "friday")) {
index = UCAL_FRIDAY;
} else if (MatchPart(&pat, "saturday")) {
index = UCAL_SATURDAY;
} else if (MatchPart(&pat, "sunday")) {
index = UCAL_SUNDAY;
} else {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
} else if (MatchPart(&pat, "dayperiods")) {
if (!MatchPart(&pat, "/")) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
symbolType = UDAT_AM_PMS;
if (MatchPart(&pat, "am")) {
index = UCAL_AM;
} else if (MatchPart(&pat, "pm")) {
index = UCAL_PM;
} else {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
} else {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
// This part must be the final part with no trailing data.
if (*pat != '\0') {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
int32_t resultSize =
udat_getSymbols(fmt, symbolType, index, Char16ToUChar(chars.begin()),
INITIAL_CHAR_BUFFER_SIZE, &status);
if (status == U_BUFFER_OVERFLOW_ERROR) {
if (!chars.resize(resultSize))
return false;
status = U_ZERO_ERROR;
udat_getSymbols(fmt, symbolType, index, Char16ToUChar(chars.begin()),
resultSize, &status);
}
if (U_FAILURE(status)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
return false;
}
JSString* word = NewStringCopyN<CanGC>(cx, chars.begin(), resultSize);
if (!word)
return false;
wordVal.setString(word);
} else {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
return false;
}
MOZ_ASSERT(wordVal.isString());
// 5.b. Append the result string to result.
if (!DefineElement(cx, result, i, wordVal))
return false;
}
// 6. Return result.
args.rval().setObject(*result);
return true;
}
/******************** Intl ********************/
const Class js::IntlClass = {
+54
View File
@@ -387,6 +387,48 @@ intl_FormatDateTime(JSContext* cx, unsigned argc, Value* vp);
extern MOZ_MUST_USE bool
intl_GetCalendarInfo(JSContext* cx, unsigned argc, Value* vp);
/**
* Returns an Array with CLDR-based fields display names.
* The function takes three arguments:
*
* locale
* BCP47 compliant locale string
* style
* A string with values: long or short or narrow
* keys
* An array or path-like strings that identify keys to be returned
* At the moment the following types of keys are supported:
*
* 'dates/fields/{year|month|week|day}'
* 'dates/gregorian/months/{january|...|december}'
* 'dates/gregorian/weekdays/{sunday|...|saturday}'
* 'dates/gregorian/dayperiods/{am|pm}'
*
* Example:
*
* let info = intl_ComputeDisplayNames(
* 'en-US',
* 'long',
* [
* 'dates/fields/year',
* 'dates/gregorian/months/january',
* 'dates/gregorian/weekdays/monday',
* 'dates/gregorian/dayperiods/am',
* ]
* );
*
* Returned value:
*
* [
* 'year',
* 'January',
* 'Monday',
* 'AM'
* ]
*/
extern MOZ_MUST_USE bool
intl_ComputeDisplayNames(JSContext* cx, unsigned argc, Value* vp);
#if ENABLE_INTL_API
/**
* Cast char16_t* strings to UChar* strings used by ICU.
@@ -402,6 +444,18 @@ Char16ToUChar(char16_t* chars)
{
return reinterpret_cast<UChar*>(chars);
}
inline char16_t*
UCharToChar16(UChar* chars)
{
return reinterpret_cast<char16_t*>(chars);
}
inline const char16_t*
UCharToChar16(const UChar* chars)
{
return reinterpret_cast<const char16_t*>(chars);
}
#endif // ENABLE_INTL_API
} // namespace js
+2
View File
@@ -474,6 +474,8 @@ MSG_DEF(JSMSG_INTL_OBJECT_NOT_INITED, 3, JSEXN_TYPEERR, "Intl.{0}.prototype.{1}
MSG_DEF(JSMSG_INTL_OBJECT_REINITED, 0, JSEXN_TYPEERR, "can't initialize object twice as an object of an Intl constructor")
MSG_DEF(JSMSG_INVALID_CURRENCY_CODE, 1, JSEXN_RANGEERR, "invalid currency code in NumberFormat(): {0}")
MSG_DEF(JSMSG_INVALID_DIGITS_VALUE, 1, JSEXN_RANGEERR, "invalid digits value: {0}")
MSG_DEF(JSMSG_INVALID_KEYS_TYPE, 0, JSEXN_TYPEERR, "calendar info keys must be an object or undefined")
MSG_DEF(JSMSG_INVALID_KEY, 1, JSEXN_RANGEERR, "invalid key: {0}")
MSG_DEF(JSMSG_INVALID_LANGUAGE_TAG, 1, JSEXN_RANGEERR, "invalid language tag: {0}")
MSG_DEF(JSMSG_INVALID_LOCALES_ELEMENT, 0, JSEXN_TYPEERR, "invalid element in locales argument")
MSG_DEF(JSMSG_INVALID_LOCALE_MATCHER, 1, JSEXN_RANGEERR, "invalid locale matcher in supportedLocalesOf(): {0}")
+1
View File
@@ -906,6 +906,7 @@ AddIntlExtras(JSContext* cx, unsigned argc, Value* vp)
static const JSFunctionSpec funcs[] = {
JS_SELF_HOSTED_FN("getCalendarInfo", "Intl_getCalendarInfo", 1, 0),
JS_SELF_HOSTED_FN("getDisplayNames", "Intl_getDisplayNames", 2, 0),
JS_FS_END
};
+238
View File
@@ -0,0 +1,238 @@
// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras'))
/* 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/. */
// Tests the getCalendarInfo function with a diverse set of arguments.
/*
* Test if getDisplayNames return value matches expected values.
*/
function checkDisplayNames(names, expected)
{
assertEq(Object.getPrototypeOf(names), Object.prototype);
assertEq(names.locale, expected.locale);
assertEq(names.style, expected.style);
const nameValues = names.values;
const expectedValues = expected.values;
const nameValuesKeys = Object.getOwnPropertyNames(nameValues).sort();
const expectedValuesKeys = Object.getOwnPropertyNames(expectedValues).sort();
assertEqArray(nameValuesKeys, expectedValuesKeys);
for (let key of expectedValuesKeys)
assertEq(nameValues[key], expectedValues[key]);
}
addIntlExtras(Intl);
let gDN = Intl.getDisplayNames;
assertEq(gDN.length, 2);
checkDisplayNames(gDN('en-US', {
}), {
locale: 'en-US',
style: 'long',
values: {}
});
checkDisplayNames(gDN('en-US', {
keys: [
'dates/gregorian/weekdays/wednesday'
],
style: 'narrow'
}), {
locale: 'en-US',
style: 'narrow',
values: {
'dates/gregorian/weekdays/wednesday': 'W'
}
});
checkDisplayNames(gDN('en-US', {
keys: [
'dates/fields/year',
'dates/fields/month',
'dates/fields/week',
'dates/fields/day',
'dates/gregorian/months/january',
'dates/gregorian/months/february',
'dates/gregorian/months/march',
'dates/gregorian/weekdays/tuesday'
]
}), {
locale: 'en-US',
style: 'long',
values: {
'dates/fields/year': 'year',
'dates/fields/month': 'month',
'dates/fields/week': 'week',
'dates/fields/day': 'day',
'dates/gregorian/months/january': 'January',
'dates/gregorian/months/february': 'February',
'dates/gregorian/months/march': 'March',
'dates/gregorian/weekdays/tuesday': 'Tuesday',
}
});
checkDisplayNames(gDN('fr', {
keys: [
'dates/fields/year',
'dates/fields/day',
'dates/gregorian/months/october',
'dates/gregorian/weekdays/saturday',
'dates/gregorian/dayperiods/pm'
]
}), {
locale: 'fr',
style: 'long',
values: {
'dates/fields/year': 'année',
'dates/fields/day': 'jour',
'dates/gregorian/months/october': 'octobre',
'dates/gregorian/weekdays/saturday': 'samedi',
'dates/gregorian/dayperiods/pm': 'PM'
}
});
checkDisplayNames(gDN('it', {
style: 'short',
keys: [
'dates/gregorian/weekdays/thursday',
'dates/gregorian/months/august',
'dates/gregorian/dayperiods/am',
'dates/fields/month',
]
}), {
locale: 'it',
style: 'short',
values: {
'dates/gregorian/weekdays/thursday': 'gio',
'dates/gregorian/months/august': 'ago',
'dates/gregorian/dayperiods/am': 'AM',
'dates/fields/month': 'mese'
}
});
checkDisplayNames(gDN('ar', {
style: 'long',
keys: [
'dates/gregorian/weekdays/thursday',
'dates/gregorian/months/august',
'dates/gregorian/dayperiods/am',
'dates/fields/month',
]
}), {
locale: 'ar',
style: 'long',
values: {
'dates/gregorian/weekdays/thursday': 'الخميس',
'dates/gregorian/months/august': 'أغسطس',
'dates/gregorian/dayperiods/am': 'ص',
'dates/fields/month': 'الشهر'
}
});
/* Invalid input */
assertThrowsInstanceOf(() => {
gDN('en-US', {
style: '',
keys: [
'dates/gregorian/weekdays/thursday',
]
});
}, RangeError);
assertThrowsInstanceOf(() => {
gDN('en-US', {
style: 'bogus',
keys: [
'dates/gregorian/weekdays/thursday',
]
});
}, RangeError);
assertThrowsInstanceOf(() => {
gDN('foo-X', {
keys: [
'dates/gregorian/weekdays/thursday',
]
});
}, RangeError);
const typeErrorKeys = [
null,
'string',
Symbol.iterator,
15,
1,
3.7,
NaN,
Infinity
];
for (let keys of typeErrorKeys) {
assertThrowsInstanceOf(() => {
gDN('en-US', {
keys
});
}, TypeError);
}
const rangeErrorKeys = [
[''],
['foo'],
['dates/foo'],
['/dates/foo'],
['dates/foo/foo'],
['dates/fields'],
['dates/fields/'],
['dates/fields/foo'],
['dates/fields/foo/month'],
['/dates/foo/faa/bar/baz'],
['dates///bar/baz'],
['dates/gregorian'],
['dates/gregorian/'],
['dates/gregorian/foo'],
['dates/gregorian/months'],
['dates/gregorian/months/foo'],
['dates/gregorian/weekdays'],
['dates/gregorian/weekdays/foo'],
['dates/gregorian/dayperiods'],
['dates/gregorian/dayperiods/foo'],
['dates/gregorian/months/الشهر'],
[3],
[null],
['d', 'a', 't', 'e', 's'],
['datesEXTRA'],
['dates/fieldsEXTRA'],
['dates/gregorianEXTRA'],
['dates/gregorian/monthsEXTRA'],
['dates/gregorian/weekdaysEXTRA'],
['dates/fields/dayperiods/amEXTRA'],
['dates/gregori\u1161n/months/january'],
["dates/fields/year/"],
["dates/fields/month/"],
["dates/fields/week/"],
["dates/fields/day/"],
["dates/gregorian/months/january/"],
["dates/gregorian/weekdays/saturday/"],
["dates/gregorian/dayperiods/am/"],
["dates/fields/months/january/"],
];
for (let keys of rangeErrorKeys) {
assertThrowsInstanceOf(() => {
gDN('en-US', {
keys
});
}, RangeError);
}
if (typeof reportCompare === 'function')
reportCompare(0, 0);
+1
View File
@@ -2477,6 +2477,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("intl_FormatDateTime", intl_FormatDateTime, 2,0),
JS_FN("intl_FormatNumber", intl_FormatNumber, 2,0),
JS_FN("intl_GetCalendarInfo", intl_GetCalendarInfo, 1,0),
JS_FN("intl_ComputeDisplayNames", intl_ComputeDisplayNames, 3,0),
JS_FN("intl_IsValidTimeZoneName", intl_IsValidTimeZoneName, 1,0),
JS_FN("intl_NumberFormat", intl_NumberFormat, 2,0),
JS_FN("intl_NumberFormat_availableLocales", intl_NumberFormat_availableLocales, 0,0),