[Intl] Only use DecimalFormat
Force to use locale with extension if the created NumberFormat is not a DecimalFormat. Check the dynamic class id. Guard DecimalFormat casting code Bug: v8:9035 Change-Id: Id32a3f652b93ddfca82f95f30ad2107b364ee7fc Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1536571 Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org> Commit-Queue: Frank Tang <ftang@chromium.org> Cr-Commit-Position: refs/heads/master@{#60452}
This commit is contained in:
parent
31d7e1d366
commit
7b2d7d4528
@ -83,9 +83,6 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
|
||||
icu::NumberFormat* number_format =
|
||||
number_format_holder->icu_number_format()->raw();
|
||||
CHECK_NOT_NULL(number_format);
|
||||
icu::DecimalFormat* decimal_format =
|
||||
static_cast<icu::DecimalFormat*>(number_format);
|
||||
CHECK_NOT_NULL(decimal_format);
|
||||
|
||||
Handle<String> locale =
|
||||
Handle<String>(number_format_holder->locale(), isolate);
|
||||
@ -159,6 +156,11 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
|
||||
factory->NewNumberFromInt(number_format->getMaximumFractionDigits()),
|
||||
Just(kDontThrow))
|
||||
.FromJust());
|
||||
CHECK(number_format->getDynamicClassID() ==
|
||||
icu::DecimalFormat::getStaticClassID());
|
||||
icu::DecimalFormat* decimal_format =
|
||||
static_cast<icu::DecimalFormat*>(number_format);
|
||||
CHECK_NOT_NULL(decimal_format);
|
||||
if (decimal_format->areSignificantDigitsUsed()) {
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->minimumSignificantDigits_string(),
|
||||
@ -335,22 +337,52 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
std::unique_ptr<icu::NumberFormat> icu_number_format;
|
||||
icu::Locale no_extension_locale(r.icu_locale.getBaseName());
|
||||
if (style == Style::DECIMAL) {
|
||||
icu_number_format.reset(
|
||||
icu::NumberFormat::createInstance(r.icu_locale, status));
|
||||
// If the subclass is not DecimalFormat, fallback to no extension
|
||||
// because other subclass has not support the format() with
|
||||
// FieldPositionIterator yet.
|
||||
if (U_FAILURE(status) || icu_number_format.get() == nullptr ||
|
||||
icu_number_format->getDynamicClassID() !=
|
||||
icu::DecimalFormat::getStaticClassID()) {
|
||||
status = U_ZERO_ERROR;
|
||||
icu_number_format.reset(
|
||||
icu::NumberFormat::createInstance(no_extension_locale, status));
|
||||
}
|
||||
} else if (style == Style::PERCENT) {
|
||||
icu_number_format.reset(
|
||||
icu::NumberFormat::createPercentInstance(r.icu_locale, status));
|
||||
// If the subclass is not DecimalFormat, fallback to no extension
|
||||
// because other subclass has not support the format() with
|
||||
// FieldPositionIterator yet.
|
||||
if (U_FAILURE(status) || icu_number_format.get() == nullptr ||
|
||||
icu_number_format->getDynamicClassID() !=
|
||||
icu::DecimalFormat::getStaticClassID()) {
|
||||
status = U_ZERO_ERROR;
|
||||
icu_number_format.reset(icu::NumberFormat::createPercentInstance(
|
||||
no_extension_locale, status));
|
||||
}
|
||||
} else {
|
||||
DCHECK_EQ(style, Style::CURRENCY);
|
||||
icu_number_format.reset(
|
||||
icu::NumberFormat::createInstance(r.icu_locale, format_style, status));
|
||||
// If the subclass is not DecimalFormat, fallback to no extension
|
||||
// because other subclass has not support the format() with
|
||||
// FieldPositionIterator yet.
|
||||
if (U_FAILURE(status) || icu_number_format.get() == nullptr ||
|
||||
icu_number_format->getDynamicClassID() !=
|
||||
icu::DecimalFormat::getStaticClassID()) {
|
||||
status = U_ZERO_ERROR;
|
||||
icu_number_format.reset(icu::NumberFormat::createInstance(
|
||||
no_extension_locale, format_style, status));
|
||||
}
|
||||
}
|
||||
|
||||
if (U_FAILURE(status) || icu_number_format.get() == nullptr) {
|
||||
status = U_ZERO_ERROR;
|
||||
// Remove extensions and try again.
|
||||
icu::Locale no_extension_locale(r.icu_locale.getBaseName());
|
||||
icu_number_format.reset(
|
||||
icu::NumberFormat::createInstance(no_extension_locale, status));
|
||||
|
||||
@ -360,6 +392,8 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
|
||||
}
|
||||
DCHECK(U_SUCCESS(status));
|
||||
CHECK_NOT_NULL(icu_number_format.get());
|
||||
CHECK(icu_number_format->getDynamicClassID() ==
|
||||
icu::DecimalFormat::getStaticClassID());
|
||||
if (style == Style::CURRENCY) {
|
||||
// 19. If style is "currency", set numberFormat.[[CurrencyDisplay]] to
|
||||
// currencyDisplay.
|
||||
@ -396,6 +430,8 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
|
||||
}
|
||||
// 22. Perform ? SetNumberFormatDigitOptions(numberFormat, options,
|
||||
// mnfdDefault, mxfdDefault).
|
||||
CHECK(icu_number_format->getDynamicClassID() ==
|
||||
icu::DecimalFormat::getStaticClassID());
|
||||
icu::DecimalFormat* icu_decimal_format =
|
||||
static_cast<icu::DecimalFormat*>(icu_number_format.get());
|
||||
Maybe<bool> maybe_set_number_for_digit_options =
|
||||
|
27
test/intl/regress-9035.js
Normal file
27
test/intl/regress-9035.js
Normal file
@ -0,0 +1,27 @@
|
||||
// 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.
|
||||
|
||||
// These Numbering Systems (nu) are listed in
|
||||
// http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/number.xml
|
||||
// with " — algorithmic" in the description but are NOT listed in
|
||||
// https://www.ecma-international.org/ecma-402/#table-numbering-system-digits
|
||||
// So there are no mandate to support these nu in a particular way.
|
||||
// Therefore in here we are only assure it won't throw exception in the
|
||||
// constructor and format method.
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-armn')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-armnlow')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-cyrl')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-ethi')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-geor')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-grek')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-greklow')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-hans')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-hansfin')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-hant')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-hantfin')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-hebr')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-jpanfin')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-roman')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-romanlow')).format(0));
|
||||
assertDoesNotThrow(() => (new Intl.NumberFormat('en-u-nu-taml')).format(0));
|
Loading…
Reference in New Issue
Block a user