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

Reland "[intl] Fix consistency in Intl API"

This is a reland of a1e6efd8

Fix Android issue by checking the resources is not filtering out.

Original change's description:
> [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: Shu-yu Guo <syg@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#77242}

Bug: v8:12209
Change-Id: I96e1ba33e97f6a4abbe20e23a8fdff6cdf8bc131
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3207380Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Commit-Queue: Frank Tang <ftang@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77290}
parent 4413ae63
......@@ -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
......
......@@ -433,7 +433,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";
}
......@@ -2009,19 +2011,62 @@ MaybeHandle<JSArray> VectorToJSArray(Isolate* isolate,
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);
namespace {
class ResourceAvailableCurrencies {
public:
ResourceAvailableCurrencies() {
UErrorCode status = U_ZERO_ERROR;
UEnumeration* uenum =
ucurr_openISOCurrencies(UCURR_COMMON | UCURR_NON_DEPRECATED, &status);
DCHECK(U_SUCCESS(status));
const char* next = nullptr;
while (U_SUCCESS(status) &&
(next = uenum_next(uenum, 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;
AddIfAvailable(next);
}
// Work around the issue that we do support the following currency codes
// in DisplayNames but the ICU API is not reporting it.
AddIfAvailable("SVC");
AddIfAvailable("VES");
AddIfAvailable("XDR");
AddIfAvailable("XSU");
AddIfAvailable("ZWL");
std::sort(list_.begin(), list_.end());
uenum_close(uenum);
}
std::sort(array.begin(), array.end());
uenum_close(ids);
return VectorToJSArray(isolate, array);
const std::vector<std::string>& Get() const { return list_; }
void AddIfAvailable(const char* currency) {
icu::UnicodeString code(currency, -1, US_INV);
UErrorCode status = U_ZERO_ERROR;
int32_t len = 0;
const UChar* result =
ucurr_getName(code.getTerminatedBuffer(), "en", UCURR_LONG_NAME,
nullptr, &len, &status);
if (U_SUCCESS(status) &&
u_strcmp(result, code.getTerminatedBuffer()) != 0) {
list_.push_back(currency);
}
}
private:
std::vector<std::string> list_;
};
const std::vector<std::string>& GetAvailableCurrencies() {
static base::LazyInstance<ResourceAvailableCurrencies>::type
available_currencies = LAZY_INSTANCE_INITIALIZER;
return available_currencies.Pointer()->Get();
}
} // namespace
MaybeHandle<JSArray> AvailableCurrencies(Isolate* isolate) {
return VectorToJSArray(isolate, GetAvailableCurrencies());
}
MaybeHandle<JSArray> AvailableNumberingSystems(Isolate* isolate) {
......@@ -2194,7 +2239,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);
......
......@@ -329,13 +329,7 @@
'built-ins/RegExp/property-escapes/generated/XID_Start': [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