[intl] Implement Intl Enumeration API

flag --harmony_intl_enumeration

I2P: https://groups.google.com/a/chromium.org/g/blink-dev/c/Txtf_rSqGH8/m/e27FY33JAQAJ
Design Doc: https://docs.google.com/document/d/1lbj_YVW-xhzYNMQeHB-qDjVkf4SA-eTHYpYXx3Oaud8
https://chromestatus.com/guide/edit/5649454590853120


Bug: v8:10743
Change-Id: I3bfe0c25b50eb55025498534eba975a20723bd2f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2953519
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76265}
This commit is contained in:
Frank Tang 2021-08-12 09:46:19 -07:00 committed by V8 LUCI CQ
parent 4955ecfc68
commit 266bd5743f
24 changed files with 444 additions and 78 deletions

View File

@ -1053,6 +1053,8 @@ namespace internal {
CPP(DisplayNamesSupportedLocalesOf) \
/* ecma402 #sec-intl.getcanonicallocales */ \
CPP(IntlGetCanonicalLocales) \
/* ecma402 #sec-intl.supportedvaluesof */ \
CPP(IntlSupportedValuesOf) \
/* ecma402 #sec-intl-listformat-constructor */ \
CPP(ListFormatConstructor) \
/* ecma402 #sec-intl-list-format.prototype.format */ \

View File

@ -576,6 +576,13 @@ BUILTIN(IntlGetCanonicalLocales) {
Intl::GetCanonicalLocales(isolate, locales));
}
BUILTIN(IntlSupportedValuesOf) {
HandleScope scope(isolate);
Handle<Object> locales = args.atOrUndefined(isolate, 1);
RETURN_RESULT_OR_FAILURE(isolate, Intl::SupportedValuesOf(isolate, locales));
}
BUILTIN(ListFormatConstructor) {
HandleScope scope(isolate);

View File

@ -293,7 +293,9 @@ DEFINE_BOOL(harmony_shipping, true, "enable all shipped harmony features")
V(harmony_array_find_last, "harmony array find last helpers")
#ifdef V8_INTL_SUPPORT
#define HARMONY_INPROGRESS(V) HARMONY_INPROGRESS_BASE(V)
#define HARMONY_INPROGRESS(V) \
HARMONY_INPROGRESS_BASE(V) \
V(harmony_intl_enumeration, "Intl Enumberation API")
#else
#define HARMONY_INPROGRESS(V) HARMONY_INPROGRESS_BASE(V)
#endif

View File

@ -4594,6 +4594,20 @@ void Genesis::InitializeGlobal_harmony_intl_locale_info() {
Builtin::kLocalePrototypeWeekInfo, true);
}
void Genesis::InitializeGlobal_harmony_intl_enumeration() {
if (!FLAG_harmony_intl_enumeration) return;
Handle<JSObject> intl = Handle<JSObject>::cast(
JSReceiver::GetProperty(
isolate(),
Handle<JSReceiver>(native_context()->global_object(), isolate()),
factory()->InternalizeUtf8String("Intl"))
.ToHandleChecked());
SimpleInstallFunction(isolate(), intl, "supportedValuesOf",
Builtin::kIntlSupportedValuesOf, 0, false);
}
#endif // V8_INTL_SUPPORT
Handle<JSFunction> Genesis::CreateArrayBuffer(

View File

@ -1666,6 +1666,145 @@ MaybeHandle<JSArray> Intl::GetCanonicalLocales(Isolate* isolate,
return CreateArrayFromList(isolate, maybe_ll.FromJust(), attr);
}
namespace {
MaybeHandle<JSArray> AvailableCollations(Isolate* isolate) {
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::StringEnumeration> enumeration(
icu::Collator::getKeywordValues("collation", status));
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
return Intl::ToJSArray(isolate, "co", enumeration.get(),
Intl::RemoveCollation, true);
}
MaybeHandle<JSArray> VectorToJSArray(Isolate* isolate,
const std::vector<std::string>& array) {
Factory* factory = isolate->factory();
Handle<FixedArray> fixed_array =
factory->NewFixedArray(static_cast<int32_t>(array.size()));
int32_t index = 0;
for (std::string item : array) {
Handle<String> str = factory->NewStringFromAsciiChecked(item.c_str());
fixed_array->set(index++, *str);
}
return factory->NewJSArrayWithElements(fixed_array);
}
MaybeHandle<JSArray> AvailableCurrencies(Isolate* isolate) {
UErrorCode status = U_ZERO_ERROR;
UEnumeration* ids =
ucurr_openISOCurrencies(UCURR_COMMON | UCURR_NON_DEPRECATED, &status);
const char* next = nullptr;
std::vector<std::string> array;
while (U_SUCCESS(status) &&
(next = uenum_next(ids, nullptr, &status)) != nullptr) {
array.push_back(next);
}
std::sort(array.begin(), array.end());
uenum_close(ids);
return VectorToJSArray(isolate, array);
}
MaybeHandle<JSArray> AvailableNumberingSystems(Isolate* isolate) {
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::StringEnumeration> enumeration(
icu::NumberingSystem::getAvailableNames(status));
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
// Need to filter out isAlgorithmic
return Intl::ToJSArray(
isolate, "nu", enumeration.get(),
[](const char* value) {
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::NumberingSystem> numbering_system(
icu::NumberingSystem::createInstanceByName(value, status));
// Skip algorithmic one since chrome filter out the resource.
return U_FAILURE(status) || numbering_system->isAlgorithmic();
},
true);
}
MaybeHandle<JSArray> AvailableTimeZones(Isolate* isolate) {
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::StringEnumeration> enumeration(
icu::TimeZone::createTimeZoneIDEnumeration(
UCAL_ZONE_TYPE_CANONICAL_LOCATION, nullptr, nullptr, status));
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
return Intl::ToJSArray(isolate, nullptr, enumeration.get(), nullptr, true);
}
MaybeHandle<JSArray> AvailableUnits(Isolate* isolate) {
Factory* factory = isolate->factory();
std::set<std::string> sanctioned(Intl::SanctionedSimpleUnits());
Handle<FixedArray> fixed_array =
factory->NewFixedArray(static_cast<int32_t>(sanctioned.size()));
int32_t index = 0;
for (std::string item : sanctioned) {
Handle<String> str = factory->NewStringFromAsciiChecked(item.c_str());
fixed_array->set(index++, *str);
}
return factory->NewJSArrayWithElements(fixed_array);
}
} // namespace
// ecma-402 #sec-intl.supportedvaluesof
MaybeHandle<JSArray> Intl::SupportedValuesOf(Isolate* isolate,
Handle<Object> key_obj) {
Factory* factory = isolate->factory();
// 1. 1. Let key be ? ToString(key).
Handle<String> key_str;
ASSIGN_RETURN_ON_EXCEPTION(isolate, key_str,
Object::ToString(isolate, key_obj), JSArray);
// 2. If key is "calendar", then
if (factory->calendar_string()->Equals(*key_str)) {
// a. Let list be ! AvailableCalendars( ).
return Intl::AvailableCalendars(isolate);
}
// 3. Else if key is "collation", then
if (factory->collation_string()->Equals(*key_str)) {
// a. Let list be ! AvailableCollations( ).
return AvailableCollations(isolate);
}
// 4. Else if key is "currency", then
if (factory->currency_string()->Equals(*key_str)) {
// a. Let list be ! AvailableCurrencies( ).
return AvailableCurrencies(isolate);
}
// 5. Else if key is "numberingSystem", then
if (factory->numberingSystem_string()->Equals(*key_str)) {
// a. Let list be ! AvailableNumberingSystems( ).
return AvailableNumberingSystems(isolate);
}
// 6. Else if key is "timeZone", then
if (factory->timeZone_string()->Equals(*key_str)) {
// a. Let list be ! AvailableTimeZones( ).
return AvailableTimeZones(isolate);
}
// 7. Else if key is "unit", then
if (factory->unit_string()->Equals(*key_str)) {
// a. Let list be ! AvailableUnits( ).
return AvailableUnits(isolate);
}
// 8. Else,
// a. Throw a RangeError exception.
// 9. Return ! CreateArrayFromList( list ).
THROW_NEW_ERROR(
isolate,
NewRangeError(MessageTemplate::kInvalid,
factory->NewStringFromStaticChars("key"), key_str),
JSArray);
}
// ECMA 402 Intl.*.supportedLocalesOf
MaybeHandle<JSObject> Intl::SupportedLocalesOf(
Isolate* isolate, const char* method,
@ -2247,5 +2386,51 @@ MaybeHandle<JSReceiver> Intl::CoerceOptionsToObject(Isolate* isolate,
return Handle<JSReceiver>::cast(options);
}
MaybeHandle<JSArray> Intl::ToJSArray(
Isolate* isolate, const char* unicode_key,
icu::StringEnumeration* enumeration,
const std::function<bool(const char*)>& removes, bool sort) {
UErrorCode status = U_ZERO_ERROR;
std::vector<std::string> array;
for (const char* item = enumeration->next(nullptr, status);
U_SUCCESS(status) && item != nullptr;
item = enumeration->next(nullptr, status)) {
if (unicode_key != nullptr) {
item = uloc_toUnicodeLocaleType(unicode_key, item);
}
if (removes == nullptr || !(removes)(item)) {
array.push_back(item);
}
}
if (sort) {
std::sort(array.begin(), array.end());
}
return VectorToJSArray(isolate, array);
}
bool Intl::RemoveCollation(const char* collation) {
return strcmp("standard", collation) == 0 || strcmp("search", collation) == 0;
}
// See the list in ecma402 #sec-issanctionedsimpleunitidentifier
std::set<std::string> Intl::SanctionedSimpleUnits() {
return std::set<std::string>({"acre", "bit", "byte",
"celsius", "centimeter", "day",
"degree", "fahrenheit", "fluid-ounce",
"foot", "gallon", "gigabit",
"gigabyte", "gram", "hectare",
"hour", "inch", "kilobit",
"kilobyte", "kilogram", "kilometer",
"liter", "megabit", "megabyte",
"meter", "mile", "mile-scandinavian",
"millimeter", "milliliter", "millisecond",
"minute", "month", "ounce",
"percent", "petabyte", "pound",
"second", "stone", "terabit",
"terabyte", "week", "yard",
"year"});
}
} // namespace internal
} // namespace v8

View File

@ -27,6 +27,7 @@ namespace U_ICU_NAMESPACE {
class BreakIterator;
class Collator;
class FormattedValue;
class StringEnumeration;
class UnicodeString;
} // namespace U_ICU_NAMESPACE
@ -142,6 +143,10 @@ class Intl {
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> GetCanonicalLocales(
Isolate* isolate, Handle<Object> locales);
// ecma-402 #sec-intl.supportedvaluesof
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> SupportedValuesOf(
Isolate* isolate, Handle<Object> key);
// For locale sensitive functions
V8_WARN_UNUSED_RESULT static MaybeHandle<String> StringLocaleConvertCase(
Isolate* isolate, Handle<String> s, bool is_upper,
@ -338,6 +343,18 @@ class Intl {
// ecma402/#sec-coerceoptionstoobject
V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> CoerceOptionsToObject(
Isolate* isolate, Handle<Object> options, const char* service);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> ToJSArray(
Isolate* isolate, const char* unicode_key,
icu::StringEnumeration* enumeration,
const std::function<bool(const char*)>& removes, bool sort);
static bool RemoveCollation(const char* collation);
static std::set<std::string> SanctionedSimpleUnits();
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> AvailableCalendars(
Isolate* isolate);
};
} // namespace internal

View File

@ -481,57 +481,13 @@ MaybeHandle<JSLocale> JSLocale::Minimize(Isolate* isolate,
return Construct(isolate, result);
}
MaybeHandle<JSArray> ToJSArray(Isolate* isolate, const char* unicode_key,
icu::StringEnumeration* enumeration,
const std::set<std::string>& removes) {
UErrorCode status = U_ZERO_ERROR;
Factory* factory = isolate->factory();
int32_t count = 0;
if (!removes.empty()) {
// If we may remove items, then we need to go one pass first to count how
// many items we will insert before we allocate the fixed array.
for (const char* item = enumeration->next(nullptr, status);
U_SUCCESS(status) && item != nullptr;
item = enumeration->next(nullptr, status)) {
if (unicode_key != nullptr) {
item = uloc_toUnicodeLocaleType(unicode_key, item);
}
if (removes.find(item) == removes.end()) {
count++;
}
}
enumeration->reset(status);
} else {
count = enumeration->count(status);
}
Handle<FixedArray> fixed_array = factory->NewFixedArray(count);
int32_t index = 0;
for (const char* item = enumeration->next(nullptr, status);
U_SUCCESS(status) && item != nullptr;
item = enumeration->next(nullptr, status)) {
if (unicode_key != nullptr) {
item = uloc_toUnicodeLocaleType(unicode_key, item);
}
if (removes.find(item) != removes.end()) {
continue;
}
Handle<String> str = factory->NewStringFromAsciiChecked(item);
fixed_array->set(index++, *str);
}
CHECK(index == count);
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
return factory->NewJSArrayWithElements(fixed_array);
}
template <typename T>
MaybeHandle<JSArray> GetKeywordValuesFromLocale(
Isolate* isolate, const char* key, const char* unicode_key,
const icu::Locale& locale, const std::set<std::string>& removes) {
MaybeHandle<JSArray> GetKeywordValuesFromLocale(Isolate* isolate,
const char* key,
const char* unicode_key,
const icu::Locale& locale,
bool (*removes)(const char*),
bool commonly_used, bool sort) {
Factory* factory = isolate->factory();
UErrorCode status = U_ZERO_ERROR;
std::string ext =
@ -544,27 +500,43 @@ MaybeHandle<JSArray> GetKeywordValuesFromLocale(
}
status = U_ZERO_ERROR;
std::unique_ptr<icu::StringEnumeration> enumeration(
T::getKeywordValuesForLocale(key, locale, true, status));
T::getKeywordValuesForLocale(key, locale, commonly_used, status));
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
return ToJSArray(isolate, unicode_key, enumeration.get(), removes);
return Intl::ToJSArray(isolate, unicode_key, enumeration.get(), removes,
sort);
}
namespace {
MaybeHandle<JSArray> CalendarsForLocale(Isolate* isolate,
const icu::Locale& icu_locale,
bool commonly_used, bool sort) {
return GetKeywordValuesFromLocale<icu::Calendar>(
isolate, "calendar", "ca", icu_locale, nullptr, commonly_used, sort);
}
} // namespace
MaybeHandle<JSArray> JSLocale::Calendars(Isolate* isolate,
Handle<JSLocale> locale) {
icu::Locale icu_locale(*(locale->icu_locale().raw()));
return GetKeywordValuesFromLocale<icu::Calendar>(
isolate, "calendar", "ca", icu_locale, std::set<std::string>());
return CalendarsForLocale(isolate, icu_locale, true, false);
}
MaybeHandle<JSArray> Intl::AvailableCalendars(Isolate* isolate) {
icu::Locale icu_locale("und");
return CalendarsForLocale(isolate, icu_locale, false, true);
}
MaybeHandle<JSArray> JSLocale::Collations(Isolate* isolate,
Handle<JSLocale> locale) {
icu::Locale icu_locale(*(locale->icu_locale().raw()));
const std::set<std::string> removes({"standard", "search"});
return GetKeywordValuesFromLocale<icu::Collator>(isolate, "collations", "co",
icu_locale, removes);
return GetKeywordValuesFromLocale<icu::Collator>(
isolate, "collations", "co", icu_locale, Intl::RemoveCollation, true,
false);
}
MaybeHandle<JSArray> JSLocale::HourCycles(Isolate* isolate,
@ -693,8 +665,7 @@ MaybeHandle<Object> JSLocale::TimeZones(Isolate* isolate,
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
return ToJSArray(isolate, nullptr, enumeration.get(),
std::set<std::string>());
return Intl::ToJSArray(isolate, nullptr, enumeration.get(), nullptr, true);
}
MaybeHandle<JSObject> JSLocale::TextInfo(Isolate* isolate,

View File

@ -173,27 +173,11 @@ std::map<const std::string, icu::MeasureUnit> CreateUnitMap() {
int32_t total = icu::MeasureUnit::getAvailable(nullptr, 0, status);
CHECK(U_FAILURE(status));
status = U_ZERO_ERROR;
// See the list in ecma402 #sec-issanctionedsimpleunitidentifier
std::set<std::string> sanctioned(
{"acre", "bit", "byte",
"celsius", "centimeter", "day",
"degree", "fahrenheit", "fluid-ounce",
"foot", "gallon", "gigabit",
"gigabyte", "gram", "hectare",
"hour", "inch", "kilobit",
"kilobyte", "kilogram", "kilometer",
"liter", "megabit", "megabyte",
"meter", "mile", "mile-scandinavian",
"millimeter", "milliliter", "millisecond",
"minute", "month", "ounce",
"percent", "petabyte", "pound",
"second", "stone", "terabit",
"terabyte", "week", "yard",
"year"});
std::vector<icu::MeasureUnit> units(total);
total = icu::MeasureUnit::getAvailable(units.data(), total, status);
CHECK(U_SUCCESS(status));
std::map<const std::string, icu::MeasureUnit> map;
std::set<std::string> sanctioned(Intl::SanctionedSimpleUnits());
for (auto it = units.begin(); it != units.end(); ++it) {
// Need to skip none/percent
if (sanctioned.count(it->getSubtype()) > 0 &&

View File

@ -0,0 +1,11 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test the return items of calendar is sorted
let name = "calendar";
let items = Intl.supportedValuesOf(name);
assertEquals([...items].sort(), items,
"return value of Intl.supportedValuesOf('" + name + "') should be sorted");

View File

@ -0,0 +1,14 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test the return items of calendar fit 'type'
let regex = /^[a-zA-Z0-9]{3,8}(-[a-zA-Z0-9]{3,8})*$/;
Intl.supportedValuesOf("calendar").forEach(
function(calendar) {
assertTrue(regex.test(calendar),
"Intl.supportedValuesOf('calendar') return " + calendar +
" which does not meet 'type: alphanum{3,8}(sep alphanum{3,8})*'");
});

View File

@ -0,0 +1,11 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test the return items of collation is sorted
let name = "collation";
let items = Intl.supportedValuesOf(name);
assertEquals([...items].sort(), items,
"return value of Intl.supportedValuesOf('" + name + "') should be sorted");

View File

@ -0,0 +1,14 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test the return items of collation fit 'type'
let regex = /^[a-zA-Z0-9]{3,8}(-[a-zA-Z0-9]{3,8})*$/;
Intl.supportedValuesOf("collation").forEach(
function(collation) {
assertTrue(regex.test(collation),
"Intl.supportedValuesOf('collation') return " + collation +
" which does not meet 'type: alphanum{3,8}(sep alphanum{3,8})*'");
});

View File

@ -0,0 +1,11 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test the return items of currency is sorted
let name = "currency";
let items = Intl.supportedValuesOf(name);
assertEquals([...items].sort(), items,
"return value of Intl.supportedValuesOf('" + name + "') should be sorted");

View File

@ -0,0 +1,14 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test the return items of currency fit 'type'
let regex = /^[A-Z]{3}$/;
Intl.supportedValuesOf("currency").forEach(
function(currency) {
assertTrue(regex.test(currency),
"Intl.supportedValuesOf('currency') return " + currency +
" which does not meet 'alpha{3}'");
});

View File

@ -0,0 +1,20 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Chrome filter out data of algorithm numberingSystems so we need to test none
// of them got returned.
let name = "numberingSystem";
let items = Intl.supportedValuesOf(name);
function verifyNoAlgorithm(nu) {
assertTrue(items.indexOf(nu) < 0, "should not return '" + nu + "' which is algorithmic");
}
["armn", "armnlow", "cyrl", "ethi", "finance", "geor", "grek", "greklow",
"hans", "hansfin", "hant", "hantfin", "hebr", "japn", "japnfin",
"roman", "romanlow", "taml", "traditio"].forEach(function(nu) {
verifyNoAlgorithm(nu);
});

View File

@ -0,0 +1,11 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test the return items of numberingSystem is sorted
let name = "numberingSystem";
let items = Intl.supportedValuesOf(name);
assertEquals([...items].sort(), items,
"return value of Intl.supportedValuesOf('" + name + "') should be sorted");

View File

@ -0,0 +1,14 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test the return items of numberingSystem fit 'type'
let regex = /^[a-zA-Z0-9]{3,8}(-[a-zA-Z0-9]{3,8})*$/;
Intl.supportedValuesOf("numberingSystem").forEach(
function(numberingSystem) {
assertTrue(regex.test(numberingSystem),
"Intl.supportedValuesOf('numberingSystem') return " + numberingSystem +
" which does not meet 'type: alphanum{3,8}(sep alphanum{3,8})*'");
});

View File

@ -0,0 +1,12 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test invalid keys
["calendars", "collations", "currencies", "numberingSystems", "timeZones", "units",
1, 0.3, true, false, {}, [] ].forEach(
function(key) {
assertThrows(() => Intl.supportedValuesOf(key), RangeError);
});

View File

@ -0,0 +1,7 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
assertEquals("supportedValuesOf", Intl.supportedValuesOf.name);

View File

@ -0,0 +1,11 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
let descriptor = Object.getOwnPropertyDescriptor(
Intl, "supportedValuesOf");
assertTrue(descriptor.writable);
assertFalse(descriptor.enumerable);
assertTrue(descriptor.configurable);

View File

@ -0,0 +1,12 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test valid keys
["calendar", "collation", "currency", "numberingSystem", "timeZone", "unit"].forEach(
function(key) {
assertDoesNotThrow(() => Intl.supportedValuesOf(key));
assertEquals("object", typeof Intl.supportedValuesOf(key));
});

View File

@ -0,0 +1,11 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test the return items of timeZone is sorted
let name = "timeZone";
let items = Intl.supportedValuesOf(name);
assertEquals([...items].sort(), items,
"return value of Intl.supportedValuesOf('" + name + "') should be sorted");

View File

@ -0,0 +1,11 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_enumeration
// Test the return items of unit is sorted
let name = "unit";
let items = Intl.supportedValuesOf(name);
assertEquals([...items].sort(), items,
"return value of Intl.supportedValuesOf('" + name + "') should be sorted");

View File

@ -14,7 +14,7 @@ for (var i = 0; i < a_to_z.length; i++) {
locale.calendars.forEach(function(tokens) {
assertTrue(regex.test(tokens),
locale + ".calendars [" + locale.calendars +
"] does not meet 'type: alphanum{3,8}(sep alphanum{3,8})*'");
"] but '" + tokens + "' does not meet 'type: alphanum{3,8}(sep alphanum{3,8})*'");
});
}
}