From 43b229225288358a6b9a66402170346b005553bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Tue, 19 Apr 2016 10:00:01 +0200 Subject: [PATCH] deps: backport ddb5c2d from V8's upstream Original commit message: Make NumberFormat use the ICU currency data, fix bug in NumberFormat NumberFormat previously just used a min of 0 digits after the decimal and a max of 3. This CL changes it so that we use the ICU currency data, and set the min and max to the number of numbers after the decimal point for each currency. This CL also fixes a small bug where if the minimum fraction digits is above 3 but the maximum fraction digits isn't set, then it returns with only three numbers after the decimal point. BUG=435465,473104,304722 LOG=Y Review URL: https://codereview.chromium.org/1231613006 Cr-Commit-Position: refs/heads/master@{#29734} PR-URL: https://github.com/nodejs/node/pull/6275 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- deps/v8/AUTHORS | 1 + deps/v8/src/i18n.cc | 19 ++++++++++++++++++- deps/v8/src/i18n.js | 18 ++++++++++++------ .../check-minimum-fraction-digits.js | 9 +++++++++ .../intl/number-format/format-currency.js | 18 ++++++++++++++++++ 5 files changed, 58 insertions(+), 7 deletions(-) create mode 100755 deps/v8/test/intl/number-format/check-minimum-fraction-digits.js create mode 100755 deps/v8/test/intl/number-format/format-currency.js diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS index 4f853c275bc249..72c23bcc83e0b7 100644 --- a/deps/v8/AUTHORS +++ b/deps/v8/AUTHORS @@ -44,6 +44,7 @@ Bert Belder Burcu Dogan Caitlin Potter Craig Schlenter +Chris Nardi Christopher A. Taylor Daniel Andersson Daniel James diff --git a/deps/v8/src/i18n.cc b/deps/v8/src/i18n.cc index 1d735c97f1f048..c10890e89e5937 100644 --- a/deps/v8/src/i18n.cc +++ b/deps/v8/src/i18n.cc @@ -258,7 +258,24 @@ icu::DecimalFormat* CreateICUNumberFormat( #endif number_format = static_cast( - icu::NumberFormat::createInstance(icu_locale, format_style, status)); + icu::NumberFormat::createInstance(icu_locale, format_style, status)); + + if (U_FAILURE(status)) { + delete number_format; + return NULL; + } + + UErrorCode status_digits = U_ZERO_ERROR; + uint32_t fraction_digits = ucurr_getDefaultFractionDigits( + currency.getTerminatedBuffer(), &status_digits); + if (U_SUCCESS(status_digits)) { + number_format->setMinimumFractionDigits(fraction_digits); + number_format->setMaximumFractionDigits(fraction_digits); + } else { + // Set min & max to default values (previously in i18n.js) + number_format->setMinimumFractionDigits(0); + number_format->setMaximumFractionDigits(3); + } } else if (style == UNICODE_STRING_SIMPLE("percent")) { number_format = static_cast( icu::NumberFormat::createPercentInstance(icu_locale, status)); diff --git a/deps/v8/src/i18n.js b/deps/v8/src/i18n.js index 79e988062e9425..a0d985ad33ac66 100644 --- a/deps/v8/src/i18n.js +++ b/deps/v8/src/i18n.js @@ -1099,11 +1099,19 @@ function initializeNumberFormat(numberFormat, locales, options) { var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1); defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid); - var mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0); - defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd); + var mnfd = options['minimumFractionDigits']; + var mxfd = options['maximumFractionDigits']; + if (!IS_UNDEFINED(mnfd) || !internalOptions.style === 'currency') { + mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0); + defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd); + } - var mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20, 3); - defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd); + if (!IS_UNDEFINED(mxfd) || !internalOptions.style === 'currency') { + mnfd = IS_UNDEFINED(mnfd) ? 0 : mnfd; + fallback_limit = (mnfd > 3) ? mnfd : 3; + mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20, fallback_limit); + defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd); + } var mnsd = options['minimumSignificantDigits']; var mxsd = options['maximumSignificantDigits']; @@ -1157,8 +1165,6 @@ function initializeNumberFormat(numberFormat, locales, options) { internalOptions, resolved); - // We can't get information about number or currency style from ICU, so we - // assume user request was fulfilled. if (internalOptions.style === 'currency') { ObjectDefineProperty(resolved, 'currencyDisplay', {value: currencyDisplay, writable: true}); diff --git a/deps/v8/test/intl/number-format/check-minimum-fraction-digits.js b/deps/v8/test/intl/number-format/check-minimum-fraction-digits.js new file mode 100755 index 00000000000000..57e65be55e2252 --- /dev/null +++ b/deps/v8/test/intl/number-format/check-minimum-fraction-digits.js @@ -0,0 +1,9 @@ +// Copyright 2015 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. + +// Make sure minimumFractionDigits is honored + +var nf = new Intl.NumberFormat("en-us",{ useGrouping: false, minimumFractionDigits: 4}); + +assertEquals("12345.6789", nf.format(12345.6789)); diff --git a/deps/v8/test/intl/number-format/format-currency.js b/deps/v8/test/intl/number-format/format-currency.js new file mode 100755 index 00000000000000..4a8db4e7d5851b --- /dev/null +++ b/deps/v8/test/intl/number-format/format-currency.js @@ -0,0 +1,18 @@ +// Copyright 2015 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. + +// Make sure currency formatting is correct (for USD only displays two decimal +// places, for JPY 0, and for EUR 2). + +var nf_USD = new Intl.NumberFormat(['en'], {style: 'currency', currency: 'USD'}); + +assertEquals("$54,306.40", nf_USD.format(parseFloat(54306.4047970))); + +var nf_JPY = new Intl.NumberFormat(['ja'], {style: 'currency', currency: 'JPY'}); + +assertEquals("¥54,306", nf_JPY.format(parseFloat(54306.4047970))); + +var nf_EUR = new Intl.NumberFormat(['pt'], {style: 'currency', currency: 'EUR'}); + +assertEquals("€1.000,00", nf_EUR.format(1000.00));