Commit a1e6efd8 authored by Frank Tang's avatar Frank Tang Committed by V8 LUCI CQ

[intl] Fix consistency in Intl API

Fix several edge cases consistency issues with ICU discovered by test262 test by
using Intl Enumeration API
1. Work around ICU short coming of always fallback in currency display
 name so when the fallback is "none" in DisplayNames, the force fallback
code will produce the correct undefined from the of(currency_code) method.
2. Always check numbering system is not algorithm based numbering system
to fix DateTimeFormat/RelativeTimeFormat/NumberFormat
resolvedOptions().numberingSystem when the reqested numberingSystem is one
of the numbering systems that we filter out the resources and not supported.
3. Generalize the iso8601 bit solution in DateTimeFormat and rename it to
alt_calendar bit to also fix DateTimeFormat resolvedOptions report
calendar as "islamic" while requesting "islamic-rgsa".
4. Work around reporting inconsistency of currency code and display name
in ICU.

Bug: v8:12209
Change-Id: Ibd349ee55426fad7d6f20a5e93fb35ff7438e111
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3153576
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77242}
parent 1dfb8cd7
......@@ -4579,7 +4579,7 @@ void Genesis::InitializeGlobal_harmony_intl_enumeration() {
.ToHandleChecked());
SimpleInstallFunction(isolate(), intl, "supportedValuesOf",
Builtin::kIntlSupportedValuesOf, 0, false);
Builtin::kIntlSupportedValuesOf, 1, false);
}
#endif // V8_INTL_SUPPORT
......
......@@ -429,7 +429,9 @@ std::string Intl::GetNumberingSystem(const icu::Locale& icu_locale) {
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::NumberingSystem> numbering_system(
icu::NumberingSystem::createInstance(icu_locale, status));
if (U_SUCCESS(status)) return numbering_system->getName();
if (U_SUCCESS(status) && !numbering_system->isAlgorithmic()) {
return numbering_system->getName();
}
return "latn";
}
......@@ -1570,8 +1572,18 @@ MaybeHandle<JSArray> AvailableCurrencies(Isolate* isolate) {
std::vector<std::string> array;
while (U_SUCCESS(status) &&
(next = uenum_next(ids, nullptr, &status)) != nullptr) {
// Work around the issue that we do not support VEF currency code
// in DisplayNames by not reporting it.
if (strcmp(next, "VEF") == 0) continue;
array.push_back(next);
}
// Work around the issue that we do support the following currency codes
// in DisplayNames but the ICU API does not reporting it.
array.push_back("SVC");
array.push_back("VES");
array.push_back("XDR");
array.push_back("XSU");
array.push_back("ZWL");
std::sort(array.begin(), array.end());
uenum_close(ids);
return VectorToJSArray(isolate, array);
......@@ -1747,7 +1759,8 @@ bool Intl::IsValidNumberingSystem(const std::string& value) {
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::NumberingSystem> numbering_system(
icu::NumberingSystem::createInstanceByName(value.c_str(), status));
return U_SUCCESS(status) && numbering_system.get() != nullptr;
return U_SUCCESS(status) && numbering_system.get() != nullptr &&
!numbering_system->isAlgorithmic();
}
namespace {
......
......@@ -28,7 +28,7 @@ ACCESSORS(JSDateTimeFormat, icu_simple_date_format,
ACCESSORS(JSDateTimeFormat, icu_date_interval_format,
Managed<icu::DateIntervalFormat>, kIcuDateIntervalFormatOffset)
BOOL_ACCESSORS(JSDateTimeFormat, flags, iso8601, Iso8601Bit::kShift)
BOOL_ACCESSORS(JSDateTimeFormat, flags, alt_calendar, AltCalendarBit::kShift)
inline void JSDateTimeFormat::set_hour_cycle(HourCycle hour_cycle) {
int hints = flags();
......
......@@ -526,13 +526,17 @@ MaybeHandle<JSObject> JSDateTimeFormat::ResolvedOptions(
// and
// http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/calendar.xml
if (calendar_str == "gregorian") {
if (date_time_format->iso8601()) {
if (date_time_format->alt_calendar()) {
calendar_str = "iso8601";
} else {
calendar_str = "gregory";
}
} else if (calendar_str == "ethiopic-amete-alem") {
calendar_str = "ethioaa";
} else if (calendar_str == "islamic") {
if (date_time_format->alt_calendar()) {
calendar_str = "islamic-rgsa";
}
}
const icu::TimeZone& tz = calendar->getTimeZone();
......@@ -1590,7 +1594,9 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
icu_locale.setUnicodeKeywordValue("ca", calendar_str.get(), status);
DCHECK(U_SUCCESS(status));
}
bool iso8601 = strstr(icu_locale.getName(), "calendar=iso8601") != nullptr;
bool alt_calendar =
strstr(icu_locale.getName(), "calendar=iso8601") != nullptr ||
strstr(icu_locale.getName(), "calendar=islamic-rgsa") != nullptr;
if (numbering_system_str != nullptr &&
Intl::IsValidNumberingSystem(numbering_system_str.get())) {
......@@ -1898,7 +1904,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
date_time_format->set_time_style(time_style);
}
date_time_format->set_hour_cycle(dateTimeFormatHourCycle);
date_time_format->set_iso8601(iso8601);
date_time_format->set_alt_calendar(alt_calendar);
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);
......
......@@ -127,7 +127,7 @@ class JSDateTimeFormat
DECL_ACCESSORS(icu_simple_date_format, Managed<icu::SimpleDateFormat>)
DECL_ACCESSORS(icu_date_interval_format, Managed<icu::DateIntervalFormat>)
DECL_BOOLEAN_ACCESSORS(iso8601)
DECL_BOOLEAN_ACCESSORS(alt_calendar)
DECL_PRINTER(JSDateTimeFormat)
......
......@@ -10,7 +10,14 @@ bitfield struct JSDateTimeFormatFlags extends uint31 {
hour_cycle: HourCycle: 3 bit;
date_style: DateTimeStyle: 3 bit;
time_style: DateTimeStyle: 3 bit;
iso8601: bool: 1bit;
// ICU report the same type "gregorian" for both "gregorian" calendar and
// "iso8601" calendar and the same type "islamic" for both "islamic" and
// "islamic-rgsa" calendar. We use the alt_calendar bit to distinguish between
// them. When the type is "gregorian" and the alt_calendar bit is set, it is
// "iso8601", otherwise the true "gregorian" calendar. While the type is
// "islamic" and the alt_calendar bit is set, it is "islamic-rgsa" calendar,
// otherwise "islamic" calendar.
alt_calendar: bool: 1bit;
}
extern class JSDateTimeFormat extends JSObject {
......
......@@ -119,8 +119,11 @@ class LanguageNames : public LocaleDisplayNamesCommon {
LanguageNames(const icu::Locale& locale, JSDisplayNames::Style style,
bool fallback, bool dialect)
: LocaleDisplayNamesCommon(locale, style, fallback, dialect) {}
~LanguageNames() override = default;
const char* type() const override { return "language"; }
Maybe<icu::UnicodeString> of(Isolate* isolate,
const char* code) const override {
UErrorCode status = U_ZERO_ERROR;
......@@ -153,8 +156,11 @@ class RegionNames : public LocaleDisplayNamesCommon {
RegionNames(const icu::Locale& locale, JSDisplayNames::Style style,
bool fallback, bool dialect)
: LocaleDisplayNamesCommon(locale, style, fallback, dialect) {}
~RegionNames() override = default;
const char* type() const override { return "region"; }
Maybe<icu::UnicodeString> of(Isolate* isolate,
const char* code) const override {
std::string code_str(code);
......@@ -175,8 +181,11 @@ class ScriptNames : public LocaleDisplayNamesCommon {
ScriptNames(const icu::Locale& locale, JSDisplayNames::Style style,
bool fallback, bool dialect)
: LocaleDisplayNamesCommon(locale, style, fallback, dialect) {}
~ScriptNames() override = default;
const char* type() const override { return "script"; }
Maybe<icu::UnicodeString> of(Isolate* isolate,
const char* code) const override {
std::string code_str(code);
......@@ -195,30 +204,47 @@ class ScriptNames : public LocaleDisplayNamesCommon {
class KeyValueDisplayNames : public LocaleDisplayNamesCommon {
public:
KeyValueDisplayNames(const icu::Locale& locale, JSDisplayNames::Style style,
bool fallback, bool dialect, const char* key)
: LocaleDisplayNamesCommon(locale, style, fallback, dialect), key_(key) {}
bool fallback, bool dialect, const char* key,
bool prevent_fallback)
: LocaleDisplayNamesCommon(locale, style, fallback, dialect),
key_(key),
prevent_fallback_(prevent_fallback) {}
~KeyValueDisplayNames() override = default;
const char* type() const override { return key_.c_str(); }
Maybe<icu::UnicodeString> of(Isolate* isolate,
const char* code) const override {
std::string code_str(code);
icu::UnicodeString result;
locale_display_names()->keyValueDisplayName(key_.c_str(), code_str.c_str(),
result);
// Work around the issue that the keyValueDisplayNames ignore no
// substituion and always fallback.
if (prevent_fallback_ && (result.length() == 3) &&
(code_str.length() == 3) &&
(result == icu::UnicodeString(code_str.c_str(), -1, US_INV))) {
result.setToBogus();
}
return Just(result);
}
private:
std::string key_;
bool prevent_fallback_;
};
class CurrencyNames : public KeyValueDisplayNames {
public:
CurrencyNames(const icu::Locale& locale, JSDisplayNames::Style style,
bool fallback, bool dialect)
: KeyValueDisplayNames(locale, style, fallback, dialect, "currency") {}
: KeyValueDisplayNames(locale, style, fallback, dialect, "currency",
fallback == false) {}
~CurrencyNames() override = default;
Maybe<icu::UnicodeString> of(Isolate* isolate,
const char* code) const override {
std::string code_str(code);
......@@ -235,8 +261,11 @@ class CalendarNames : public KeyValueDisplayNames {
public:
CalendarNames(const icu::Locale& locale, JSDisplayNames::Style style,
bool fallback, bool dialect)
: KeyValueDisplayNames(locale, style, fallback, dialect, "calendar") {}
: KeyValueDisplayNames(locale, style, fallback, dialect, "calendar",
false) {}
~CalendarNames() override = default;
Maybe<icu::UnicodeString> of(Isolate* isolate,
const char* code) const override {
std::string code_str(code);
......@@ -313,9 +342,13 @@ class DateTimeFieldNames : public DisplayNamesInternal {
icu::DateTimePatternGenerator::createInstance(locale_, status));
DCHECK(U_SUCCESS(status));
}
~DateTimeFieldNames() override = default;
const char* type() const override { return "dateTimeField"; }
icu::Locale locale() const override { return locale_; }
Maybe<icu::UnicodeString> of(Isolate* isolate,
const char* code) const override {
UDateTimePatternField field = StringToUDateTimePatternField(code);
......
......@@ -220,13 +220,7 @@
'intl402/NumberFormat/currency-digits': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=12209
'intl402/Intl/supportedValuesOf/calendars-accepted-by-DateTimeFormat': [FAIL],
'intl402/Intl/supportedValuesOf/collations-accepted-by-Collator': [FAIL],
'intl402/Intl/supportedValuesOf/currencies-accepted-by-DisplayNames': [FAIL],
'intl402/Intl/supportedValuesOf/length': [FAIL],
'intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-DateTimeFormat': [FAIL],
'intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-NumberFormat': [FAIL],
'intl402/Intl/supportedValuesOf/numberingSystems-accepted-by-RelativeTimeFormat': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=7831
'language/statements/generators/generator-created-after-decl-inst': [FAIL],
......
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