Commit 1a225459 authored by Brian Stell's avatar Brian Stell Committed by Commit Bot

Implement ResolveLocale in C++.

Bug: v8:8065, v8:5751
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: Id9dc16455d63b7c436126c21758d64fae0ec8de9
Reviewed-on: https://chromium-review.googlesource.com/1211402Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55925}
parent 24a232e2
......@@ -96,7 +96,6 @@ enum ContextLookupFlags {
V(REFERENCE_ERROR_FUNCTION_INDEX, JSFunction, reference_error_function) \
V(CACHED_OR_NEW_SERVICE_LOCALE_FUNCTION_INDEX, JSFunction, \
cached_or_new_service) \
V(RESOLVE_LOCALE_FUNCTION_INDEX, JSFunction, resolve_locale) \
V(SET_ADD_INDEX, JSFunction, set_add) \
V(SET_DELETE_INDEX, JSFunction, set_delete) \
V(SET_HAS_INDEX, JSFunction, set_has) \
......
This diff is collapsed.
This diff is collapsed.
......@@ -89,6 +89,13 @@ class Intl {
static bool RemoveLocaleScriptTag(const std::string& icu_locale,
std::string* locale_less_script);
struct ResolvedLocale {
std::string locale; // The bcp47 locale to use.
std::string unicode_extensions;
std::map<std::string, std::string> extensions;
std::string locale_with_extensions;
};
// The ResolveLocale abstract operation compares a BCP 47 language
// priority list requestedLocales against the locales in
// availableLocales and determines the best available language to
......@@ -98,14 +105,15 @@ class Intl {
//
// #ecma402/sec-partitiondatetimepattern
//
// Returns a JSObject with two properties:
// Returns an object with two properties:
// (1) locale
// (2) extension
//
// To access either, use JSObject::GetDataProperty.
V8_WARN_UNUSED_RESULT static MaybeHandle<JSObject> ResolveLocale(
Isolate* isolate, const char* service, Handle<Object> requestedLocales,
Handle<Object> options);
V8_WARN_UNUSED_RESULT static Maybe<ResolvedLocale*> ResolveLocale(
Isolate* isolate, const char* service,
const std::set<std::string>& available_locales,
const std::vector<std::string>& requested_locales,
const std::set<std::string>& relevant_extension_keys,
Handle<JSReceiver> options);
// This currently calls out to the JavaScript implementation of
// CanonicalizeLocaleList.
......
......@@ -28,6 +28,9 @@ MaybeHandle<JSV8BreakIterator> JSV8BreakIterator::InitializeV8BreakIterator(
Isolate* isolate, Handle<JSV8BreakIterator> break_iterator_holder,
Handle<Object> locales, Handle<Object> options_obj) {
Factory* factory = isolate->factory();
Maybe<std::vector<std::string>> requested_locales =
Intl::CanonicalizeLocaleList(isolate, locales, false);
MAYBE_RETURN(requested_locales, MaybeHandle<JSV8BreakIterator>());
Handle<JSReceiver> options;
if (options_obj->IsUndefined(isolate)) {
......@@ -40,15 +43,18 @@ MaybeHandle<JSV8BreakIterator> JSV8BreakIterator::InitializeV8BreakIterator(
}
// Extract locale string
Handle<JSObject> r;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, r,
Intl::ResolveLocale(isolate, "breakiterator", locales, options),
JSV8BreakIterator);
Handle<Object> locale_obj =
JSObject::GetDataProperty(r, factory->locale_string());
CHECK(locale_obj->IsString());
Handle<String> locale = Handle<String>::cast(locale_obj);
const std::set<std::string> relevant_extension_keys;
std::set<std::string> available_locales =
Intl::GetAvailableLocales(IcuService::kListFormatter);
Maybe<Intl::ResolvedLocale*> maybe_resolved_locale = Intl::ResolveLocale(
isolate, "breakiterator", available_locales, requested_locales.FromJust(),
relevant_extension_keys, options);
MAYBE_RETURN(maybe_resolved_locale, MaybeHandle<JSV8BreakIterator>());
std::unique_ptr<Intl::ResolvedLocale> r(maybe_resolved_locale.FromJust());
CHECK_NOT_NULL(r.get());
Handle<String> locale =
isolate->factory()->NewStringFromAsciiChecked(r.get()->locale.c_str());
// Extract type from options
std::unique_ptr<char[]> type_str = nullptr;
......
......@@ -221,10 +221,9 @@ MaybeHandle<JSCollator> JSCollator::InitializeCollator(
Isolate* isolate, Handle<JSCollator> collator, Handle<Object> locales,
Handle<Object> options_obj) {
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
Handle<JSObject> requested_locales;
ASSIGN_RETURN_ON_EXCEPTION(isolate, requested_locales,
Intl::CanonicalizeLocaleListJS(isolate, locales),
JSCollator);
Maybe<std::vector<std::string>> requested_locales =
Intl::CanonicalizeLocaleList(isolate, locales, false);
MAYBE_RETURN(requested_locales, MaybeHandle<JSCollator>());
// 2. If options is undefined, then
if (options_obj->IsUndefined(isolate)) {
......@@ -257,10 +256,7 @@ MaybeHandle<JSCollator> JSCollator::InitializeCollator(
}
}
// TODO(gsathya): This is currently done as part of the
// Intl::ResolveLocale call below. Fix this once resolveLocale is
// changed to not do the lookup.
//
// Steps 9 and 10 are done as part of the Intl::ResolveLocale call below.
// 9. Let matcher be ? GetOption(options, "localeMatcher", "string",
// « "lookup", "best fit" », "best fit").
// 10. Set opt.[[localeMatcher]] to matcher.
......@@ -316,25 +312,20 @@ MaybeHandle<JSCollator> JSCollator::InitializeCollator(
// requestedLocales, opt, %Collator%.[[RelevantExtensionKeys]],
// localeData).
// 18. Set collator.[[Locale]] to r.[[locale]].
Handle<JSObject> r;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, r,
Intl::ResolveLocale(isolate, "collator", requested_locales, options),
JSCollator);
Handle<String> locale_with_extension_str =
isolate->factory()->NewStringFromStaticChars("localeWithExtension");
Handle<Object> locale_with_extension_obj =
JSObject::GetDataProperty(r, locale_with_extension_str);
// The locale_with_extension has to be a string. Either a user
// provided canonicalized string or the default locale.
CHECK(locale_with_extension_obj->IsString());
Handle<String> locale_with_extension =
Handle<String>::cast(locale_with_extension_obj);
icu::Locale icu_locale =
Intl::CreateICULocale(isolate, locale_with_extension);
std::set<std::string> available_locales =
Intl::GetAvailableLocales(IcuService::kCollator);
Maybe<Intl::ResolvedLocale*> maybe_resolved_locale = Intl::ResolveLocale(
isolate, "collator", available_locales, requested_locales.FromJust(),
relevant_extension_keys, options);
MAYBE_RETURN(maybe_resolved_locale, MaybeHandle<JSCollator>());
std::unique_ptr<Intl::ResolvedLocale> r(maybe_resolved_locale.FromJust());
CHECK_NOT_NULL(r.get());
std::string locale_with_extension = r.get()->locale_with_extensions;
Handle<String> locale = isolate->factory()->NewStringFromAsciiChecked(
locale_with_extension.c_str());
icu::Locale icu_locale = Intl::CreateICULocale(isolate, locale);
DCHECK(!icu_locale.isBogus());
std::map<std::string, std::string> extensions =
......
......@@ -775,7 +775,12 @@ enum FormatMatcherOption { kBestFit, kBasic };
// ecma402/#sec-initializedatetimeformat
MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::Initialize(
Isolate* isolate, Handle<JSDateTimeFormat> date_time_format,
Handle<Object> requested_locales, Handle<Object> input_options) {
Handle<Object> locales, Handle<Object> input_options) {
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
Maybe<std::vector<std::string>> requested_locales =
Intl::CanonicalizeLocaleList(isolate, locales, false);
MAYBE_RETURN(requested_locales, MaybeHandle<JSDateTimeFormat>());
// 2. Let options be ? ToDateTimeOptions(options, "any", "date").
Handle<JSObject> options;
ASSIGN_RETURN_ON_EXCEPTION(
......@@ -784,29 +789,26 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::Initialize(
isolate, input_options, RequiredOption::kAny, DefaultsOption::kDate),
JSDateTimeFormat);
const std::set<std::string> relevant_extension_keys{"ca", "nu", "hc"};
// 11. Let r be ResolveLocale( %DateTimeFormat%.[[AvailableLocales]],
// requestedLocales, opt, %DateTimeFormat%.[[RelevantExtensionKeys]],
// localeData).
const char* kService = "Intl.DateTimeFormat";
Handle<JSObject> r;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, r,
Intl::ResolveLocale(isolate, "dateformat", requested_locales, options),
JSDateTimeFormat);
Handle<String> locale_with_extension_str =
isolate->factory()->NewStringFromStaticChars("localeWithExtension");
Handle<Object> locale_with_extension_obj =
JSObject::GetDataProperty(r, locale_with_extension_str);
// The locale_with_extension has to be a string. Either a user
// provided canonicalized string or the default locale.
CHECK(locale_with_extension_obj->IsString());
Handle<String> locale_with_extension =
Handle<String>::cast(locale_with_extension_obj);
icu::Locale icu_locale =
Intl::CreateICULocale(isolate, locale_with_extension);
std::set<std::string> available_locales =
Intl::GetAvailableLocales(IcuService::kRelativeDateTimeFormatter);
Maybe<Intl::ResolvedLocale*> maybe_resolved_locale = Intl::ResolveLocale(
isolate, "datetimeformat", available_locales,
requested_locales.FromJust(), relevant_extension_keys, options);
MAYBE_RETURN(maybe_resolved_locale, MaybeHandle<JSDateTimeFormat>());
std::unique_ptr<Intl::ResolvedLocale> r(maybe_resolved_locale.FromJust());
CHECK_NOT_NULL(r.get());
std::string locale_with_extension = r.get()->locale_with_extensions;
Handle<String> locale = isolate->factory()->NewStringFromAsciiChecked(
locale_with_extension.c_str());
icu::Locale icu_locale = Intl::CreateICULocale(isolate, locale);
DCHECK(!icu_locale.isBogus());
// We implement only best fit algorithm, but still need to check
......
......@@ -122,7 +122,10 @@ JSListFormat::Type get_type(const char* str) {
MaybeHandle<JSListFormat> JSListFormat::InitializeListFormat(
Isolate* isolate, Handle<JSListFormat> list_format_holder,
Handle<Object> input_locales, Handle<Object> input_options) {
Factory* factory = isolate->factory();
Maybe<std::vector<std::string>> requested_locales =
Intl::CanonicalizeLocaleList(isolate, input_locales, false);
MAYBE_RETURN(requested_locales, MaybeHandle<JSListFormat>());
list_format_holder->set_flags(0);
Handle<JSReceiver> options;
......@@ -170,23 +173,23 @@ MaybeHandle<JSListFormat> JSListFormat::InitializeListFormat(
// 10. Let r be ResolveLocale(%ListFormat%.[[AvailableLocales]],
// requestedLocales, opt, undefined, localeData).
Handle<JSObject> r;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, r,
Intl::ResolveLocale(isolate, "listformat", input_locales, options),
JSListFormat);
Handle<Object> locale_obj =
JSObject::GetDataProperty(r, factory->locale_string());
Handle<String> locale;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, locale, Object::ToString(isolate, locale_obj), JSListFormat);
const std::set<std::string> relevant_extension_keys;
std::set<std::string> available_locales =
Intl::GetAvailableLocales(IcuService::kListFormatter);
Maybe<Intl::ResolvedLocale*> maybe_resolved_locale = Intl::ResolveLocale(
isolate, "listformatter", available_locales, requested_locales.FromJust(),
relevant_extension_keys, options);
MAYBE_RETURN(maybe_resolved_locale, MaybeHandle<JSListFormat>());
std::unique_ptr<Intl::ResolvedLocale> r(maybe_resolved_locale.FromJust());
CHECK_NOT_NULL(r.get());
Handle<String> locale =
isolate->factory()->NewStringFromAsciiChecked(r.get()->locale.c_str());
// 18. Set listFormat.[[Locale]] to the value of r.[[Locale]].
list_format_holder->set_locale(*locale);
std::unique_ptr<char[]> locale_name = locale->ToCString();
icu::Locale icu_locale(locale_name.get());
icu::Locale icu_locale(r.get()->locale.c_str());
UErrorCode status = U_ZERO_ERROR;
icu::ListFormatter* formatter = icu::ListFormatter::createInstance(
icu_locale, GetIcuStyleString(style_enum, type_enum), status);
......
......@@ -189,10 +189,9 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
number_format->set_flags(0);
Factory* factory = isolate->factory();
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
Handle<JSObject> requested_locales;
ASSIGN_RETURN_ON_EXCEPTION(isolate, requested_locales,
Intl::CanonicalizeLocaleListJS(isolate, locales),
JSNumberFormat);
Maybe<std::vector<std::string>> requested_locales =
Intl::CanonicalizeLocaleList(isolate, locales, false);
MAYBE_RETURN(requested_locales, MaybeHandle<JSNumberFormat>());
// 2. If options is undefined, then
if (options_obj->IsUndefined(isolate)) {
......@@ -212,6 +211,8 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
// 4. Let opt be a new Record.
//
// Steps 5 and 6 are currently done as part of the
// Intl::ResolveLocale call below.
// 5. Let matcher be ? GetOption(options, "localeMatcher", "string", «
// "lookup", "best fit" », "best fit").
//
......@@ -225,29 +226,26 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
//
// 9. Set numberFormat.[[Locale]] to r.[[locale]].
Handle<JSObject> r;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, r,
Intl::ResolveLocale(isolate, "numberformat", requested_locales, options),
JSNumberFormat);
Handle<String> locale_with_extension_str =
isolate->factory()->NewStringFromStaticChars("localeWithExtension");
Handle<Object> locale_with_extension_obj =
JSObject::GetDataProperty(r, locale_with_extension_str);
// The locale_with_extension has to be a string. Either a user
// provided canonicalized string or the default locale.
CHECK(locale_with_extension_obj->IsString());
Handle<String> locale_with_extension =
Handle<String>::cast(locale_with_extension_obj);
icu::Locale icu_locale =
Intl::CreateICULocale(isolate, locale_with_extension);
number_format->set_locale(*locale_with_extension);
std::set<std::string> available_locales =
Intl::GetAvailableLocales(IcuService::kNumberFormat);
// 13.3.3 Internal slots
// https://tc39.github.io/ecma402/#sec-intl.numberformat-internal-slots
const std::set<std::string> relevant_extension_keys{"nu"};
Maybe<Intl::ResolvedLocale*> maybe_resolved_locale = Intl::ResolveLocale(
isolate, "numberformat", available_locales, requested_locales.FromJust(),
relevant_extension_keys, options);
MAYBE_RETURN(maybe_resolved_locale, MaybeHandle<JSNumberFormat>());
std::unique_ptr<Intl::ResolvedLocale> r(maybe_resolved_locale.FromJust());
CHECK_NOT_NULL(r.get());
std::string locale_with_extension = r.get()->locale_with_extensions;
Handle<String> locale = isolate->factory()->NewStringFromAsciiChecked(
locale_with_extension.c_str());
icu::Locale icu_locale = Intl::CreateICULocale(isolate, locale);
number_format->set_locale(*locale);
DCHECK(!icu_locale.isBogus());
std::set<std::string> relevant_extension_keys{"nu"};
std::map<std::string, std::string> extensions =
Intl::LookupUnicodeExtensions(icu_locale, relevant_extension_keys);
......
......@@ -89,12 +89,9 @@ MaybeHandle<JSPluralRules> JSPluralRules::InitializePluralRules(
Isolate* isolate, Handle<JSPluralRules> plural_rules,
Handle<Object> locales, Handle<Object> options_obj) {
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
// TODO(jkummerow): Port ResolveLocale, then use the C++ version of
// CanonicalizeLocaleList here.
Handle<JSObject> requested_locales;
ASSIGN_RETURN_ON_EXCEPTION(isolate, requested_locales,
Intl::CanonicalizeLocaleListJS(isolate, locales),
JSPluralRules);
Maybe<std::vector<std::string>> requested_locales =
Intl::CanonicalizeLocaleList(isolate, locales, false);
MAYBE_RETURN(requested_locales, MaybeHandle<JSPluralRules>());
// 2. If options is undefined, then
if (options_obj->IsUndefined(isolate)) {
......@@ -112,10 +109,8 @@ MaybeHandle<JSPluralRules> JSPluralRules::InitializePluralRules(
// At this point, options_obj can either be a JSObject or a JSProxy only.
Handle<JSReceiver> options = Handle<JSReceiver>::cast(options_obj);
// TODO(gsathya): This is currently done as part of the
// Intl::ResolveLocale call below. Fix this once resolveLocale is
// changed to not do the lookup.
//
// Steps 5 and 6 are currently done as part of the
// Intl::ResolveLocale call below.
// 5. Let matcher be ? GetOption(options, "localeMatcher", "string",
// « "lookup", "best fit" », "best fit").
// 6. Set opt.[[localeMatcher]] to matcher.
......@@ -146,19 +141,21 @@ MaybeHandle<JSPluralRules> JSPluralRules::InitializePluralRules(
// 11. Let r be ResolveLocale(%PluralRules%.[[AvailableLocales]],
// requestedLocales, opt, %PluralRules%.[[RelevantExtensionKeys]],
// localeData).
Handle<JSObject> r;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, r,
Intl::ResolveLocale(isolate, "pluralrules", requested_locales, options),
JSPluralRules);
Handle<String> locale_str = isolate->factory()->locale_string();
Handle<Object> locale_obj = JSObject::GetDataProperty(r, locale_str);
// The locale has to be a string. Either a user provided
// canonicalized string or the default locale.
CHECK(locale_obj->IsString());
Handle<String> locale = Handle<String>::cast(locale_obj);
std::set<std::string> available_locales =
Intl::GetAvailableLocales(IcuService::kPluralRules);
// 13.3.3 Internal slots
// https://tc39.github.io/ecma402/#sec-intl.pluralrules-internal-slots
// The value of the [[RelevantExtensionKeys]] internal slot is [].
const std::set<std::string> relevant_extension_keys;
Maybe<Intl::ResolvedLocale*> maybe_resolved_locale = Intl::ResolveLocale(
isolate, "pluralrules", available_locales, requested_locales.FromJust(),
relevant_extension_keys, options);
MAYBE_RETURN(maybe_resolved_locale, MaybeHandle<JSPluralRules>());
std::unique_ptr<Intl::ResolvedLocale> r(maybe_resolved_locale.FromJust());
CHECK_NOT_NULL(r.get());
Handle<String> locale =
isolate->factory()->NewStringFromAsciiChecked(r.get()->locale.c_str());
// 12. Set pluralRules.[[Locale]] to the value of r.[[locale]].
plural_rules->set_locale(*locale);
......
......@@ -59,7 +59,10 @@ MaybeHandle<JSRelativeTimeFormat>
JSRelativeTimeFormat::InitializeRelativeTimeFormat(
Isolate* isolate, Handle<JSRelativeTimeFormat> relative_time_format_holder,
Handle<Object> input_locales, Handle<Object> input_options) {
Factory* factory = isolate->factory();
Maybe<std::vector<std::string>> requested_locales =
Intl::CanonicalizeLocaleList(isolate, input_locales, false);
MAYBE_RETURN(requested_locales, MaybeHandle<JSRelativeTimeFormat>());
relative_time_format_holder->set_flags(0);
// 4. If options is undefined, then
Handle<JSReceiver> options;
......@@ -78,17 +81,20 @@ JSRelativeTimeFormat::InitializeRelativeTimeFormat(
// requestedLocales, opt,
// %RelativeTimeFormat%.[[RelevantExtensionKeys]],
// localeData).
Handle<JSObject> r;
ASSIGN_RETURN_ON_EXCEPTION(isolate, r,
Intl::ResolveLocale(isolate, "relativetimeformat",
input_locales, options),
JSRelativeTimeFormat);
Handle<Object> locale_obj =
JSObject::GetDataProperty(r, factory->locale_string());
Handle<String> locale;
ASSIGN_RETURN_ON_EXCEPTION(isolate, locale,
Object::ToString(isolate, locale_obj),
JSRelativeTimeFormat);
std::set<std::string> available_locales =
Intl::GetAvailableLocales(IcuService::kRelativeDateTimeFormatter);
// 13.3.3 Internal slots
// The value of the [[RelevantExtensionKeys]] internal slot is [].
const std::set<std::string> relevant_extension_keys;
Maybe<Intl::ResolvedLocale*> maybe_resolved_locale = Intl::ResolveLocale(
isolate, "relativetimeformat", available_locales,
requested_locales.FromJust(), relevant_extension_keys, options);
MAYBE_RETURN(maybe_resolved_locale, MaybeHandle<JSRelativeTimeFormat>());
std::unique_ptr<Intl::ResolvedLocale> r(maybe_resolved_locale.FromJust());
CHECK_NOT_NULL(r.get());
Handle<String> locale =
isolate->factory()->NewStringFromAsciiChecked(r.get()->locale.c_str());
// 11. Let locale be r.[[Locale]].
// 12. Set relativeTimeFormat.[[Locale]] to locale.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment