[Intl] Change order of "currency" and "unit" validation.
Fix changes caused by pull/75 Fix skeleton to unit code which missed the case of ...-per-percent. https://github.com/tc39/proposal-unified-intl-numberformat/pull/75 Bug: v8:10112 Change-Id: I06f4668894c95234f36944cf3dcf2b8dbafb8b8c Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2032713 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Frank Tang <ftang@chromium.org> Cr-Commit-Position: refs/heads/master@{#66073}
This commit is contained in:
parent
d9d43b62c2
commit
880b28e4e1
@ -553,13 +553,13 @@ namespace {
|
||||
std::string UnitFromSkeleton(const icu::UnicodeString& skeleton) {
|
||||
std::string str;
|
||||
str = skeleton.toUTF8String<std::string>(str);
|
||||
// Special case for "percent" first.
|
||||
if (str.find("percent") != str.npos) {
|
||||
return "percent";
|
||||
}
|
||||
std::string search("measure-unit/");
|
||||
size_t begin = str.find(search);
|
||||
if (begin == str.npos) {
|
||||
// Special case for "percent".
|
||||
if (str.find("percent") != str.npos) {
|
||||
return "percent";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
// Skip the type (ex: "length").
|
||||
@ -703,20 +703,20 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
|
||||
.FromJust());
|
||||
}
|
||||
|
||||
if (style == JSNumberFormat::Style::UNIT) {
|
||||
std::string unit = UnitFromSkeleton(skeleton);
|
||||
if (!unit.empty()) {
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->unit_string(),
|
||||
isolate->factory()->NewStringFromAsciiChecked(unit.c_str()),
|
||||
Just(kDontThrow))
|
||||
.FromJust());
|
||||
}
|
||||
if (style == JSNumberFormat::Style::UNIT) {
|
||||
std::string unit = UnitFromSkeleton(skeleton);
|
||||
if (!unit.empty()) {
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->unitDisplay_string(),
|
||||
UnitDisplayString(isolate, skeleton), Just(kDontThrow))
|
||||
isolate, options, factory->unit_string(),
|
||||
isolate->factory()->NewStringFromAsciiChecked(unit.c_str()),
|
||||
Just(kDontThrow))
|
||||
.FromJust());
|
||||
}
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->unitDisplay_string(),
|
||||
UnitDisplayString(isolate, skeleton), Just(kDontThrow))
|
||||
.FromJust());
|
||||
}
|
||||
|
||||
CHECK(
|
||||
JSReceiver::CreateDataProperty(
|
||||
@ -894,7 +894,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
|
||||
icu::number::NumberFormatter::withLocale(icu_locale)
|
||||
.roundingMode(UNUM_ROUND_HALFUP);
|
||||
|
||||
// 12. Let style be ? GetOption(options, "style", "string", « "decimal",
|
||||
// 3. Let style be ? GetOption(options, "style", "string", « "decimal",
|
||||
// "percent", "currency", "unit" », "decimal").
|
||||
|
||||
Maybe<JSNumberFormat::Style> maybe_style =
|
||||
@ -907,9 +907,9 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
|
||||
MAYBE_RETURN(maybe_style, MaybeHandle<JSNumberFormat>());
|
||||
JSNumberFormat::Style style = maybe_style.FromJust();
|
||||
|
||||
// 13. Set numberFormat.[[Style]] to style.
|
||||
// 4. Set intlObj.[[Style]] to style.
|
||||
|
||||
// 14. Let currency be ? GetOption(options, "currency", "string", undefined,
|
||||
// 5. Let currency be ? GetOption(options, "currency", "string", undefined,
|
||||
// undefined).
|
||||
std::unique_ptr<char[]> currency_cstr;
|
||||
const std::vector<const char*> empty_values = {};
|
||||
@ -918,11 +918,11 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
|
||||
MAYBE_RETURN(found_currency, MaybeHandle<JSNumberFormat>());
|
||||
|
||||
std::string currency;
|
||||
// 15. If currency is not undefined, then
|
||||
// 6. If currency is not undefined, then
|
||||
if (found_currency.FromJust()) {
|
||||
DCHECK_NOT_NULL(currency_cstr.get());
|
||||
currency = currency_cstr.get();
|
||||
// 15. a. If the result of IsWellFormedCurrencyCode(currency) is false,
|
||||
// 6. a. If the result of IsWellFormedCurrencyCode(currency) is false,
|
||||
// throw a RangeError exception.
|
||||
if (!IsWellFormedCurrencyCode(currency)) {
|
||||
THROW_NEW_ERROR(
|
||||
@ -934,25 +934,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
|
||||
}
|
||||
}
|
||||
|
||||
// 16. If style is "currency" and currency is undefined, throw a TypeError
|
||||
// exception.
|
||||
if (style == JSNumberFormat::Style::CURRENCY && !found_currency.FromJust()) {
|
||||
THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kCurrencyCode),
|
||||
JSNumberFormat);
|
||||
}
|
||||
// 17. If style is "currency", then
|
||||
int c_digits = 0;
|
||||
icu::UnicodeString currency_ustr;
|
||||
if (style == JSNumberFormat::Style::CURRENCY) {
|
||||
// a. Let currency be the result of converting currency to upper case as
|
||||
// specified in 6.1
|
||||
std::transform(currency.begin(), currency.end(), currency.begin(), toupper);
|
||||
// c. Let cDigits be CurrencyDigits(currency).
|
||||
currency_ustr = currency.c_str();
|
||||
c_digits = CurrencyDigits(currency_ustr);
|
||||
}
|
||||
|
||||
// 18. Let currencyDisplay be ? GetOption(options, "currencyDisplay",
|
||||
// 7. Let currencyDisplay be ? GetOption(options, "currencyDisplay",
|
||||
// "string", « "code", "symbol", "name", "narrowSymbol" », "symbol").
|
||||
Maybe<CurrencyDisplay> maybe_currency_display =
|
||||
Intl::GetStringOption<CurrencyDisplay>(
|
||||
@ -965,7 +947,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
|
||||
CurrencyDisplay currency_display = maybe_currency_display.FromJust();
|
||||
|
||||
CurrencySign currency_sign = CurrencySign::STANDARD;
|
||||
// Let currencySign be ? GetOption(options, "currencySign", "string", «
|
||||
// 8. Let currencySign be ? GetOption(options, "currencySign", "string", «
|
||||
// "standard", "accounting" », "standard").
|
||||
Maybe<CurrencySign> maybe_currency_sign = Intl::GetStringOption<CurrencySign>(
|
||||
isolate, options, "currencySign", service, {"standard", "accounting"},
|
||||
@ -974,7 +956,8 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
|
||||
MAYBE_RETURN(maybe_currency_sign, MaybeHandle<JSNumberFormat>());
|
||||
currency_sign = maybe_currency_sign.FromJust();
|
||||
|
||||
// Let unit be ? GetOption(options, "unit", "string", undefined, undefined).
|
||||
// 9. Let unit be ? GetOption(options, "unit", "string", undefined,
|
||||
// undefined).
|
||||
std::unique_ptr<char[]> unit_cstr;
|
||||
Maybe<bool> found_unit = Intl::GetStringOption(
|
||||
isolate, options, "unit", empty_values, service, &unit_cstr);
|
||||
@ -985,8 +968,21 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
|
||||
DCHECK_NOT_NULL(unit_cstr.get());
|
||||
unit = unit_cstr.get();
|
||||
}
|
||||
// 10. If unit is not undefined, then
|
||||
// 10.a If the result of IsWellFormedUnitIdentifier(unit) is false, throw a
|
||||
// RangeError exception.
|
||||
Maybe<std::pair<icu::MeasureUnit, icu::MeasureUnit>> maybe_wellformed_unit =
|
||||
IsWellFormedUnitIdentifier(isolate, unit);
|
||||
if (found_unit.FromJust() && maybe_wellformed_unit.IsNothing()) {
|
||||
THROW_NEW_ERROR(
|
||||
isolate,
|
||||
NewRangeError(MessageTemplate::kInvalidUnit,
|
||||
factory->NewStringFromAsciiChecked(service),
|
||||
factory->NewStringFromAsciiChecked(unit.c_str())),
|
||||
JSNumberFormat);
|
||||
}
|
||||
|
||||
// Let unitDisplay be ? GetOption(options, "unitDisplay", "string", «
|
||||
// 11. Let unitDisplay be ? GetOption(options, "unitDisplay", "string", «
|
||||
// "short", "narrow", "long" », "short").
|
||||
Maybe<UnitDisplay> maybe_unit_display = Intl::GetStringOption<UnitDisplay>(
|
||||
isolate, options, "unitDisplay", service, {"short", "narrow", "long"},
|
||||
@ -995,9 +991,43 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
|
||||
MAYBE_RETURN(maybe_unit_display, MaybeHandle<JSNumberFormat>());
|
||||
UnitDisplay unit_display = maybe_unit_display.FromJust();
|
||||
|
||||
// If style is "unit", then
|
||||
// 12. If style is "currency", then
|
||||
icu::UnicodeString currency_ustr;
|
||||
if (style == JSNumberFormat::Style::CURRENCY) {
|
||||
// 12.a. If currency is undefined, throw a TypeError exception.
|
||||
if (!found_currency.FromJust()) {
|
||||
THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kCurrencyCode),
|
||||
JSNumberFormat);
|
||||
}
|
||||
// 12.b. Let currency be the result of converting currency to upper case as
|
||||
// specified in 6.1
|
||||
std::transform(currency.begin(), currency.end(), currency.begin(), toupper);
|
||||
currency_ustr = currency.c_str();
|
||||
|
||||
// 12.c. Set numberFormat.[[Currency]] to currency.
|
||||
if (!currency_ustr.isEmpty()) {
|
||||
Handle<String> currency_string;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, currency_string,
|
||||
Intl::ToString(isolate, currency_ustr),
|
||||
JSNumberFormat);
|
||||
|
||||
icu_number_formatter = icu_number_formatter.unit(
|
||||
icu::CurrencyUnit(currency_ustr.getBuffer(), status));
|
||||
CHECK(U_SUCCESS(status));
|
||||
// 12.d Set intlObj.[[CurrencyDisplay]] to currencyDisplay.
|
||||
// The default unitWidth is SHORT in ICU and that mapped from
|
||||
// Symbol so we can skip the setting for optimization.
|
||||
if (currency_display != CurrencyDisplay::SYMBOL) {
|
||||
icu_number_formatter = icu_number_formatter.unitWidth(
|
||||
ToUNumberUnitWidth(currency_display));
|
||||
}
|
||||
CHECK(U_SUCCESS(status));
|
||||
}
|
||||
}
|
||||
|
||||
// 13. If style is "unit", then
|
||||
if (style == JSNumberFormat::Style::UNIT) {
|
||||
// If unit is undefined, throw a TypeError exception.
|
||||
// 13.a If unit is undefined, throw a TypeError exception.
|
||||
if (unit == "") {
|
||||
THROW_NEW_ERROR(isolate,
|
||||
NewTypeError(MessageTemplate::kInvalidUnit,
|
||||
@ -1006,22 +1036,10 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
|
||||
JSNumberFormat);
|
||||
}
|
||||
|
||||
// If the result of IsWellFormedUnitIdentifier(unit) is false, throw a
|
||||
// RangeError exception.
|
||||
Maybe<std::pair<icu::MeasureUnit, icu::MeasureUnit>> maybe_wellformed =
|
||||
IsWellFormedUnitIdentifier(isolate, unit);
|
||||
if (maybe_wellformed.IsNothing()) {
|
||||
THROW_NEW_ERROR(
|
||||
isolate,
|
||||
NewRangeError(MessageTemplate::kInvalidUnit,
|
||||
factory->NewStringFromAsciiChecked(service),
|
||||
factory->NewStringFromAsciiChecked(unit.c_str())),
|
||||
JSNumberFormat);
|
||||
}
|
||||
std::pair<icu::MeasureUnit, icu::MeasureUnit> unit_pair =
|
||||
maybe_wellformed.FromJust();
|
||||
maybe_wellformed_unit.FromJust();
|
||||
|
||||
// Set intlObj.[[Unit]] to unit.
|
||||
// 13.b Set intlObj.[[Unit]] to unit.
|
||||
if (unit_pair.first != icu::NoUnit::base()) {
|
||||
icu_number_formatter = icu_number_formatter.unit(unit_pair.first);
|
||||
}
|
||||
@ -1042,35 +1060,13 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
|
||||
.scale(icu::number::Scale::powerOfTen(2));
|
||||
}
|
||||
|
||||
if (style == JSNumberFormat::Style::CURRENCY) {
|
||||
// 19. If style is "currency", set numberFormat.[[CurrencyDisplay]] to
|
||||
// currencyDisplay.
|
||||
|
||||
// 17.b. Set numberFormat.[[Currency]] to currency.
|
||||
if (!currency_ustr.isEmpty()) {
|
||||
Handle<String> currency_string;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, currency_string,
|
||||
Intl::ToString(isolate, currency_ustr),
|
||||
JSNumberFormat);
|
||||
|
||||
icu_number_formatter = icu_number_formatter.unit(
|
||||
icu::CurrencyUnit(currency_ustr.getBuffer(), status));
|
||||
CHECK(U_SUCCESS(status));
|
||||
// The default unitWidth is SHORT in ICU and that mapped from
|
||||
// Symbol so we can skip the setting for optimization.
|
||||
if (currency_display != CurrencyDisplay::SYMBOL) {
|
||||
icu_number_formatter = icu_number_formatter.unitWidth(
|
||||
ToUNumberUnitWidth(currency_display));
|
||||
}
|
||||
CHECK(U_SUCCESS(status));
|
||||
}
|
||||
}
|
||||
|
||||
// 23. If style is "currency", then
|
||||
int mnfd_default, mxfd_default;
|
||||
if (style == JSNumberFormat::Style::CURRENCY) {
|
||||
// a. Let mnfdDefault be cDigits.
|
||||
// b. Let mxfdDefault be cDigits.
|
||||
// b. Let cDigits be CurrencyDigits(currency).
|
||||
int c_digits = CurrencyDigits(currency_ustr);
|
||||
// c. Let mnfdDefault be cDigits.
|
||||
// d. Let mxfdDefault be cDigits.
|
||||
mnfd_default = c_digits;
|
||||
mxfd_default = c_digits;
|
||||
// 24. Else,
|
||||
|
@ -552,11 +552,6 @@
|
||||
'intl402/NumberFormat/prototype/formatToParts/signDisplay-ko-KR': [FAIL],
|
||||
'intl402/NumberFormat/prototype/formatToParts/signDisplay-zh-TW': [FAIL],
|
||||
|
||||
# Intl.NumberFormat constructor should throw RangeError
|
||||
# https://bugs.chromium.org/p/v8/issues/detail?id=10112
|
||||
'intl402/NumberFormat/constructor-order': [FAIL],
|
||||
'intl402/NumberFormat/constructor-unit': [FAIL],
|
||||
|
||||
######################## NEEDS INVESTIGATION ###########################
|
||||
|
||||
# https://bugs.chromium.org/p/v8/issues/detail?id=7833
|
||||
|
Loading…
Reference in New Issue
Block a user