Commit 6a44b750 authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

Remove keyword/value "ca" and "nu" from locale

Remove unicode keyword/value "ca" and "nu" from
the resolvedOptions().locale, if it does not match
the option "calendar" / "numberingSystem".

Bug: v8:9887
Change-Id: Idabc7e266e8e5f847f919324a93e39df4df440c8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1877708Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Frank Tang <ftang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64663}
parent d93dab6b
......@@ -2013,6 +2013,7 @@ void JSCollator::JSCollatorPrint(std::ostream& os) { // NOLINT
void JSDateTimeFormat::JSDateTimeFormatPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, *this, "JSDateTimeFormat");
os << "\n - locale: " << Brief(locale());
os << "\n - icu locale: " << Brief(icu_locale());
os << "\n - icu simple date format: " << Brief(icu_simple_date_format());
os << "\n - icu date interval format: " << Brief(icu_date_interval_format());
......@@ -2039,6 +2040,7 @@ void JSLocale::JSLocalePrint(std::ostream& os) { // NOLINT
void JSNumberFormat::JSNumberFormatPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, *this, "JSNumberFormat");
os << "\n - locale: " << Brief(locale());
os << "\n - numberingSystem: " << Brief(numberingSystem());
os << "\n - icu_number_formatter: " << Brief(icu_number_formatter());
os << "\n - bound_format: " << Brief(bound_format());
JSObjectPrintBody(os, *this);
......@@ -2057,6 +2059,7 @@ void JSRelativeTimeFormat::JSRelativeTimeFormatPrint(
std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, *this, "JSRelativeTimeFormat");
os << "\n - locale: " << Brief(locale());
os << "\n - numberingSystem: " << Brief(numberingSystem());
os << "\n - style: " << StyleAsString();
os << "\n - numeric: " << NumericAsString();
os << "\n - icu formatter: " << Brief(icu_formatter());
......
......@@ -15,6 +15,7 @@
#include 'src/objects/js-segmenter.h'
extern class JSDateTimeFormat extends JSObject {
locale: String;
icu_locale: Foreign; // Managed<icu::Locale>
icu_simple_date_format: Foreign; // Managed<icu::SimpleDateFormat>
icu_date_interval_format: Foreign; // Managed<icu::DateIntervalFormat>
......@@ -30,6 +31,7 @@ extern class JSListFormat extends JSObject {
extern class JSNumberFormat extends JSObject {
locale: String;
numberingSystem: String;
icu_number_formatter:
Foreign; // Managed<icu::number::LocalizedNumberFormatter>
bound_format: JSFunction|Undefined;
......@@ -46,6 +48,7 @@ extern class JSPluralRules extends JSObject {
extern class JSRelativeTimeFormat extends JSObject {
locale: String;
numberingSystem: String;
icu_formatter: Foreign; // Managed<icu::RelativeDateTimeFormatter>
flags: Smi;
}
......
......@@ -20,6 +20,7 @@ namespace internal {
OBJECT_CONSTRUCTORS_IMPL(JSDateTimeFormat, JSObject)
ACCESSORS(JSDateTimeFormat, locale, String, kLocaleOffset)
ACCESSORS(JSDateTimeFormat, icu_locale, Managed<icu::Locale>, kIcuLocaleOffset)
ACCESSORS(JSDateTimeFormat, icu_simple_date_format,
Managed<icu::SimpleDateFormat>, kIcuSimpleDateFormatOffset)
......
......@@ -383,14 +383,10 @@ MaybeHandle<JSObject> JSDateTimeFormat::ResolvedOptions(
Handle<Object> resolved_obj;
Handle<String> locale = Handle<String>(date_time_format->locale(), isolate);
CHECK(!date_time_format->icu_locale().is_null());
CHECK_NOT_NULL(date_time_format->icu_locale().raw());
icu::Locale* icu_locale = date_time_format->icu_locale().raw();
Maybe<std::string> maybe_locale_str = Intl::ToLanguageTag(*icu_locale);
MAYBE_RETURN(maybe_locale_str, MaybeHandle<JSObject>());
std::string locale_str = maybe_locale_str.FromJust();
Handle<String> locale =
factory->NewStringFromAsciiChecked(locale_str.c_str());
icu::SimpleDateFormat* icu_simple_date_format =
date_time_format->icu_simple_date_format().raw();
......@@ -1327,6 +1323,27 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
DCHECK(!icu_locale.isBogus());
UErrorCode status = U_ZERO_ERROR;
if (calendar_str != nullptr) {
auto ca_extension_it = r.extensions.find("ca");
if (ca_extension_it != r.extensions.end() &&
ca_extension_it->second != calendar_str.get()) {
icu_locale.setUnicodeKeywordValue("ca", nullptr, status);
CHECK(U_SUCCESS(status));
}
}
if (numbering_system_str != nullptr) {
auto nu_extension_it = r.extensions.find("nu");
if (nu_extension_it != r.extensions.end() &&
nu_extension_it->second != numbering_system_str.get()) {
icu_locale.setUnicodeKeywordValue("nu", nullptr, status);
CHECK(U_SUCCESS(status));
}
}
// Need to keep a copy of icu_locale which not changing "ca", "nu", "hc"
// by option.
icu::Locale resolved_locale(icu_locale);
if (calendar_str != nullptr &&
Intl::IsValidCalendar(icu_locale, calendar_str.get())) {
icu_locale.setUnicodeKeywordValue("ca", calendar_str.get(), status);
......@@ -1555,12 +1572,17 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
if (hc != Intl::ToHourCycle(hc_extension_it->second.c_str())) {
// Remove -hc- if it does not agree with what we used.
UErrorCode status = U_ZERO_ERROR;
icu_locale.setUnicodeKeywordValue("hc", nullptr, status);
resolved_locale.setUnicodeKeywordValue("hc", nullptr, status);
CHECK(U_SUCCESS(status));
}
}
}
Maybe<std::string> maybe_locale_str = Intl::ToLanguageTag(resolved_locale);
MAYBE_RETURN(maybe_locale_str, MaybeHandle<JSDateTimeFormat>());
Handle<String> locale_str = isolate->factory()->NewStringFromAsciiChecked(
maybe_locale_str.FromJust().c_str());
Handle<Managed<icu::Locale>> managed_locale =
Managed<icu::Locale>::FromRawPtr(isolate, 0, icu_locale.clone());
......@@ -1587,6 +1609,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
(time_style == DateTimeStyle::kUndefined)) {
date_time_format->set_hour_cycle(hc);
}
date_time_format->set_locale(*locale_str);
date_time_format->set_icu_locale(*managed_locale);
date_time_format->set_icu_simple_date_format(*managed_format);
date_time_format->set_icu_date_interval_format(*managed_interval_format);
......
......@@ -133,6 +133,7 @@ class JSDateTimeFormat : public JSObject {
STATIC_ASSERT(DateTimeStyle::kMedium <= TimeStyleBits::kMax);
STATIC_ASSERT(DateTimeStyle::kShort <= TimeStyleBits::kMax);
DECL_ACCESSORS(locale, String)
DECL_ACCESSORS(icu_locale, Managed<icu::Locale>)
DECL_ACCESSORS(icu_simple_date_format, Managed<icu::SimpleDateFormat>)
DECL_ACCESSORS(icu_date_interval_format, Managed<icu::DateIntervalFormat>)
......
......@@ -21,6 +21,7 @@ namespace internal {
OBJECT_CONSTRUCTORS_IMPL(JSNumberFormat, JSObject)
ACCESSORS(JSNumberFormat, locale, String, kLocaleOffset)
ACCESSORS(JSNumberFormat, numberingSystem, String, kNumberingSystemOffset)
ACCESSORS(JSNumberFormat, icu_number_formatter,
Managed<icu::number::LocalizedNumberFormatter>,
kIcuNumberFormatterOffset)
......
......@@ -654,12 +654,8 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
Handle<JSObject> options = factory->NewJSObject(isolate->object_function());
Handle<String> locale = Handle<String>(number_format->locale(), isolate);
std::unique_ptr<char[]> locale_str = locale->ToCString();
icu::Locale icu_locale = Intl::CreateICULocale(locale_str.get());
std::string numbering_system = Intl::GetNumberingSystem(icu_locale);
Handle<String> numberingSystem =
Handle<String>(number_format->numberingSystem(), isolate);
// 5. For each row of Table 4, except the header row, in table order, do
// Table 4: Resolved Options of NumberFormat Instances
// Internal Slot Property
......@@ -678,13 +674,10 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
factory->locale_string(), locale,
Just(kDontThrow))
.FromJust());
if (!numbering_system.empty()) {
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->numberingSystem_string(),
factory->NewStringFromAsciiChecked(numbering_system.c_str()),
Just(kDontThrow))
.FromJust());
}
CHECK(JSReceiver::CreateDataProperty(isolate, options,
factory->numberingSystem_string(),
numberingSystem, Just(kDontThrow))
.FromJust());
JSNumberFormat::Style style = number_format->style();
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->style_string(),
......@@ -866,23 +859,37 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
Intl::ResolveLocale(isolate, JSNumberFormat::GetAvailableLocales(),
requested_locales, matcher, relevant_extension_keys);
icu::Locale icu_locale = r.icu_locale;
UErrorCode status = U_ZERO_ERROR;
if (numbering_system_str != nullptr) {
auto nu_extension_it = r.extensions.find("nu");
if (nu_extension_it != r.extensions.end() &&
nu_extension_it->second != numbering_system_str.get()) {
icu_locale.setUnicodeKeywordValue("nu", nullptr, status);
CHECK(U_SUCCESS(status));
}
}
// 9. Set numberFormat.[[Locale]] to r.[[locale]].
Maybe<std::string> maybe_locale_str = Intl::ToLanguageTag(icu_locale);
MAYBE_RETURN(maybe_locale_str, MaybeHandle<JSNumberFormat>());
Handle<String> locale_str = isolate->factory()->NewStringFromAsciiChecked(
maybe_locale_str.FromJust().c_str());
if (numbering_system_str != nullptr &&
Intl::IsValidNumberingSystem(numbering_system_str.get())) {
r.icu_locale.setUnicodeKeywordValue("nu", numbering_system_str.get(),
status);
icu_locale.setUnicodeKeywordValue("nu", numbering_system_str.get(), status);
CHECK(U_SUCCESS(status));
r.locale = Intl::ToLanguageTag(r.icu_locale).FromJust();
}
// 9. Set numberFormat.[[Locale]] to r.[[locale]].
Handle<String> locale_str =
isolate->factory()->NewStringFromAsciiChecked(r.locale.c_str());
Handle<String> numberingSystem_str =
isolate->factory()->NewStringFromAsciiChecked(
Intl::GetNumberingSystem(icu_locale).c_str());
// 11. Let dataLocale be r.[[dataLocale]].
icu::number::LocalizedNumberFormatter icu_number_formatter =
icu::number::NumberFormatter::withLocale(r.icu_locale)
icu::number::NumberFormatter::withLocale(icu_locale)
.roundingMode(UNUM_ROUND_HALFUP);
// 12. Let style be ? GetOption(options, "style", "string", « "decimal",
......@@ -1178,6 +1185,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
number_format->set_flags(0);
number_format->set_style(style);
number_format->set_locale(*locale_str);
number_format->set_numberingSystem(*numberingSystem_str);
number_format->set_icu_number_formatter(*managed_number_formatter);
number_format->set_bound_format(*factory->undefined_value());
......
......@@ -97,6 +97,7 @@ class JSNumberFormat : public JSObject {
STATIC_ASSERT(Style::UNIT <= StyleBits::kMax);
DECL_ACCESSORS(locale, String)
DECL_ACCESSORS(numberingSystem, String)
DECL_ACCESSORS(icu_number_formatter,
Managed<icu::number::LocalizedNumberFormatter>)
DECL_ACCESSORS(bound_format, Object)
......
......@@ -22,6 +22,7 @@ OBJECT_CONSTRUCTORS_IMPL(JSRelativeTimeFormat, JSObject)
// Base relative time format accessors.
ACCESSORS(JSRelativeTimeFormat, locale, String, kLocaleOffset)
ACCESSORS(JSRelativeTimeFormat, numberingSystem, String, kNumberingSystemOffset)
ACCESSORS(JSRelativeTimeFormat, icu_formatter,
Managed<icu::RelativeDateTimeFormatter>, kIcuFormatterOffset)
SMI_ACCESSORS(JSRelativeTimeFormat, flags, kFlagsOffset)
......
......@@ -107,24 +107,38 @@ MaybeHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::New(
Intl::ResolveLocale(isolate, JSRelativeTimeFormat::GetAvailableLocales(),
requested_locales, matcher, {"nu"});
UErrorCode status = U_ZERO_ERROR;
icu::Locale icu_locale = r.icu_locale;
if (numbering_system_str != nullptr) {
auto nu_extension_it = r.extensions.find("nu");
if (nu_extension_it != r.extensions.end() &&
nu_extension_it->second != numbering_system_str.get()) {
icu_locale.setUnicodeKeywordValue("nu", nullptr, status);
CHECK(U_SUCCESS(status));
}
}
// 12. Let locale be r.[[Locale]].
Maybe<std::string> maybe_locale_str = Intl::ToLanguageTag(icu_locale);
MAYBE_RETURN(maybe_locale_str, MaybeHandle<JSRelativeTimeFormat>());
// 13. Set relativeTimeFormat.[[Locale]] to locale.
// 14. Let dataLocale be r.[[DataLocale]].
icu::Locale icu_locale = r.icu_locale;
UErrorCode status = U_ZERO_ERROR;
Handle<String> locale_str = isolate->factory()->NewStringFromAsciiChecked(
maybe_locale_str.FromJust().c_str());
// 14. Set relativeTimeFormat.[[NumberingSystem]] to r.[[nu]].
if (numbering_system_str != nullptr &&
Intl::IsValidNumberingSystem(numbering_system_str.get())) {
icu_locale.setUnicodeKeywordValue("nu", numbering_system_str.get(), status);
CHECK(U_SUCCESS(status));
}
Handle<String> numbering_system_string =
isolate->factory()->NewStringFromAsciiChecked(
Intl::GetNumberingSystem(icu_locale).c_str());
Maybe<std::string> maybe_locale_str = Intl::ToLanguageTag(icu_locale);
MAYBE_RETURN(maybe_locale_str, MaybeHandle<JSRelativeTimeFormat>());
Handle<String> locale_str = isolate->factory()->NewStringFromAsciiChecked(
maybe_locale_str.FromJust().c_str());
// 15. Let dataLocale be r.[[DataLocale]].
// 15. Let s be ? GetOption(options, "style", "string",
// 16. Let s be ? GetOption(options, "style", "string",
// «"long", "short", "narrow"», "long").
Maybe<Style> maybe_style = Intl::GetStringOption<Style>(
isolate, options, "style", "Intl.RelativeTimeFormat",
......@@ -133,7 +147,9 @@ MaybeHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::New(
MAYBE_RETURN(maybe_style, MaybeHandle<JSRelativeTimeFormat>());
Style style_enum = maybe_style.FromJust();
// 17. Let numeric be ? GetOption(options, "numeric", "string",
// 17. Set relativeTimeFormat.[[Style]] to s.
// 18. Let numeric be ? GetOption(options, "numeric", "string",
// «"always", "auto"», "always").
Maybe<Numeric> maybe_numeric = Intl::GetStringOption<Numeric>(
isolate, options, "numeric", "Intl.RelativeTimeFormat",
......@@ -141,7 +157,9 @@ MaybeHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::New(
MAYBE_RETURN(maybe_numeric, MaybeHandle<JSRelativeTimeFormat>());
Numeric numeric_enum = maybe_numeric.FromJust();
// 19. Let relativeTimeFormat.[[NumberFormat]] be
// 19. Set relativeTimeFormat.[[Numeric]] to numeric.
// 23. Let relativeTimeFormat.[[NumberFormat]] be
// ? Construct(%NumberFormat%, « nfLocale, nfOptions »).
icu::NumberFormat* number_format =
icu::NumberFormat::createInstance(icu_locale, UNUM_DECIMAL, status);
......@@ -170,25 +188,18 @@ MaybeHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::New(
Managed<icu::RelativeDateTimeFormatter>::FromRawPtr(isolate, 0,
icu_formatter);
// Now all properties are ready, so we can allocate the result object.
Handle<JSRelativeTimeFormat> relative_time_format_holder =
Handle<JSRelativeTimeFormat>::cast(
isolate->factory()->NewFastOrSlowJSObjectFromMap(map));
DisallowHeapAllocation no_gc;
relative_time_format_holder->set_flags(0);
relative_time_format_holder->set_locale(*locale_str);
// 16. Set relativeTimeFormat.[[Style]] to s.
relative_time_format_holder->set_numberingSystem(*numbering_system_string);
relative_time_format_holder->set_style(style_enum);
// 18. Set relativeTimeFormat.[[Numeric]] to numeric.
relative_time_format_holder->set_numeric(numeric_enum);
// 21. Set relativeTimeFormat.[[InitializedRelativeTimeFormat]] to true.
relative_time_format_holder->set_icu_formatter(*managed_formatter);
// 22. Return relativeTimeFormat.
// 25. Return relativeTimeFormat.
return relative_time_format_holder;
}
......@@ -197,18 +208,15 @@ Handle<JSObject> JSRelativeTimeFormat::ResolvedOptions(
Factory* factory = isolate->factory();
Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
Handle<String> locale(format_holder->locale(), isolate);
Handle<String> numberingSystem(format_holder->numberingSystem(), isolate);
JSObject::AddProperty(isolate, result, factory->locale_string(), locale,
NONE);
JSObject::AddProperty(isolate, result, factory->style_string(),
format_holder->StyleAsString(), NONE);
JSObject::AddProperty(isolate, result, factory->numeric_string(),
format_holder->NumericAsString(), NONE);
std::string locale_str(format_holder->locale().ToCString().get());
icu::Locale icu_locale = Intl::CreateICULocale(locale_str);
std::string numbering_system = Intl::GetNumberingSystem(icu_locale);
JSObject::AddProperty(
isolate, result, factory->numberingSystem_string(),
factory->NewStringFromAsciiChecked(numbering_system.c_str()), NONE);
JSObject::AddProperty(isolate, result, factory->numberingSystem_string(),
numberingSystem, NONE);
return result;
}
......
......@@ -58,6 +58,7 @@ class JSRelativeTimeFormat : public JSObject {
// RelativeTimeFormat accessors.
DECL_ACCESSORS(locale, String)
DECL_ACCESSORS(numberingSystem, String)
DECL_ACCESSORS(icu_formatter, Managed<icu::RelativeDateTimeFormatter>)
......
......@@ -67,7 +67,7 @@ validCalendar.forEach(function(calendar) {
locales.forEach(function(base) {
let l = base + "-u-ca-" + calendar;
let dtf = new Intl.DateTimeFormat([base], {calendar});
assertEquals(l, dtf.resolvedOptions().locale);
assertEquals(base, dtf.resolvedOptions().locale);
// Test the formatting result is the same as passing in via u-ca-
// in the locale.
......
......@@ -74,7 +74,7 @@ validNumberingSystem.forEach(function(numberingSystem) {
locales.forEach(function(base) {
let l = base + "-u-nu-" + numberingSystem;
let dtf = new Intl.DateTimeFormat([base], {numberingSystem});
assertEquals(l, dtf.resolvedOptions().locale);
assertEquals(base, dtf.resolvedOptions().locale);
assertEquals(numberingSystem, dtf.resolvedOptions().numberingSystem);
// Test the formatting result is the same as passing in via u-nu-
......
......@@ -75,7 +75,7 @@ validNumberingSystem.forEach(function(numberingSystem) {
locales.forEach(function(base) {
let l = base + "-u-nu-" + numberingSystem;
let nf = new Intl.NumberFormat([base], {numberingSystem});
assertEquals(l, nf.resolvedOptions().locale);
assertEquals(base, nf.resolvedOptions().locale);
assertEquals(numberingSystem, nf.resolvedOptions().numberingSystem);
// Test the formatting result is the same as passing in via u-nu-
......
// Copyright 2019 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-add-calendar-numbering-system
let intlClasses = [
Intl.RelativeTimeFormat,
Intl.NumberFormat,
Intl.DateTimeFormat
];
// Check "nu" on Intl.RelativeTimeFormat, Intl.NumberFormat and
// Intl.DateTimeFormat
intlClasses.forEach(function(cls) {
let o1 = (new cls("en")).resolvedOptions();
assertEquals('latn', o1.numberingSystem);
let o2 = (new cls("en-u-nu-arab")).resolvedOptions();
assertEquals("arab", o2.numberingSystem);
assertEquals("en-u-nu-arab", o2.locale);
let o3 = (new cls(
"en-u-nu-arab", {numberingSystem: 'thai'})).resolvedOptions();
assertEquals("thai", o3.numberingSystem);
assertEquals("en", o3.locale);
let o4 = (new cls(
"en", {numberingSystem: 'bali'})).resolvedOptions();
assertEquals("bali", o4.numberingSystem);
assertEquals("en", o4.locale);
let o5 = (new cls("ar-SA")).resolvedOptions();
assertEquals('arab', o5.numberingSystem);
let o6 = (new cls(
"ar-SA-u-nu-arab", {numberingSystem: 'thai'})).resolvedOptions();
assertEquals("thai", o6.numberingSystem);
assertEquals("ar-SA", o6.locale);
let o7 = (new cls(
"ar-SA-u-nu-arab", {numberingSystem: 'arab'})).resolvedOptions();
assertEquals("arab", o7.numberingSystem);
assertEquals("ar-SA-u-nu-arab", o7.locale);
});
// Check "ca" on Intl.DateTimeFormat
cls = Intl.DateTimeFormat;
let o1 = (new cls("en")).resolvedOptions();
assertEquals('gregory', o1.calendar);
let o2 = (new cls("en-u-ca-roc")).resolvedOptions();
assertEquals("roc", o2.calendar);
assertEquals("en-u-ca-roc", o2.locale);
let o3 = (new cls(
"en-u-ca-roc", {calendar: 'chinese'})).resolvedOptions();
assertEquals("chinese", o3.calendar);
assertEquals("en", o3.locale);
let o4 = (new cls(
"en", {calendar: 'japanese'})).resolvedOptions();
assertEquals("japanese", o4.calendar);
assertEquals("en", o4.locale);
let o5 = (new cls("fa")).resolvedOptions();
assertEquals('persian', o5.calendar);
......@@ -73,7 +73,7 @@ validNumberingSystem.forEach(function(numberingSystem) {
locales.forEach(function(base) {
let l = base + "-u-nu-" + numberingSystem;
let nf = new Intl.RelativeTimeFormat([base], {numberingSystem});
assertEquals(l, nf.resolvedOptions().locale);
assertEquals(base, nf.resolvedOptions().locale);
assertEquals(numberingSystem, nf.resolvedOptions().numberingSystem);
// Test the formatting result is the same as passing in via u-nu-
......
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