Commit 76f789c3 authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

[Intl] Fix crash bug of formatToParts and -0

1. Fix formatToParts show "plusSign" for -0 by using signbit instead of < 0
2. Fix crash bug of formatToParts while notation is either "engineering" or
   "scientific".

Bug: v8:9513
Change-Id: I36b0b995c157dc642b9c201694d0ac0bb0396988
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1710148
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62856}
parent 40624b5b
......@@ -29,14 +29,14 @@
V(_, endRange_string, "endRange") \
V(_, engineering_string, "engineering") \
V(_, era_string, "era") \
V(_, first_string, "first") \
V(_, format_string, "format") \
V(_, fractionalSecond_string, "fractionalSecond") \
V(_, exceptZero_string, "exceptZero") \
V(_, exponentInteger_string, "exponentInteger") \
V(_, exponentMinusSign_string, "exponentMinusSign") \
V(_, exponentSeparator_string, "exponentSeparator") \
V(_, first_string, "first") \
V(_, format_string, "format") \
V(_, fraction_string, "fraction") \
V(_, fractionalSecond_string, "fractionalSecond") \
V(_, fractionalSecondDigits_string, "fractionalSecondDigits") \
V(_, full_string, "full") \
V(_, granularity_string, "granularity") \
......
......@@ -2080,16 +2080,17 @@ Handle<String> Intl::NumberFieldToType(Isolate* isolate,
: isolate->factory()->plusSign_string();
} else {
double number = numeric_obj->Number();
return number < 0 ? isolate->factory()->minusSign_string()
: isolate->factory()->plusSign_string();
return std::signbit(number) ? isolate->factory()->minusSign_string()
: isolate->factory()->plusSign_string();
}
case UNUM_EXPONENT_SYMBOL_FIELD:
return isolate->factory()->exponentSeparator_string();
case UNUM_EXPONENT_SIGN_FIELD:
return isolate->factory()->exponentMinusSign_string();
case UNUM_EXPONENT_FIELD:
// We should never get these because we're not using any scientific
// formatter.
UNREACHABLE();
return Handle<String>();
return isolate->factory()->exponentInteger_string();
case UNUM_PERMILL_FIELD:
// We're not creating any permill formatter, and it's not even clear how
......
// 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 notation: "engineering" with formatToParts.
const nf = Intl.NumberFormat("en", {notation: "engineering"});
let parts = nf.formatToParts(123.456);
// [{type: "integer", value: "123"}, {type: "decimal", value: "."},
// {type: "fraction", value: "456"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "0"}]
assertEquals("integer", parts[0].type);
assertEquals("123", parts[0].value);
assertEquals("decimal", parts[1].type);
assertEquals(".", parts[1].value);
assertEquals("fraction", parts[2].type);
assertEquals("456", parts[2].value);
assertEquals("exponentSeparator", parts[3].type);
assertEquals("E", parts[3].value);
assertEquals("exponentInteger", parts[4].type);
assertEquals("0", parts[4].value);
assertEquals(5, parts.length);
parts = nf.formatToParts(-123.456);
// [{type: "minusSign", value: "-"}, {type: "integer", value: "123"},
// {type: "decimal", value: "."}, {type: "fraction", value: "456"},
// {type: "exponentSeparator", value: "E"}, {type: "exponentInteger", value: "0"}]
assertEquals("minusSign", parts[0].type);
assertEquals("-", parts[0].value);
assertEquals("integer", parts[1].type);
assertEquals("123", parts[1].value);
assertEquals("decimal", parts[2].type);
assertEquals(".", parts[2].value);
assertEquals("fraction", parts[3].type);
assertEquals("456", parts[3].value);
assertEquals("exponentSeparator", parts[4].type);
assertEquals("E", parts[4].value);
assertEquals("exponentInteger", parts[5].type);
assertEquals("0", parts[5].value);
assertEquals(6, parts.length);
parts = nf.formatToParts(12345678901234567890);
// [{type: "integer", value: "12"}, {type: "decimal", value: "."},
// {type: "fraction", value: "346"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "18"}]
assertEquals("integer", parts[0].type);
assertEquals("12", parts[0].value);
assertEquals("decimal", parts[1].type);
assertEquals(".", parts[1].value);
assertEquals("fraction", parts[2].type);
assertEquals("346", parts[2].value);
assertEquals("exponentSeparator", parts[3].type);
assertEquals("E", parts[3].value);
assertEquals("exponentInteger", parts[4].type);
assertEquals("18", parts[4].value);
assertEquals(5, parts.length);
parts = nf.formatToParts(-12345678901234567890);
// [{type: "minusSign", value: "-"}, {type: "integer", value: "12"},
// {type: "decimal", value: "."}, {type: "fraction", value: "346"},
// {type: "exponentSeparator", value: "E"}, {type: "exponentInteger", value: "18"}]
assertEquals("minusSign", parts[0].type);
assertEquals("-", parts[0].value);
assertEquals("integer", parts[1].type);
assertEquals("12", parts[1].value);
assertEquals("decimal", parts[2].type);
assertEquals(".", parts[2].value);
assertEquals("fraction", parts[3].type);
assertEquals("346", parts[3].value);
assertEquals("exponentSeparator", parts[4].type);
assertEquals("E", parts[4].value);
assertEquals("exponentInteger", parts[5].type);
assertEquals("18", parts[5].value);
assertEquals(6, parts.length);
parts = nf.formatToParts(0.000000000000123456);
// [{type: "integer", value: "123"}, {type: "decimal", value: "."},
// {type: "fraction", value: "456"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentMinusSign", value: "-"}, {type: "exponentInteger", value: "15"}]
assertEquals("integer", parts[0].type);
assertEquals("123", parts[0].value);
assertEquals("decimal", parts[1].type);
assertEquals(".", parts[1].value);
assertEquals("fraction", parts[2].type);
assertEquals("456", parts[2].value);
assertEquals("exponentSeparator", parts[3].type);
assertEquals("E", parts[3].value);
assertEquals("exponentMinusSign", parts[4].type);
assertEquals("-", parts[4].value);
assertEquals("exponentInteger", parts[5].type);
assertEquals("15", parts[5].value);
assertEquals(6, parts.length);
parts = nf.formatToParts(-0.000000000000123456);
// [{type: "minusSign", value: "-"}, {type: "integer", value: "123"},
// {type: "decimal", value: "."}, {type: "fraction", value: "456"},
// {type: "exponentSeparator", value: "E"},
// {type: "exponentMinusSign", value: "-"}, {type: "exponentInteger", value: "15"}]
assertEquals("minusSign", parts[0].type);
assertEquals("-", parts[0].value);
assertEquals("integer", parts[1].type);
assertEquals("123", parts[1].value);
assertEquals("decimal", parts[2].type);
assertEquals(".", parts[2].value);
assertEquals("fraction", parts[3].type);
assertEquals("456", parts[3].value);
assertEquals("exponentSeparator", parts[4].type);
assertEquals("E", parts[4].value);
assertEquals("exponentMinusSign", parts[5].type);
assertEquals("-", parts[5].value);
assertEquals("exponentInteger", parts[6].type);
assertEquals("15", parts[6].value);
assertEquals(7, parts.length);
parts = nf.formatToParts(0);
// [{type: "integer", value: "0"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "0"}]
assertEquals("integer", parts[0].type);
assertEquals("0", parts[0].value);
assertEquals("exponentSeparator", parts[1].type);
assertEquals("E", parts[1].value);
assertEquals("exponentInteger", parts[2].type);
assertEquals("0", parts[2].value);
assertEquals(3, parts.length);
parts = nf.formatToParts(-0);
// [{type: "minusSign", value: "-"}, {type: "integer", value: "0"},
// {type: "exponentSeparator", value: "E"}, {type: "exponentInteger", value: "0"}]
assertEquals("minusSign", parts[0].type);
assertEquals("-", parts[0].value);
assertEquals("integer", parts[1].type);
assertEquals("0", parts[1].value);
assertEquals("exponentSeparator", parts[2].type);
assertEquals("E", parts[2].value);
assertEquals("exponentInteger", parts[3].type);
assertEquals("0", parts[3].value);
assertEquals(4, parts.length);
parts = nf.formatToParts(Infinity);
// [{type: "infinity", value: "∞"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "0"}]
assertEquals("infinity", parts[0].type);
assertEquals("∞", parts[0].value);
assertEquals("exponentSeparator", parts[1].type);
assertEquals("E", parts[1].value);
assertEquals("exponentInteger", parts[2].type);
assertEquals("0", parts[2].value);
assertEquals(3, parts.length);
parts = nf.formatToParts(-Infinity);
// [{type: "minusSign", value: "-"}, {type: "infinity", value: "∞"},
// {type: "exponentSeparator", value: "E"}, {type: "exponentInteger", value: "0"}]
assertEquals("minusSign", parts[0].type);
assertEquals("-", parts[0].value);
assertEquals("infinity", parts[1].type);
assertEquals("∞", parts[1].value);
assertEquals("exponentSeparator", parts[2].type);
assertEquals("E", parts[2].value);
assertEquals("exponentInteger", parts[3].type);
assertEquals("0", parts[3].value);
assertEquals(4, parts.length);
parts = nf.formatToParts(NaN);
// [{type: "nan", value: "NaN"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "0"}]
assertEquals("nan", parts[0].type);
assertEquals("NaN", parts[0].value);
assertEquals("exponentSeparator", parts[1].type);
assertEquals("E", parts[1].value);
assertEquals("exponentInteger", parts[2].type);
assertEquals("0", parts[2].value);
assertEquals(3, parts.length);
// 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 notation: "scientific" with formatToParts.
const nf = Intl.NumberFormat("en", {notation: "scientific"});
let parts = nf.formatToParts(123.456);
// [{type: "integer", value: "1"}, {type: "decimal", value: "."},
// {type: "fraction", value: "235"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "2"}]
assertEquals("integer", parts[0].type);
assertEquals("1", parts[0].value);
assertEquals("decimal", parts[1].type);
assertEquals(".", parts[1].value);
assertEquals("fraction", parts[2].type);
assertEquals("235", parts[2].value);
assertEquals("exponentSeparator", parts[3].type);
assertEquals("E", parts[3].value);
assertEquals("exponentInteger", parts[4].type);
assertEquals("2", parts[4].value);
assertEquals(5, parts.length);
parts = nf.formatToParts(-123.456);
// [{type: "minusSign", value: "-"},i
// {type: "integer", value: "1"}, {type: "decimal", value: "."},
// {type: "fraction", value: "235"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "2"}]
assertEquals("minusSign", parts[0].type);
assertEquals("-", parts[0].value);
assertEquals("integer", parts[1].type);
assertEquals("1", parts[1].value);
assertEquals("decimal", parts[2].type);
assertEquals(".", parts[2].value);
assertEquals("fraction", parts[3].type);
assertEquals("235", parts[3].value);
assertEquals("exponentSeparator", parts[4].type);
assertEquals("E", parts[4].value);
assertEquals("exponentInteger", parts[5].type);
assertEquals("2", parts[5].value);
assertEquals(6, parts.length);
parts = nf.formatToParts(12345678901234567890);
// [{type: "integer", value: "1"}, {type: "decimal", value: "."},
// {type: "fraction", value: "235"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "19"}]
assertEquals("integer", parts[0].type);
assertEquals("1", parts[0].value);
assertEquals("decimal", parts[1].type);
assertEquals(".", parts[1].value);
assertEquals("fraction", parts[2].type);
assertEquals("235", parts[2].value);
assertEquals("exponentSeparator", parts[3].type);
assertEquals("E", parts[3].value);
assertEquals("exponentInteger", parts[4].type);
assertEquals("19", parts[4].value);
assertEquals(5, parts.length);
parts = nf.formatToParts(-12345678901234567890);
// [{type: "minusSign", value: "-"},
// {type: "integer", value: "1"}, {type: "decimal", value: "."},
// {type: "fraction", value: "235"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "19"}]
assertEquals("minusSign", parts[0].type);
assertEquals("-", parts[0].value);
assertEquals("integer", parts[1].type);
assertEquals("1", parts[1].value);
assertEquals("decimal", parts[2].type);
assertEquals(".", parts[2].value);
assertEquals("fraction", parts[3].type);
assertEquals("235", parts[3].value);
assertEquals("exponentSeparator", parts[4].type);
assertEquals("E", parts[4].value);
assertEquals("exponentInteger", parts[5].type);
assertEquals("19", parts[5].value);
assertEquals(6, parts.length);
parts = nf.formatToParts(0.000000000000123456);
// [{type: "integer", value: "1"}, {type: "decimal", value: "."},
// {type: "fraction", value: "235"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentMinusSign", value: "-"}, {type: "exponentInteger", value: "13"}]
assertEquals("integer", parts[0].type);
assertEquals("1", parts[0].value);
assertEquals("decimal", parts[1].type);
assertEquals(".", parts[1].value);
assertEquals("fraction", parts[2].type);
assertEquals("235", parts[2].value);
assertEquals("exponentSeparator", parts[3].type);
assertEquals("E", parts[3].value);
assertEquals("exponentMinusSign", parts[4].type);
assertEquals("-", parts[4].value);
assertEquals("exponentInteger", parts[5].type);
assertEquals("13", parts[5].value);
assertEquals(6, parts.length);
parts = nf.formatToParts(-0.000000000000123456);
// [{type: "minusSign", value: "-"}, {type: "integer", value: "1"},
// {type: "decimal", value: "."}, {type: "fraction", value: "235"},
// {type: "exponentSeparator", value: "E"},
// {type: "exponentMinusSign", value: "-"}, {type: "exponentInteger", value: "13"}]
assertEquals("minusSign", parts[0].type);
assertEquals("-", parts[0].value);
assertEquals("integer", parts[1].type);
assertEquals("1", parts[1].value);
assertEquals("decimal", parts[2].type);
assertEquals(".", parts[2].value);
assertEquals("fraction", parts[3].type);
assertEquals("235", parts[3].value);
assertEquals("exponentSeparator", parts[4].type);
assertEquals("E", parts[4].value);
assertEquals("exponentMinusSign", parts[5].type);
assertEquals("-", parts[5].value);
assertEquals("exponentInteger", parts[6].type);
assertEquals("13", parts[6].value);
assertEquals(7, parts.length);
parts = nf.formatToParts(0);
// [{type: "integer", value: "0"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "0"}]
assertEquals("integer", parts[0].type);
assertEquals("0", parts[0].value);
assertEquals("exponentSeparator", parts[1].type);
assertEquals("E", parts[1].value);
assertEquals("exponentInteger", parts[2].type);
assertEquals("0", parts[2].value);
assertEquals(3, parts.length);
parts = nf.formatToParts(-0);
// [{type: "minusSign", value: "-"}, {type: "integer", value: "0"},
// {type: "exponentSeparator", value: "E"}, {type: "exponentInteger", value: "0"}]
assertEquals("minusSign", parts[0].type);
assertEquals("-", parts[0].value);
assertEquals("integer", parts[1].type);
assertEquals("0", parts[1].value);
assertEquals("exponentSeparator", parts[2].type);
assertEquals("E", parts[2].value);
assertEquals("exponentInteger", parts[3].type);
assertEquals("0", parts[3].value);
assertEquals(4, parts.length);
parts = nf.formatToParts(Infinity);
// [{type: "infinity", value: "∞"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "0"}]
assertEquals("infinity", parts[0].type);
assertEquals("∞", parts[0].value);
assertEquals("exponentSeparator", parts[1].type);
assertEquals("E", parts[1].value);
assertEquals("exponentInteger", parts[2].type);
assertEquals("0", parts[2].value);
assertEquals(3, parts.length);
parts = nf.formatToParts(-Infinity);
// [{type: "minusSign", value: "-"}, {type: "infinity", value: "∞"},
// {type: "exponentSeparator", value: "E"}, {type: "exponentInteger", value: "0"}]
assertEquals("minusSign", parts[0].type);
assertEquals("-", parts[0].value);
assertEquals("infinity", parts[1].type);
assertEquals("∞", parts[1].value);
assertEquals("exponentSeparator", parts[2].type);
assertEquals("E", parts[2].value);
assertEquals("exponentInteger", parts[3].type);
assertEquals("0", parts[3].value);
assertEquals(4, parts.length);
parts = nf.formatToParts(NaN);
// [{type: "nan", value: "NaN"}, {type: "exponentSeparator", value: "E"},
// {type: "exponentInteger", value: "0"}]
assertEquals("nan", parts[0].type);
assertEquals("NaN", parts[0].value);
assertEquals("exponentSeparator", parts[1].type);
assertEquals("E", parts[1].value);
assertEquals("exponentInteger", parts[2].type);
assertEquals("0", parts[2].value);
assertEquals(3, parts.length);
// 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 Infinity, -Infinity, NaN won't crash with any notation in formatToParts.
let validNotations = [
"standard",
"compact",
"engineering",
"scientific",
];
let tests = [
123,
Infinity,
-Infinity,
NaN
];
for (const notation of validNotations) {
let nf = new Intl.NumberFormat("en", {notation});
for (const test of tests) {
assertDoesNotThrow(() => nf.format(test));
assertDoesNotThrow(() => nf.formatToParts(test));
}
}
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