[Intl] Clean up SupportedLocalesOf and GetAvailableLocales
As per https://unicode-org.atlassian.net/browse/ICU-20009?focusedCommentId=62380&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-62380 we can just use DateFormat::GetAvailableLocales for RelativeTimeFormat removing a lot of code. This patch also cleans up the code to be in line with the rest of V8. Bug: v8:5751 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: I8df5b0e5a9a05c426aaa4f7fb9c67d7947301478 Reviewed-on: https://chromium-review.googlesource.com/c/1237298 Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org> Reviewed-by: Adam Klein <adamk@chromium.org> Cr-Commit-Position: refs/heads/master@{#56455}
This commit is contained in:
parent
01ce70a210
commit
55d37600e5
@ -130,44 +130,24 @@ BUILTIN(StringPrototypeNormalizeIntl) {
|
|||||||
result.length())));
|
result.length())));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
BUILTIN(V8BreakIteratorSupportedLocalesOf) {
|
||||||
|
HandleScope scope(isolate);
|
||||||
MaybeHandle<JSObject> SupportedLocalesOfCommon(Isolate* isolate,
|
|
||||||
const char* service_in,
|
|
||||||
BuiltinArguments args) {
|
|
||||||
Factory* factory = isolate->factory();
|
|
||||||
Handle<String> service = factory->NewStringFromAsciiChecked(service_in);
|
|
||||||
Handle<Object> locales = args.atOrUndefined(isolate, 1);
|
Handle<Object> locales = args.atOrUndefined(isolate, 1);
|
||||||
Handle<Object> options = args.atOrUndefined(isolate, 2);
|
Handle<Object> options = args.atOrUndefined(isolate, 2);
|
||||||
|
|
||||||
MaybeHandle<JSObject> result =
|
|
||||||
Intl::SupportedLocalesOf(isolate, service, locales, options);
|
|
||||||
Handle<JSObject> elements;
|
|
||||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, elements, result, JSObject);
|
|
||||||
return elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
BUILTIN(V8BreakIteratorSupportedLocalesOf) {
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
// 1. If NewTarget is defined, throw a TypeError exception.
|
|
||||||
if (!args.new_target()->IsUndefined(isolate)) { // [[Call]]
|
|
||||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
|
||||||
isolate,
|
|
||||||
NewTypeError(MessageTemplate::kOrdinaryFunctionCalledAsConstructor,
|
|
||||||
isolate->factory()->NewStringFromStaticChars(
|
|
||||||
"Intl.v8BreakIterator")));
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_RESULT_OR_FAILURE(
|
RETURN_RESULT_OR_FAILURE(
|
||||||
isolate, SupportedLocalesOfCommon(isolate, "breakiterator", args));
|
isolate, Intl::SupportedLocalesOf(isolate, ICUService::kBreakIterator,
|
||||||
|
locales, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILTIN(NumberFormatSupportedLocalesOf) {
|
BUILTIN(NumberFormatSupportedLocalesOf) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
|
Handle<Object> locales = args.atOrUndefined(isolate, 1);
|
||||||
|
Handle<Object> options = args.atOrUndefined(isolate, 2);
|
||||||
|
|
||||||
RETURN_RESULT_OR_FAILURE(
|
RETURN_RESULT_OR_FAILURE(
|
||||||
isolate, SupportedLocalesOfCommon(isolate, "numberformat", args));
|
isolate, Intl::SupportedLocalesOf(isolate, ICUService::kNumberFormat,
|
||||||
|
locales, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILTIN(NumberFormatPrototypeFormatToParts) {
|
BUILTIN(NumberFormatPrototypeFormatToParts) {
|
||||||
@ -204,8 +184,12 @@ BUILTIN(DateTimeFormatPrototypeResolvedOptions) {
|
|||||||
|
|
||||||
BUILTIN(DateTimeFormatSupportedLocalesOf) {
|
BUILTIN(DateTimeFormatSupportedLocalesOf) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
|
Handle<Object> locales = args.atOrUndefined(isolate, 1);
|
||||||
|
Handle<Object> options = args.atOrUndefined(isolate, 2);
|
||||||
|
|
||||||
RETURN_RESULT_OR_FAILURE(
|
RETURN_RESULT_OR_FAILURE(
|
||||||
isolate, SupportedLocalesOfCommon(isolate, "dateformat", args));
|
isolate, Intl::SupportedLocalesOf(isolate, ICUService::kDateFormat,
|
||||||
|
locales, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILTIN(DateTimeFormatPrototypeFormatToParts) {
|
BUILTIN(DateTimeFormatPrototypeFormatToParts) {
|
||||||
@ -543,8 +527,12 @@ BUILTIN(ListFormatPrototypeResolvedOptions) {
|
|||||||
|
|
||||||
BUILTIN(ListFormatSupportedLocalesOf) {
|
BUILTIN(ListFormatSupportedLocalesOf) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
|
Handle<Object> locales = args.atOrUndefined(isolate, 1);
|
||||||
|
Handle<Object> options = args.atOrUndefined(isolate, 2);
|
||||||
|
|
||||||
RETURN_RESULT_OR_FAILURE(
|
RETURN_RESULT_OR_FAILURE(
|
||||||
isolate, SupportedLocalesOfCommon(isolate, "listformat", args));
|
isolate, Intl::SupportedLocalesOf(isolate, ICUService::kListFormatter,
|
||||||
|
locales, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -646,8 +634,13 @@ BUILTIN(LocalePrototypeMinimize) {
|
|||||||
|
|
||||||
BUILTIN(RelativeTimeFormatSupportedLocalesOf) {
|
BUILTIN(RelativeTimeFormatSupportedLocalesOf) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
|
Handle<Object> locales = args.atOrUndefined(isolate, 1);
|
||||||
|
Handle<Object> options = args.atOrUndefined(isolate, 2);
|
||||||
|
|
||||||
RETURN_RESULT_OR_FAILURE(
|
RETURN_RESULT_OR_FAILURE(
|
||||||
isolate, SupportedLocalesOfCommon(isolate, "relativetimeformat", args));
|
isolate,
|
||||||
|
Intl::SupportedLocalesOf(isolate, ICUService::kRelativeDateTimeFormatter,
|
||||||
|
locales, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILTIN(RelativeTimeFormatPrototypeFormat) {
|
BUILTIN(RelativeTimeFormatPrototypeFormat) {
|
||||||
@ -905,8 +898,12 @@ BUILTIN(PluralRulesPrototypeSelect) {
|
|||||||
|
|
||||||
BUILTIN(PluralRulesSupportedLocalesOf) {
|
BUILTIN(PluralRulesSupportedLocalesOf) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
|
Handle<Object> locales = args.atOrUndefined(isolate, 1);
|
||||||
|
Handle<Object> options = args.atOrUndefined(isolate, 2);
|
||||||
|
|
||||||
RETURN_RESULT_OR_FAILURE(
|
RETURN_RESULT_OR_FAILURE(
|
||||||
isolate, SupportedLocalesOfCommon(isolate, "pluralrules", args));
|
isolate, Intl::SupportedLocalesOf(isolate, ICUService::kPluralRules,
|
||||||
|
locales, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILTIN(CollatorConstructor) {
|
BUILTIN(CollatorConstructor) {
|
||||||
@ -951,8 +948,12 @@ BUILTIN(CollatorPrototypeResolvedOptions) {
|
|||||||
|
|
||||||
BUILTIN(CollatorSupportedLocalesOf) {
|
BUILTIN(CollatorSupportedLocalesOf) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
RETURN_RESULT_OR_FAILURE(isolate,
|
Handle<Object> locales = args.atOrUndefined(isolate, 1);
|
||||||
SupportedLocalesOfCommon(isolate, "collator", args));
|
Handle<Object> options = args.atOrUndefined(isolate, 2);
|
||||||
|
|
||||||
|
RETURN_RESULT_OR_FAILURE(
|
||||||
|
isolate, Intl::SupportedLocalesOf(isolate, ICUService::kCollator, locales,
|
||||||
|
options));
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILTIN(CollatorPrototypeCompare) {
|
BUILTIN(CollatorPrototypeCompare) {
|
||||||
@ -1047,8 +1048,12 @@ BUILTIN(SegmenterConstructor) {
|
|||||||
|
|
||||||
BUILTIN(SegmenterSupportedLocalesOf) {
|
BUILTIN(SegmenterSupportedLocalesOf) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
|
Handle<Object> locales = args.atOrUndefined(isolate, 1);
|
||||||
|
Handle<Object> options = args.atOrUndefined(isolate, 2);
|
||||||
|
|
||||||
RETURN_RESULT_OR_FAILURE(
|
RETURN_RESULT_OR_FAILURE(
|
||||||
isolate, SupportedLocalesOfCommon(isolate, "segmenter", args));
|
isolate, Intl::SupportedLocalesOf(isolate, ICUService::kSegmenter,
|
||||||
|
locales, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILTIN(SegmenterPrototypeResolvedOptions) {
|
BUILTIN(SegmenterPrototypeResolvedOptions) {
|
||||||
|
@ -23,13 +23,12 @@ class TimeZone;
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
enum class IcuService {
|
enum class ICUService {
|
||||||
kBreakIterator,
|
kBreakIterator,
|
||||||
kCollator,
|
kCollator,
|
||||||
kDateFormat,
|
kDateFormat,
|
||||||
kNumberFormat,
|
kNumberFormat,
|
||||||
kPluralRules,
|
kPluralRules,
|
||||||
kResourceBundle,
|
|
||||||
kRelativeDateTimeFormatter,
|
kRelativeDateTimeFormatter,
|
||||||
kListFormatter,
|
kListFormatter,
|
||||||
kSegmenter
|
kSegmenter
|
||||||
|
@ -159,9 +159,15 @@ void Intl::AddElement(Isolate* isolate, Handle<JSArray> array, int index,
|
|||||||
JSObject::AddProperty(isolate, element, additional_property_name,
|
JSObject::AddProperty(isolate, element, additional_property_name,
|
||||||
additional_property_value, NONE);
|
additional_property_value, NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
// Build the shortened locale; eg, convert xx_Yyyy_ZZ to xx_ZZ.
|
// Build the shortened locale; eg, convert xx_Yyyy_ZZ to xx_ZZ.
|
||||||
bool Intl::RemoveLocaleScriptTag(const std::string& icu_locale,
|
//
|
||||||
std::string* locale_less_script) {
|
// If locale has a script tag then return true and the locale without the
|
||||||
|
// script else return false and an empty string.
|
||||||
|
bool RemoveLocaleScriptTag(const std::string& icu_locale,
|
||||||
|
std::string* locale_less_script) {
|
||||||
icu::Locale new_locale = icu::Locale::createCanonical(icu_locale.c_str());
|
icu::Locale new_locale = icu::Locale::createCanonical(icu_locale.c_str());
|
||||||
const char* icu_script = new_locale.getScript();
|
const char* icu_script = new_locale.getScript();
|
||||||
if (icu_script == nullptr || strlen(icu_script) == 0) {
|
if (icu_script == nullptr || strlen(icu_script) == 0) {
|
||||||
@ -172,31 +178,33 @@ bool Intl::RemoveLocaleScriptTag(const std::string& icu_locale,
|
|||||||
const char* icu_language = new_locale.getLanguage();
|
const char* icu_language = new_locale.getLanguage();
|
||||||
const char* icu_country = new_locale.getCountry();
|
const char* icu_country = new_locale.getCountry();
|
||||||
icu::Locale short_locale = icu::Locale(icu_language, icu_country);
|
icu::Locale short_locale = icu::Locale(icu_language, icu_country);
|
||||||
const char* icu_name = short_locale.getName();
|
*locale_less_script = short_locale.getName();
|
||||||
*locale_less_script = std::string(icu_name);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<std::string> Intl::GetAvailableLocales(const IcuService& service) {
|
} // namespace
|
||||||
|
|
||||||
|
std::set<std::string> Intl::GetAvailableLocales(const ICUService service) {
|
||||||
const icu::Locale* icu_available_locales = nullptr;
|
const icu::Locale* icu_available_locales = nullptr;
|
||||||
int32_t count = 0;
|
int32_t count = 0;
|
||||||
std::set<std::string> locales;
|
std::set<std::string> locales;
|
||||||
|
|
||||||
switch (service) {
|
switch (service) {
|
||||||
case IcuService::kSegmenter:
|
case ICUService::kBreakIterator:
|
||||||
case IcuService::kBreakIterator:
|
case ICUService::kSegmenter:
|
||||||
icu_available_locales = icu::BreakIterator::getAvailableLocales(count);
|
icu_available_locales = icu::BreakIterator::getAvailableLocales(count);
|
||||||
break;
|
break;
|
||||||
case IcuService::kCollator:
|
case ICUService::kCollator:
|
||||||
icu_available_locales = icu::Collator::getAvailableLocales(count);
|
icu_available_locales = icu::Collator::getAvailableLocales(count);
|
||||||
break;
|
break;
|
||||||
case IcuService::kDateFormat:
|
case ICUService::kRelativeDateTimeFormatter:
|
||||||
|
case ICUService::kDateFormat:
|
||||||
icu_available_locales = icu::DateFormat::getAvailableLocales(count);
|
icu_available_locales = icu::DateFormat::getAvailableLocales(count);
|
||||||
break;
|
break;
|
||||||
case IcuService::kNumberFormat:
|
case ICUService::kNumberFormat:
|
||||||
icu_available_locales = icu::NumberFormat::getAvailableLocales(count);
|
icu_available_locales = icu::NumberFormat::getAvailableLocales(count);
|
||||||
break;
|
break;
|
||||||
case IcuService::kPluralRules:
|
case ICUService::kPluralRules:
|
||||||
// TODO(littledan): For PluralRules, filter out locales that
|
// TODO(littledan): For PluralRules, filter out locales that
|
||||||
// don't support PluralRules.
|
// don't support PluralRules.
|
||||||
// PluralRules is missing an appropriate getAvailableLocales method,
|
// PluralRules is missing an appropriate getAvailableLocales method,
|
||||||
@ -204,44 +212,7 @@ std::set<std::string> Intl::GetAvailableLocales(const IcuService& service) {
|
|||||||
// https://ssl.icu-project.org/trac/ticket/12756
|
// https://ssl.icu-project.org/trac/ticket/12756
|
||||||
icu_available_locales = icu::Locale::getAvailableLocales(count);
|
icu_available_locales = icu::Locale::getAvailableLocales(count);
|
||||||
break;
|
break;
|
||||||
case IcuService::kResourceBundle: {
|
case ICUService::kListFormatter: {
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
|
||||||
UEnumeration* en = ures_openAvailableLocales(nullptr, &status);
|
|
||||||
int32_t length = 0;
|
|
||||||
const char* locale_str = uenum_next(en, &length, &status);
|
|
||||||
while (U_SUCCESS(status) && (locale_str != nullptr)) {
|
|
||||||
std::string locale(locale_str, length);
|
|
||||||
std::replace(locale.begin(), locale.end(), '_', '-');
|
|
||||||
locales.insert(locale);
|
|
||||||
std::string shortened_locale;
|
|
||||||
if (Intl::RemoveLocaleScriptTag(locale_str, &shortened_locale)) {
|
|
||||||
std::replace(shortened_locale.begin(), shortened_locale.end(), '_',
|
|
||||||
'-');
|
|
||||||
locales.insert(shortened_locale);
|
|
||||||
}
|
|
||||||
locale_str = uenum_next(en, &length, &status);
|
|
||||||
}
|
|
||||||
uenum_close(en);
|
|
||||||
return locales;
|
|
||||||
}
|
|
||||||
case IcuService::kRelativeDateTimeFormatter: {
|
|
||||||
// ICU RelativeDateTimeFormatter does not provide a getAvailableLocales()
|
|
||||||
// interface, because RelativeDateTimeFormatter depends on
|
|
||||||
// 1. NumberFormat and 2. ResourceBundle, return the
|
|
||||||
// intersection of these two set.
|
|
||||||
// ICU FR at https://unicode-org.atlassian.net/browse/ICU-20009
|
|
||||||
// TODO(ftang): change to call ICU's getAvailableLocales() after it is
|
|
||||||
// added.
|
|
||||||
std::set<std::string> number_format_set(
|
|
||||||
Intl::GetAvailableLocales(IcuService::kNumberFormat));
|
|
||||||
std::set<std::string> resource_bundle_set(
|
|
||||||
Intl::GetAvailableLocales(IcuService::kResourceBundle));
|
|
||||||
set_intersection(resource_bundle_set.begin(), resource_bundle_set.end(),
|
|
||||||
number_format_set.begin(), number_format_set.end(),
|
|
||||||
std::inserter(locales, locales.begin()));
|
|
||||||
return locales;
|
|
||||||
}
|
|
||||||
case IcuService::kListFormatter: {
|
|
||||||
// TODO(ftang): for now just use
|
// TODO(ftang): for now just use
|
||||||
// icu::Locale::getAvailableLocales(count) until we migrate to
|
// icu::Locale::getAvailableLocales(count) until we migrate to
|
||||||
// Intl::GetAvailableLocales().
|
// Intl::GetAvailableLocales().
|
||||||
@ -268,7 +239,7 @@ std::set<std::string> Intl::GetAvailableLocales(const IcuService& service) {
|
|||||||
locales.insert(locale);
|
locales.insert(locale);
|
||||||
|
|
||||||
std::string shortened_locale;
|
std::string shortened_locale;
|
||||||
if (Intl::RemoveLocaleScriptTag(icu_name, &shortened_locale)) {
|
if (RemoveLocaleScriptTag(icu_name, &shortened_locale)) {
|
||||||
std::replace(shortened_locale.begin(), shortened_locale.end(), '_', '-');
|
std::replace(shortened_locale.begin(), shortened_locale.end(), '_', '-');
|
||||||
locales.insert(shortened_locale);
|
locales.insert(shortened_locale);
|
||||||
}
|
}
|
||||||
@ -277,32 +248,60 @@ std::set<std::string> Intl::GetAvailableLocales(const IcuService& service) {
|
|||||||
return locales;
|
return locales;
|
||||||
}
|
}
|
||||||
|
|
||||||
IcuService Intl::StringToIcuService(Handle<String> service) {
|
namespace {
|
||||||
if (service->IsUtf8EqualTo(CStrVector("collator"))) {
|
|
||||||
return IcuService::kCollator;
|
// TODO(gsathya): Remove this once we port ResolveLocale to C++.
|
||||||
} else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
|
ICUService StringToICUService(Handle<String> service) {
|
||||||
return IcuService::kNumberFormat;
|
std::unique_ptr<char[]> service_cstr = service->ToCString();
|
||||||
} else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
|
if (strcmp(service_cstr.get(), "collator") == 0) {
|
||||||
return IcuService::kDateFormat;
|
return ICUService::kCollator;
|
||||||
} else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
|
} else if (strcmp(service_cstr.get(), "numberformat") == 0) {
|
||||||
return IcuService::kBreakIterator;
|
return ICUService::kNumberFormat;
|
||||||
} else if (service->IsUtf8EqualTo(CStrVector("pluralrules"))) {
|
} else if (strcmp(service_cstr.get(), "dateformat") == 0) {
|
||||||
return IcuService::kPluralRules;
|
return ICUService::kDateFormat;
|
||||||
} else if (service->IsUtf8EqualTo(CStrVector("relativetimeformat"))) {
|
} else if (strcmp(service_cstr.get(), "breakiterator") == 0) {
|
||||||
return IcuService::kRelativeDateTimeFormatter;
|
return ICUService::kBreakIterator;
|
||||||
} else if (service->IsUtf8EqualTo(CStrVector("listformat"))) {
|
} else if (strcmp(service_cstr.get(), "pluralrules") == 0) {
|
||||||
return IcuService::kListFormatter;
|
return ICUService::kPluralRules;
|
||||||
|
} else if (strcmp(service_cstr.get(), "relativetimeformat") == 0) {
|
||||||
|
return ICUService::kRelativeDateTimeFormatter;
|
||||||
|
} else if (strcmp(service_cstr.get(), "listformat") == 0) {
|
||||||
|
return ICUService::kListFormatter;
|
||||||
} else if (service->IsUtf8EqualTo(CStrVector("segmenter"))) {
|
} else if (service->IsUtf8EqualTo(CStrVector("segmenter"))) {
|
||||||
return IcuService::kSegmenter;
|
return ICUService::kSegmenter;
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* ICUServiceToString(ICUService service) {
|
||||||
|
switch (service) {
|
||||||
|
case ICUService::kCollator:
|
||||||
|
return "Intl.Collator";
|
||||||
|
case ICUService::kNumberFormat:
|
||||||
|
return "Intl.NumberFormat";
|
||||||
|
case ICUService::kDateFormat:
|
||||||
|
return "Intl.DateFormat";
|
||||||
|
case ICUService::kBreakIterator:
|
||||||
|
return "Intl.v8BreakIterator";
|
||||||
|
case ICUService::kPluralRules:
|
||||||
|
return "Intl.PluralRules";
|
||||||
|
case ICUService::kRelativeDateTimeFormatter:
|
||||||
|
return "Intl.RelativeTimeFormat";
|
||||||
|
case ICUService::kListFormatter:
|
||||||
|
return "Intl.kListFormat";
|
||||||
|
case ICUService::kSegmenter:
|
||||||
|
return "Intl.kSegmenter";
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> Intl::AvailableLocalesOf(
|
V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> Intl::AvailableLocalesOf(
|
||||||
Isolate* isolate, Handle<String> service) {
|
Isolate* isolate, Handle<String> service) {
|
||||||
Factory* factory = isolate->factory();
|
Factory* factory = isolate->factory();
|
||||||
std::set<std::string> results =
|
std::set<std::string> results =
|
||||||
Intl::GetAvailableLocales(StringToIcuService(service));
|
Intl::GetAvailableLocales(StringToICUService(service));
|
||||||
Handle<JSObject> locales = factory->NewJSObjectWithNullProto();
|
Handle<JSObject> locales = factory->NewJSObjectWithNullProto();
|
||||||
|
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
@ -1349,26 +1348,28 @@ MaybeHandle<JSObject> CreateReadOnlyArray(Isolate* isolate,
|
|||||||
// ECMA 402 9.2.9 SupportedLocales(availableLocales, requestedLocales, options)
|
// ECMA 402 9.2.9 SupportedLocales(availableLocales, requestedLocales, options)
|
||||||
// https://tc39.github.io/ecma402/#sec-supportedlocales
|
// https://tc39.github.io/ecma402/#sec-supportedlocales
|
||||||
MaybeHandle<JSObject> SupportedLocales(
|
MaybeHandle<JSObject> SupportedLocales(
|
||||||
Isolate* isolate, const std::string& service,
|
Isolate* isolate, ICUService service,
|
||||||
const std::set<std::string>& available_locales,
|
const std::set<std::string>& available_locales,
|
||||||
const std::vector<std::string>& requested_locales, Handle<Object> options) {
|
const std::vector<std::string>& requested_locales, Handle<Object> options) {
|
||||||
std::vector<std::string> supported_locales;
|
std::vector<std::string> supported_locales;
|
||||||
|
|
||||||
// 1. If options is not undefined, then
|
|
||||||
// a. Let options be ? ToObject(options).
|
|
||||||
// b. Let matcher be ? GetOption(options, "localeMatcher", "string",
|
|
||||||
// « "lookup", "best fit" », "best fit").
|
|
||||||
// 2. Else, let matcher be "best fit".
|
// 2. Else, let matcher be "best fit".
|
||||||
MatcherOption matcher = kBestFit;
|
MatcherOption matcher = kBestFit;
|
||||||
|
|
||||||
|
// 1. If options is not undefined, then
|
||||||
if (!options->IsUndefined(isolate)) {
|
if (!options->IsUndefined(isolate)) {
|
||||||
|
// 1. a. Let options be ? ToObject(options).
|
||||||
Handle<JSReceiver> options_obj;
|
Handle<JSReceiver> options_obj;
|
||||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, options_obj,
|
ASSIGN_RETURN_ON_EXCEPTION(isolate, options_obj,
|
||||||
Object::ToObject(isolate, options), JSObject);
|
Object::ToObject(isolate, options), JSObject);
|
||||||
|
|
||||||
|
// 1. b. Let matcher be ? GetOption(options, "localeMatcher", "string",
|
||||||
|
// « "lookup", "best fit" », "best fit").
|
||||||
std::unique_ptr<char[]> matcher_str = nullptr;
|
std::unique_ptr<char[]> matcher_str = nullptr;
|
||||||
std::vector<const char*> matcher_values = {"lookup", "best fit"};
|
std::vector<const char*> matcher_values = {"lookup", "best fit"};
|
||||||
Maybe<bool> maybe_found_matcher =
|
Maybe<bool> maybe_found_matcher = Intl::GetStringOption(
|
||||||
Intl::GetStringOption(isolate, options_obj, "localeMatcher",
|
isolate, options_obj, "localeMatcher", matcher_values,
|
||||||
matcher_values, service.c_str(), &matcher_str);
|
ICUServiceToString(service), &matcher_str);
|
||||||
MAYBE_RETURN(maybe_found_matcher, MaybeHandle<JSObject>());
|
MAYBE_RETURN(maybe_found_matcher, MaybeHandle<JSObject>());
|
||||||
if (maybe_found_matcher.FromJust()) {
|
if (maybe_found_matcher.FromJust()) {
|
||||||
DCHECK_NOT_NULL(matcher_str.get());
|
DCHECK_NOT_NULL(matcher_str.get());
|
||||||
@ -1412,30 +1413,21 @@ MaybeHandle<JSObject> SupportedLocales(
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// ECMA 402 Intl.*.supportedLocalesOf
|
// ECMA 402 Intl.*.supportedLocalesOf
|
||||||
// https://tc39.github.io/ecma402/#sec-intl.collator.supportedlocalesof
|
|
||||||
// https://tc39.github.io/ecma402/#sec-intl.numberformat.supportedlocalesof
|
|
||||||
// https://tc39.github.io/ecma402/#sec-intl.datetimeformat.supportedlocalesof
|
|
||||||
// https://tc39.github.io/ecma402/#sec-intl.pluralrules.supportedlocalesof
|
|
||||||
// http://tc39.github.io/proposal-intl-relative-time/#sec-Intl.RelativeTimeFormat.supportedLocalesOf
|
|
||||||
MaybeHandle<JSObject> Intl::SupportedLocalesOf(Isolate* isolate,
|
MaybeHandle<JSObject> Intl::SupportedLocalesOf(Isolate* isolate,
|
||||||
Handle<String> service,
|
ICUService service,
|
||||||
Handle<Object> locales_in,
|
Handle<Object> locales,
|
||||||
Handle<Object> options_in) {
|
Handle<Object> options) {
|
||||||
// Let availableLocales be %Collator%.[[AvailableLocales]].
|
// Let availableLocales be %Collator%.[[AvailableLocales]].
|
||||||
IcuService icu_service = Intl::StringToIcuService(service);
|
std::set<std::string> available_locales = GetAvailableLocales(service);
|
||||||
std::set<std::string> available_locales = GetAvailableLocales(icu_service);
|
|
||||||
std::vector<std::string> requested_locales;
|
|
||||||
// Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
// Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||||
bool got_requested_locales =
|
Maybe<std::vector<std::string>> requested_locales =
|
||||||
CanonicalizeLocaleList(isolate, locales_in, false).To(&requested_locales);
|
CanonicalizeLocaleList(isolate, locales, false);
|
||||||
if (!got_requested_locales) {
|
MAYBE_RETURN(requested_locales, MaybeHandle<JSObject>());
|
||||||
return MaybeHandle<JSObject>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return ? SupportedLocales(availableLocales, requestedLocales, options).
|
// Return ? SupportedLocales(availableLocales, requestedLocales, options).
|
||||||
std::string service_str(service->ToCString().get());
|
return SupportedLocales(isolate, service, available_locales,
|
||||||
return SupportedLocales(isolate, service_str, available_locales,
|
requested_locales.FromJust(), options);
|
||||||
requested_locales, options_in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, std::string> Intl::LookupUnicodeExtensions(
|
std::map<std::string, std::string> Intl::LookupUnicodeExtensions(
|
||||||
|
@ -61,13 +61,11 @@ class Intl {
|
|||||||
static bool IsObjectOfType(Isolate* isolate, Handle<Object> object,
|
static bool IsObjectOfType(Isolate* isolate, Handle<Object> object,
|
||||||
Intl::Type expected_type);
|
Intl::Type expected_type);
|
||||||
|
|
||||||
static IcuService StringToIcuService(Handle<String> service);
|
|
||||||
|
|
||||||
// Gets the ICU locales for a given service. If there is a locale with a
|
// Gets the ICU locales for a given service. If there is a locale with a
|
||||||
// script tag then the locales also include a locale without the script; eg,
|
// script tag then the locales also include a locale without the script; eg,
|
||||||
// pa_Guru_IN (language=Panjabi, script=Gurmukhi, country-India) would include
|
// pa_Guru_IN (language=Panjabi, script=Gurmukhi, country-India) would include
|
||||||
// pa_IN.
|
// pa_IN.
|
||||||
static std::set<std::string> GetAvailableLocales(const IcuService& service);
|
static std::set<std::string> GetAvailableLocales(ICUService service);
|
||||||
|
|
||||||
// Get the name of the numbering system from locale.
|
// Get the name of the numbering system from locale.
|
||||||
// ICU doesn't expose numbering system in any way, so we have to assume that
|
// ICU doesn't expose numbering system in any way, so we have to assume that
|
||||||
@ -78,18 +76,12 @@ class Intl {
|
|||||||
static V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> AvailableLocalesOf(
|
static V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> AvailableLocalesOf(
|
||||||
Isolate* isolate, Handle<String> service);
|
Isolate* isolate, Handle<String> service);
|
||||||
|
|
||||||
static MaybeHandle<JSObject> SupportedLocalesOf(Isolate* isolate,
|
static V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> SupportedLocalesOf(
|
||||||
Handle<String> service,
|
Isolate* isolate, ICUService service, Handle<Object> locales_in,
|
||||||
Handle<Object> locales_in,
|
Handle<Object> options_in);
|
||||||
Handle<Object> options_in);
|
|
||||||
|
|
||||||
static std::string DefaultLocale(Isolate* isolate);
|
static std::string DefaultLocale(Isolate* isolate);
|
||||||
|
|
||||||
// If locale has a script tag then return true and the locale without the
|
|
||||||
// script else return false and an empty string
|
|
||||||
static bool RemoveLocaleScriptTag(const std::string& icu_locale,
|
|
||||||
std::string* locale_less_script);
|
|
||||||
|
|
||||||
// The ResolveLocale abstract operation compares a BCP 47 language
|
// The ResolveLocale abstract operation compares a BCP 47 language
|
||||||
// priority list requestedLocales against the locales in
|
// priority list requestedLocales against the locales in
|
||||||
// availableLocales and determines the best available language to
|
// availableLocales and determines the best available language to
|
||||||
|
@ -208,52 +208,26 @@ TEST(GetBoolOption) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptTagWasRemoved(std::string locale, std::string expected) {
|
|
||||||
std::string without_script_tag;
|
|
||||||
bool didShorten = Intl::RemoveLocaleScriptTag(locale, &without_script_tag);
|
|
||||||
return didShorten && expected == without_script_tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScriptTagWasNotRemoved(std::string locale) {
|
|
||||||
std::string without_script_tag;
|
|
||||||
bool didShorten = Intl::RemoveLocaleScriptTag(locale, &without_script_tag);
|
|
||||||
return !didShorten && without_script_tag.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RemoveLocaleScriptTag) {
|
|
||||||
CHECK(ScriptTagWasRemoved("aa_Bbbb_CC", "aa_CC"));
|
|
||||||
CHECK(ScriptTagWasRemoved("aaa_Bbbb_CC", "aaa_CC"));
|
|
||||||
|
|
||||||
CHECK(ScriptTagWasNotRemoved("aa"));
|
|
||||||
CHECK(ScriptTagWasNotRemoved("aaa"));
|
|
||||||
CHECK(ScriptTagWasNotRemoved("aa_CC"));
|
|
||||||
CHECK(ScriptTagWasNotRemoved("aa_Bbb_CC"));
|
|
||||||
CHECK(ScriptTagWasNotRemoved("aa_1bbb_CC"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(GetAvailableLocales) {
|
TEST(GetAvailableLocales) {
|
||||||
std::set<std::string> locales;
|
std::set<std::string> locales;
|
||||||
|
|
||||||
locales = Intl::GetAvailableLocales(IcuService::kBreakIterator);
|
locales = Intl::GetAvailableLocales(ICUService::kBreakIterator);
|
||||||
CHECK(locales.count("en-US"));
|
CHECK(locales.count("en-US"));
|
||||||
CHECK(!locales.count("abcdefg"));
|
CHECK(!locales.count("abcdefg"));
|
||||||
|
|
||||||
locales = Intl::GetAvailableLocales(IcuService::kCollator);
|
locales = Intl::GetAvailableLocales(ICUService::kCollator);
|
||||||
CHECK(locales.count("en-US"));
|
CHECK(locales.count("en-US"));
|
||||||
|
|
||||||
locales = Intl::GetAvailableLocales(IcuService::kDateFormat);
|
locales = Intl::GetAvailableLocales(ICUService::kDateFormat);
|
||||||
CHECK(locales.count("en-US"));
|
CHECK(locales.count("en-US"));
|
||||||
|
|
||||||
locales = Intl::GetAvailableLocales(IcuService::kNumberFormat);
|
locales = Intl::GetAvailableLocales(ICUService::kNumberFormat);
|
||||||
CHECK(locales.count("en-US"));
|
CHECK(locales.count("en-US"));
|
||||||
|
|
||||||
locales = Intl::GetAvailableLocales(IcuService::kPluralRules);
|
locales = Intl::GetAvailableLocales(ICUService::kPluralRules);
|
||||||
CHECK(locales.count("en-US"));
|
CHECK(locales.count("en-US"));
|
||||||
|
|
||||||
locales = Intl::GetAvailableLocales(IcuService::kResourceBundle);
|
locales = Intl::GetAvailableLocales(ICUService::kRelativeDateTimeFormatter);
|
||||||
CHECK(locales.count("en-US"));
|
|
||||||
|
|
||||||
locales = Intl::GetAvailableLocales(IcuService::kRelativeDateTimeFormatter);
|
|
||||||
CHECK(locales.count("en-US"));
|
CHECK(locales.count("en-US"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user