summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/js-number-format.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects/js-number-format.cc')
-rw-r--r--deps/v8/src/objects/js-number-format.cc129
1 files changed, 90 insertions, 39 deletions
diff --git a/deps/v8/src/objects/js-number-format.cc b/deps/v8/src/objects/js-number-format.cc
index 646cbed8e7..fda9a940d6 100644
--- a/deps/v8/src/objects/js-number-format.cc
+++ b/deps/v8/src/objects/js-number-format.cc
@@ -109,19 +109,20 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
// [[MinimumSignificantDigits]] "minimumSignificantDigits"
// [[MaximumSignificantDigits]] "maximumSignificantDigits"
// [[UseGrouping]] "useGrouping"
- CHECK(JSReceiver::CreateDataProperty(
- isolate, options, factory->locale_string(), locale, kDontThrow)
+ CHECK(JSReceiver::CreateDataProperty(isolate, options,
+ 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()),
- kDontThrow)
+ Just(kDontThrow))
.FromJust());
}
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->style_string(),
- number_format_holder->StyleAsString(), kDontThrow)
+ number_format_holder->StyleAsString(), Just(kDontThrow))
.FromJust());
if (number_format_holder->style() == Style::CURRENCY) {
icu::UnicodeString currency(number_format->getCurrency());
@@ -133,49 +134,49 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
reinterpret_cast<const uint16_t*>(currency.getBuffer()),
currency.length()))
.ToHandleChecked(),
- kDontThrow)
+ Just(kDontThrow))
.FromJust());
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->currencyDisplay_string(),
- number_format_holder->CurrencyDisplayAsString(), kDontThrow)
+ number_format_holder->CurrencyDisplayAsString(), Just(kDontThrow))
.FromJust());
}
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->minimumIntegerDigits_string(),
factory->NewNumberFromInt(number_format->getMinimumIntegerDigits()),
- kDontThrow)
+ Just(kDontThrow))
.FromJust());
CHECK(
JSReceiver::CreateDataProperty(
isolate, options, factory->minimumFractionDigits_string(),
factory->NewNumberFromInt(number_format->getMinimumFractionDigits()),
- kDontThrow)
+ Just(kDontThrow))
.FromJust());
CHECK(
JSReceiver::CreateDataProperty(
isolate, options, factory->maximumFractionDigits_string(),
factory->NewNumberFromInt(number_format->getMaximumFractionDigits()),
- kDontThrow)
+ Just(kDontThrow))
.FromJust());
if (decimal_format->areSignificantDigitsUsed()) {
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->minimumSignificantDigits_string(),
factory->NewNumberFromInt(
decimal_format->getMinimumSignificantDigits()),
- kDontThrow)
+ Just(kDontThrow))
.FromJust());
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->maximumSignificantDigits_string(),
factory->NewNumberFromInt(
decimal_format->getMaximumSignificantDigits()),
- kDontThrow)
+ Just(kDontThrow))
.FromJust());
}
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->useGrouping_string(),
factory->ToBoolean((number_format->isGroupingUsed() == TRUE)),
- kDontThrow)
+ Just(kDontThrow))
.FromJust());
return options;
}
@@ -461,10 +462,45 @@ Handle<String> JSNumberFormat::CurrencyDisplayAsString() const {
}
}
-MaybeHandle<String> JSNumberFormat::FormatNumber(
- Isolate* isolate, const icu::NumberFormat& number_format, double number) {
+namespace {
+Maybe<icu::UnicodeString> IcuFormatNumber(
+ Isolate* isolate, const icu::NumberFormat& number_format,
+ Handle<Object> numeric_obj, icu::FieldPositionIterator* fp_iter) {
icu::UnicodeString result;
- number_format.format(number, result);
+ // If it is BigInt, handle it differently.
+ UErrorCode status = U_ZERO_ERROR;
+ if (numeric_obj->IsBigInt()) {
+ Handle<BigInt> big_int = Handle<BigInt>::cast(numeric_obj);
+ Handle<String> big_int_string;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, big_int_string,
+ BigInt::ToString(isolate, big_int),
+ Nothing<icu::UnicodeString>());
+ number_format.format(
+ {big_int_string->ToCString().get(), big_int_string->length()}, result,
+ fp_iter, status);
+ } else {
+ double number = numeric_obj->Number();
+ number_format.format(number, result, fp_iter, status);
+ }
+ if (U_FAILURE(status)) {
+ THROW_NEW_ERROR_RETURN_VALUE(isolate,
+ NewTypeError(MessageTemplate::kIcuError),
+ Nothing<icu::UnicodeString>());
+ }
+ return Just(result);
+}
+
+} // namespace
+
+MaybeHandle<String> JSNumberFormat::FormatNumeric(
+ Isolate* isolate, const icu::NumberFormat& number_format,
+ Handle<Object> numeric_obj) {
+ DCHECK(numeric_obj->IsNumeric());
+
+ Maybe<icu::UnicodeString> maybe_format =
+ IcuFormatNumber(isolate, number_format, numeric_obj, nullptr);
+ MAYBE_RETURN(maybe_format, Handle<String>());
+ icu::UnicodeString result = maybe_format.FromJust();
return isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(result.getBuffer()), result.length()));
@@ -490,13 +526,22 @@ bool cmp_NumberFormatSpan(const NumberFormatSpan& a,
// The list comes from third_party/icu/source/i18n/unicode/unum.h.
// They're mapped to NumberFormat part types mentioned throughout
// https://tc39.github.io/ecma402/#sec-partitionnumberpattern .
-Handle<String> IcuNumberFieldIdToNumberType(int32_t field_id, double number,
+Handle<String> IcuNumberFieldIdToNumberType(int32_t field_id,
+ Handle<Object> numeric_obj,
Isolate* isolate) {
+ DCHECK(numeric_obj->IsNumeric());
switch (static_cast<UNumberFormatFields>(field_id)) {
case UNUM_INTEGER_FIELD:
- if (std::isfinite(number)) return isolate->factory()->integer_string();
- if (std::isnan(number)) return isolate->factory()->nan_string();
- return isolate->factory()->infinity_string();
+ if (numeric_obj->IsBigInt()) {
+ // Neither NaN nor Infinite could be stored into BigInt
+ // so just return integer.
+ return isolate->factory()->integer_string();
+ } else {
+ double number = numeric_obj->Number();
+ if (std::isfinite(number)) return isolate->factory()->integer_string();
+ if (std::isnan(number)) return isolate->factory()->nan_string();
+ return isolate->factory()->infinity_string();
+ }
case UNUM_FRACTION_FIELD:
return isolate->factory()->fraction_string();
case UNUM_DECIMAL_SEPARATOR_FIELD:
@@ -508,9 +553,15 @@ Handle<String> IcuNumberFieldIdToNumberType(int32_t field_id, double number,
case UNUM_PERCENT_FIELD:
return isolate->factory()->percentSign_string();
case UNUM_SIGN_FIELD:
- return number < 0 ? isolate->factory()->minusSign_string()
- : isolate->factory()->plusSign_string();
-
+ if (numeric_obj->IsBigInt()) {
+ Handle<BigInt> big_int = Handle<BigInt>::cast(numeric_obj);
+ return big_int->IsNegative() ? isolate->factory()->minusSign_string()
+ : isolate->factory()->plusSign_string();
+ } else {
+ double number = numeric_obj->Number();
+ return number < 0 ? isolate->factory()->minusSign_string()
+ : isolate->factory()->plusSign_string();
+ }
case UNUM_EXPONENT_SYMBOL_FIELD:
case UNUM_EXPONENT_SIGN_FIELD:
case UNUM_EXPONENT_FIELD:
@@ -625,16 +676,15 @@ std::vector<NumberFormatSpan> FlattenRegionsToParts(
Maybe<int> JSNumberFormat::FormatToParts(Isolate* isolate,
Handle<JSArray> result,
int start_index,
- const icu::NumberFormat& fmt,
- double number, Handle<String> unit) {
- icu::UnicodeString formatted;
+ const icu::NumberFormat& number_format,
+ Handle<Object> numeric_obj,
+ Handle<String> unit) {
+ DCHECK(numeric_obj->IsNumeric());
icu::FieldPositionIterator fp_iter;
- UErrorCode status = U_ZERO_ERROR;
- fmt.format(number, formatted, &fp_iter, status);
- if (U_FAILURE(status)) {
- THROW_NEW_ERROR_RETURN_VALUE(
- isolate, NewTypeError(MessageTemplate::kIcuError), Nothing<int>());
- }
+ Maybe<icu::UnicodeString> maybe_format =
+ IcuFormatNumber(isolate, number_format, numeric_obj, &fp_iter);
+ MAYBE_RETURN(maybe_format, Nothing<int>());
+ icu::UnicodeString formatted = maybe_format.FromJust();
int32_t length = formatted.length();
int index = start_index;
@@ -662,7 +712,7 @@ Maybe<int> JSNumberFormat::FormatToParts(Isolate* isolate,
Handle<String> field_type_string =
part.field_id == -1
? isolate->factory()->literal_string()
- : IcuNumberFieldIdToNumberType(part.field_id, number, isolate);
+ : IcuNumberFieldIdToNumberType(part.field_id, numeric_obj, isolate);
Handle<String> substring;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, substring,
@@ -681,7 +731,9 @@ Maybe<int> JSNumberFormat::FormatToParts(Isolate* isolate,
}
MaybeHandle<JSArray> JSNumberFormat::FormatToParts(
- Isolate* isolate, Handle<JSNumberFormat> number_format, double number) {
+ Isolate* isolate, Handle<JSNumberFormat> number_format,
+ Handle<Object> numeric_obj) {
+ CHECK(numeric_obj->IsNumeric());
Factory* factory = isolate->factory();
icu::NumberFormat* fmt = number_format->icu_number_format()->raw();
CHECK_NOT_NULL(fmt);
@@ -689,17 +741,16 @@ MaybeHandle<JSArray> JSNumberFormat::FormatToParts(
Handle<JSArray> result = factory->NewJSArray(0);
Maybe<int> maybe_format_to_parts = JSNumberFormat::FormatToParts(
- isolate, result, 0, *fmt, number, Handle<String>());
+ isolate, result, 0, *fmt, numeric_obj, Handle<String>());
MAYBE_RETURN(maybe_format_to_parts, Handle<JSArray>());
return result;
}
-std::set<std::string> JSNumberFormat::GetAvailableLocales() {
- int32_t num_locales = 0;
- const icu::Locale* icu_available_locales =
- icu::NumberFormat::getAvailableLocales(num_locales);
- return Intl::BuildLocaleSet(icu_available_locales, num_locales);
+const std::set<std::string>& JSNumberFormat::GetAvailableLocales() {
+ static base::LazyInstance<Intl::AvailableLocales<icu::NumberFormat>>::type
+ available_locales = LAZY_INSTANCE_INITIALIZER;
+ return available_locales.Pointer()->Get();
}
} // namespace internal