Commit f0d37721 authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

[Intl] Change the behavior of percent format under "unit"

1. Sync with
https://github.com/tc39/proposal-unified-intl-numberformat/pull/57
so the formatting of {style: "unit" unit: "percent"} and
the formatting of {style: "percent:"} are treated different that
simplified the algorithm.
2. Store style into bit flags because we need it quickly during format.
3. Add more unit tests and regression test.

Bug: v8:9498
Change-Id: I75ed22fef1feb73ebf624bda70ebe45b80e7bc8b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1704948Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Commit-Queue: Frank Tang <ftang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62834}
parent cbbe0e22
...@@ -66,6 +66,17 @@ inline void JSNumberFormat::set_maximum_fraction_digits(int digits) { ...@@ -66,6 +66,17 @@ inline void JSNumberFormat::set_maximum_fraction_digits(int digits) {
set_flags(hints); set_flags(hints);
} }
inline void JSNumberFormat::set_style(Style style) {
DCHECK_GE(StyleBits::kMax, style);
int hints = flags();
hints = StyleBits::update(hints, style);
set_flags(hints);
}
inline JSNumberFormat::Style JSNumberFormat::style() const {
return StyleBits::decode(flags());
}
CAST_ACCESSOR(JSNumberFormat) CAST_ACCESSOR(JSNumberFormat)
} // namespace internal } // namespace internal
......
This diff is collapsed.
...@@ -92,6 +92,14 @@ class JSNumberFormat : public JSObject { ...@@ -92,6 +92,14 @@ class JSNumberFormat : public JSObject {
inline int maximum_fraction_digits() const; inline int maximum_fraction_digits() const;
inline void set_maximum_fraction_digits(int digits); inline void set_maximum_fraction_digits(int digits);
// [[Style]] is one of the values "decimal", "percent", "currency",
// or "unit" identifying the style of the number format.
// Note: "unit" is added in proposal-unified-intl-numberformat
enum class Style { DECIMAL, PERCENT, CURRENCY, UNIT };
inline void set_style(Style style);
inline Style style() const;
// Layout description. // Layout description.
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
TORQUE_GENERATED_JSNUMBER_FORMAT_FIELDS) TORQUE_GENERATED_JSNUMBER_FORMAT_FIELDS)
...@@ -99,13 +107,18 @@ class JSNumberFormat : public JSObject { ...@@ -99,13 +107,18 @@ class JSNumberFormat : public JSObject {
// Bit positions in |flags|. // Bit positions in |flags|.
#define FLAGS_BIT_FIELDS(V, _) \ #define FLAGS_BIT_FIELDS(V, _) \
V(MinimumFractionDigitsBits, int, 5, _) \ V(MinimumFractionDigitsBits, int, 5, _) \
V(MaximumFractionDigitsBits, int, 5, _) V(MaximumFractionDigitsBits, int, 5, _) \
V(StyleBits, Style, 2, _)
DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS) DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
#undef FLAGS_BIT_FIELDS #undef FLAGS_BIT_FIELDS
STATIC_ASSERT(20 <= MinimumFractionDigitsBits::kMax); STATIC_ASSERT(20 <= MinimumFractionDigitsBits::kMax);
STATIC_ASSERT(20 <= MaximumFractionDigitsBits::kMax); STATIC_ASSERT(20 <= MaximumFractionDigitsBits::kMax);
STATIC_ASSERT(Style::DECIMAL <= StyleBits::kMax);
STATIC_ASSERT(Style::PERCENT <= StyleBits::kMax);
STATIC_ASSERT(Style::CURRENCY <= StyleBits::kMax);
STATIC_ASSERT(Style::UNIT <= StyleBits::kMax);
DECL_ACCESSORS(locale, String) DECL_ACCESSORS(locale, String)
DECL_ACCESSORS(icu_number_formatter, DECL_ACCESSORS(icu_number_formatter,
......
// 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.
// Flags: --harmony-intl-numberformat-unified
//
// Test the handling of "percent" w/ "unit"
let nf1 = new Intl.NumberFormat("en-US", {
style: "percent",
unitDisplay: "long" // Read, but ignored.
});
let resolved1 = nf1.resolvedOptions();
assertEquals("percent", resolved1.style);
assertEquals(undefined, resolved1.unit);
assertEquals(undefined, resolved1.unitDisplay);
let parts1 = nf1.formatToParts(100);
assertEquals(4, parts1.length);
assertEquals("integer", parts1[0].type);
assertEquals("10", parts1[0].value);
assertEquals("group", parts1[1].type);
assertEquals(",", parts1[1].value);
assertEquals("integer", parts1[2].type);
assertEquals("000", parts1[2].value);
assertEquals("percentSign", parts1[3].type);
assertEquals("%", parts1[3].value);
let nf2 = new Intl.NumberFormat("en-US", {
style: "unit",
unit: "percent",
unitDisplay: "long" // This is OK
});
let resolved2 = nf2.resolvedOptions();
assertEquals("unit", resolved2.style);
assertEquals("percent", resolved2.unit);
assertEquals("long", resolved2.unitDisplay);
let parts2 = nf2.formatToParts(100);
assertEquals(3, parts2.length);
assertEquals("integer", parts2[0].type);
assertEquals("100", parts2[0].value);
assertEquals("literal", parts2[1].type);
assertEquals(" ", parts2[1].value);
assertEquals("unit", parts2[2].type);
assertEquals("percent", parts2[2].value);
let nf3 = new Intl.NumberFormat("en-US", {
style: "unit",
unit: "percent"
});
let resolved3 = nf3.resolvedOptions();
assertEquals("unit", resolved3.style);
assertEquals("percent", resolved3.unit);
assertEquals("short", resolved3.unitDisplay);
let parts3 = nf3.formatToParts(100);
assertEquals(2, parts3.length);
assertEquals("integer", parts3[0].type);
assertEquals("100", parts3[0].value);
assertEquals("unit", parts3[1].type);
assertEquals("%", parts3[1].value);
...@@ -19,7 +19,7 @@ nf = new Intl.NumberFormat("en", {style: 'currency', currency: 'TWD'}); ...@@ -19,7 +19,7 @@ nf = new Intl.NumberFormat("en", {style: 'currency', currency: 'TWD'});
assertEquals(undefined, nf.resolvedOptions().unit); assertEquals(undefined, nf.resolvedOptions().unit);
nf = new Intl.NumberFormat("en", {style: 'percent'}); nf = new Intl.NumberFormat("en", {style: 'percent'});
assertEquals('percent', nf.resolvedOptions().unit); assertEquals(undefined, nf.resolvedOptions().unit);
assertThrows(() => new Intl.NumberFormat("en", {style: 'unit'}), TypeError); assertThrows(() => new Intl.NumberFormat("en", {style: 'unit'}), TypeError);
......
...@@ -21,7 +21,7 @@ nf = new Intl.NumberFormat("en", {style: 'unit', unit: "meter"}); ...@@ -21,7 +21,7 @@ nf = new Intl.NumberFormat("en", {style: 'unit', unit: "meter"});
assertEquals("short", nf.resolvedOptions().unitDisplay); assertEquals("short", nf.resolvedOptions().unitDisplay);
nf = new Intl.NumberFormat("en", {style: 'percent'}); nf = new Intl.NumberFormat("en", {style: 'percent'});
assertEquals("short", nf.resolvedOptions().unitDisplay); assertEquals(undefined, nf.resolvedOptions().unitDisplay);
const testData = [ const testData = [
["short"], ["short"],
......
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