Bug 1610514 - Part 3: Pass through a boolean flag to detect style=unit number formatters. r=jwalden

Differential Revision: https://phabricator.services.mozilla.com/D60969

--HG--
extra : moz-landing-system : lando
This commit is contained in:
André Bargull 2020-01-30 09:47:48 +00:00
parent 16f000f4f4
commit ffe63d4342
7 changed files with 119 additions and 19 deletions

View File

@ -31,6 +31,6 @@ function BigInt_toLocaleString() {
}
// Step 3.
return intl_FormatNumber(numberFormat, x, /* formatToParts = */ false);
return intl_FormatNumber(numberFormat, x, /* formatToParts = */ false, /* unitStyle = */ false);
}
#endif // JS_HAS_INTL_API

View File

@ -35,7 +35,7 @@ function Number_toLocaleString() {
}
// Step 5.
return intl_FormatNumber(numberFormat, x, /* formatToParts = */ false);
return intl_FormatNumber(numberFormat, x, /* formatToParts = */ false, /* unitStyle = */ false);
}
#endif // JS_HAS_INTL_API

View File

@ -1005,8 +1005,11 @@ static bool FormatNumeric(JSContext* cx, const UNumberFormatter* nf,
return true;
}
enum class FormattingType { ForUnit, NotForUnit };
static FieldType GetFieldTypeForNumberField(UNumberFormatFields fieldName,
HandleValue x) {
HandleValue x,
FormattingType formattingType) {
// See intl/icu/source/i18n/unicode/unum.h for a detailed field list. This
// list is deliberately exhaustive: cases might have to be added/removed if
// this code is compiled with a different ICU with more UNumberFormatFields
@ -1044,6 +1047,11 @@ static FieldType GetFieldTypeForNumberField(UNumberFormatFields fieldName,
}
case UNUM_PERCENT_FIELD:
// Percent fields are returned as "unit" elements when the number
// formatter's style is "unit".
if (formattingType == FormattingType::ForUnit) {
return &JSAtomState::unit;
}
return &JSAtomState::percentSign;
case UNUM_CURRENCY_FIELD:
@ -1418,6 +1426,7 @@ static bool FormattedNumberToParts(JSContext* cx,
const UFormattedValue* formattedValue,
HandleValue number,
FieldType relativeTimeUnit,
FormattingType formattingType,
MutableHandleValue result) {
MOZ_ASSERT(number.isNumeric());
@ -1468,8 +1477,8 @@ static bool FormattedNumberToParts(JSContext* cx,
return false;
}
FieldType type =
GetFieldTypeForNumberField(UNumberFormatFields(field), number);
FieldType type = GetFieldTypeForNumberField(UNumberFormatFields(field),
number, formattingType);
if (!fields.append(type, beginIndex, endIndex)) {
return false;
@ -1489,9 +1498,9 @@ bool js::intl::FormattedRelativeTimeToParts(
JSContext* cx, const UFormattedValue* formattedValue, double timeValue,
FieldType relativeTimeUnit, MutableHandleValue result) {
Value tval = DoubleValue(timeValue);
return FormattedNumberToParts(cx, formattedValue,
HandleValue::fromMarkedLocation(&tval),
relativeTimeUnit, result);
return FormattedNumberToParts(
cx, formattedValue, HandleValue::fromMarkedLocation(&tval),
relativeTimeUnit, FormattingType::NotForUnit, result);
}
#else
static ArrayObject* LegacyFormattedNumberToParts(
@ -1542,6 +1551,7 @@ static ArrayObject* LegacyFormattedNumberToParts(
static bool FormatNumericToParts(JSContext* cx, const UNumberFormatter* nf,
UFormattedNumber* formatted, HandleValue x,
FormattingType formattingType,
MutableHandleValue result) {
PartitionNumberPatternResult formattedValue =
PartitionNumberPattern(cx, nf, formatted, x);
@ -1550,7 +1560,8 @@ static bool FormatNumericToParts(JSContext* cx, const UNumberFormatter* nf,
}
#ifndef U_HIDE_DRAFT_API
return FormattedNumberToParts(cx, formattedValue, x, nullptr, result);
return FormattedNumberToParts(cx, formattedValue, x, nullptr, formattingType,
result);
#else
return LegacyFormattedNumberToParts(cx, formattedValue, x, result);
#endif
@ -1558,10 +1569,11 @@ static bool FormatNumericToParts(JSContext* cx, const UNumberFormatter* nf,
bool js::intl_FormatNumber(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 3);
MOZ_ASSERT(args.length() == 4);
MOZ_ASSERT(args[0].isObject());
MOZ_ASSERT(args[1].isNumeric());
MOZ_ASSERT(args[2].isBoolean());
MOZ_ASSERT(args[3].isBoolean());
Rooted<NumberFormatObject*> numberFormat(
cx, &args[0].toObject().as<NumberFormatObject>());
@ -1593,7 +1605,11 @@ bool js::intl_FormatNumber(JSContext* cx, unsigned argc, Value* vp) {
// Use the UNumberFormatter to actually format the number.
if (args[2].toBoolean()) {
return FormatNumericToParts(cx, nf, formatted, args[1], args.rval());
FormattingType formattingType = args[3].toBoolean()
? FormattingType::ForUnit
: FormattingType::NotForUnit;
return FormatNumericToParts(cx, nf, formatted, args[1], formattingType,
args.rval());
}
return FormatNumeric(cx, nf, formatted, args[1], args.rval());

View File

@ -94,7 +94,8 @@ extern MOZ_MUST_USE bool intl_numberingSystem(JSContext* cx, unsigned argc,
*
* Spec: ECMAScript Internationalization API Specification, 11.3.2.
*
* Usage: formatted = intl_FormatNumber(numberFormat, x, formatToParts)
* Usage: formatted = intl_FormatNumber(numberFormat, x, formatToParts,
* unitStyle)
*/
extern MOZ_MUST_USE bool intl_FormatNumber(JSContext* cx, unsigned argc,
Value* vp);

View File

@ -698,7 +698,7 @@ function createNumberFormatFormat(nf) {
var x = ToNumeric(value);
// Step 5.
return intl_FormatNumber(nf, x, /* formatToParts = */ false);
return intl_FormatNumber(nf, x, /* formatToParts = */ false, /* unitStyle = */ false);
};
}
@ -746,14 +746,14 @@ function Intl_NumberFormat_formatToParts(value) {
"Intl_NumberFormat_formatToParts");
}
// Ensure the NumberFormat internals are resolved.
getNumberFormatInternals(nf);
var internals = getNumberFormatInternals(nf);
var unitStyle = internals.style === "unit";
// Step 4.
var x = ToNumeric(value);
// Step 5.
return intl_FormatNumber(nf, x, /* formatToParts = */ true);
return intl_FormatNumber(nf, x, /* formatToParts = */ true, unitStyle);
}
/**

View File

@ -464,9 +464,6 @@ skip script test262/intl402/NumberFormat/prototype/format/signDisplay-ko-KR.js
skip script test262/intl402/NumberFormat/prototype/format/signDisplay-de-DE.js
skip script test262/intl402/NumberFormat/prototype/format/signDisplay-rounding.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1610514
skip script test262/intl402/NumberFormat/prototype/formatToParts/percent-en-US.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1608809
skip script test262/language/expressions/class/super-evaluation-order.js

View File

@ -0,0 +1,86 @@
// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
const sanctionedSimpleUnitIdentifiers = [
"acre",
"bit",
"byte",
"celsius",
"centimeter",
"day",
"degree",
"fahrenheit",
"fluid-ounce",
"foot",
"gallon",
"gigabit",
"gigabyte",
"gram",
"hectare",
"hour",
"inch",
"kilobit",
"kilobyte",
"kilogram",
"kilometer",
"liter",
"megabit",
"megabyte",
"meter",
"mile",
"mile-scandinavian",
"milliliter",
"millimeter",
"millisecond",
"minute",
"month",
"ounce",
"percent",
"petabyte",
"pound",
"second",
"stone",
"terabit",
"terabyte",
"week",
"yard",
"year",
];
// Test only English and Chinese to keep the overall runtime reasonable.
//
// Chinese is included because it contains more than one "unit" element for
// certain unit combinations.
const locales = ["en", "zh"];
// Plural rules for English only differentiate between "one" and "other". Plural
// rules for Chinese only use "other". That means we only need to test two values
// per unit.
const values = [0, 1];
// Ensure unit formatters contain at least one "unit" element.
for (const locale of locales) {
for (const unit of sanctionedSimpleUnitIdentifiers) {
const nf = new Intl.NumberFormat(locale, {style: "unit", unit});
for (const value of values) {
assertEq(nf.formatToParts(value).filter(e => e.type === "unit").length > 0, true,
`locale=${locale}, unit=${unit}`);
}
}
for (const numerator of sanctionedSimpleUnitIdentifiers) {
for (const denominator of sanctionedSimpleUnitIdentifiers) {
const unit = `${numerator}-per-${denominator}`;
const nf = new Intl.NumberFormat(locale, {style: "unit", unit});
for (const value of values) {
assertEq(nf.formatToParts(value).filter(e => e.type === "unit").length > 0, true,
`locale=${locale}, unit=${unit}`);
}
}
}
}
if (typeof reportCompare === "function")
reportCompare(true, true);