Commit a4bdc77f authored by Frank Tang's avatar Frank Tang Committed by V8 LUCI CQ

[intl] Part 3 of NumberFormat v3

Add NumberFormat.prototype.formatRange(ToParts)?

https://github.com/tc39/proposal-intl-numberformat-v3

https://chromestatus.com/guide/edit/5707621009981440

Design Doc: https://docs.google.com/document/d/19jAogPBb6W4Samt8NWGZKu47iv0_KoQhBvLgQH3xvr8/edit


Bug: v8:10776
Change-Id: I9bb163c0c15ccac9d3a2d5e55ad38aa5c06bbaa6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3429464Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Commit-Queue: Frank Tang <ftang@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79373}
parent 82c4c977
......@@ -1771,6 +1771,10 @@ namespace internal {
CPP(NumberFormatInternalFormatNumber) \
/* ecma402 #sec-intl.numberformat.prototype.format */ \
CPP(NumberFormatPrototypeFormatNumber) \
/* ecma402 #sec-intl.numberformat.prototype.formatrange */ \
CPP(NumberFormatPrototypeFormatRange) \
/* ecma402 #sec-intl.numberformat.prototype.formatrangetoparts */ \
CPP(NumberFormatPrototypeFormatRangeToParts) \
/* ecma402 #sec-intl.numberformat.prototype.formattoparts */ \
CPP(NumberFormatPrototypeFormatToParts) \
/* ecma402 #sec-intl.numberformat.prototype.resolvedoptions */ \
......
......@@ -163,11 +163,10 @@ BUILTIN(DateTimeFormatPrototypeFormatToParts) {
}
// Common code for DateTimeFormatPrototypeFormtRange(|ToParts)
template <class T>
template <class T, MaybeHandle<T> (*F)(Isolate*, Handle<JSDateTimeFormat>,
double, double)>
V8_WARN_UNUSED_RESULT Object DateTimeFormatRange(
BuiltinArguments args, Isolate* isolate, const char* const method_name,
MaybeHandle<T> (*format)(Isolate*, Handle<JSDateTimeFormat>, double,
double)) {
BuiltinArguments args, Isolate* isolate, const char* const method_name) {
// 1. Let dtf be this value.
// 2. If Type(dtf) is not Object, throw a TypeError exception.
CHECK_RECEIVER(JSObject, date_format_holder, method_name);
......@@ -211,22 +210,22 @@ V8_WARN_UNUSED_RESULT Object DateTimeFormatRange(
// 8. Return ? FormatDateTimeRange(dtf, x, y)
// OR
// 8. Return ? FormatDateTimeRangeToParts(dtf, x, y).
RETURN_RESULT_OR_FAILURE(isolate, format(isolate, dtf, x, y));
RETURN_RESULT_OR_FAILURE(isolate, F(isolate, dtf, x, y));
}
BUILTIN(DateTimeFormatPrototypeFormatRange) {
const char* const method_name = "Intl.DateTimeFormat.prototype.formatRange";
HandleScope handle_scope(isolate);
return DateTimeFormatRange<String>(args, isolate, method_name,
JSDateTimeFormat::FormatRange);
return DateTimeFormatRange<String, JSDateTimeFormat::FormatRange>(
args, isolate, method_name);
}
BUILTIN(DateTimeFormatPrototypeFormatRangeToParts) {
const char* const method_name =
"Intl.DateTimeFormat.prototype.formatRangeToParts";
HandleScope handle_scope(isolate);
return DateTimeFormatRange<JSArray>(args, isolate, method_name,
JSDateTimeFormat::FormatRangeToParts);
return DateTimeFormatRange<JSArray, JSDateTimeFormat::FormatRangeToParts>(
args, isolate, method_name);
}
namespace {
......@@ -527,6 +526,63 @@ BUILTIN(NumberFormatInternalFormatNumber) {
isolate, *icu_localized_number_formatter, numeric_obj));
}
// Common code for NumberFormatPrototypeFormtRange(|ToParts)
template <class T, MaybeHandle<T> (*F)(Isolate*, Handle<JSNumberFormat>,
Handle<Object>, Handle<Object>)>
V8_WARN_UNUSED_RESULT Object NumberFormatRange(BuiltinArguments args,
Isolate* isolate,
const char* const method_name) {
// 1. Let nf be this value.
// 2. Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]]).
CHECK_RECEIVER(JSNumberFormat, nf, method_name);
Handle<Object> start = args.atOrUndefined(isolate, 1);
Handle<Object> end = args.atOrUndefined(isolate, 2);
Factory* factory = isolate->factory();
// 3. If start is undefined or end is undefined, throw a TypeError exception.
if (start->IsUndefined(isolate)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewTypeError(MessageTemplate::kInvalid,
factory->NewStringFromStaticChars("start"), start));
}
if (end->IsUndefined(isolate)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kInvalid,
factory->NewStringFromStaticChars("end"), end));
}
// 4. Let x be ? ToIntlMathematicalValue(start).
Handle<Object> x;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, x,
Intl::ToIntlMathematicalValueAsNumberBigIntOrString(isolate, start));
// 5. Let y be ? ToIntlMathematicalValue(end).
Handle<Object> y;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, y,
Intl::ToIntlMathematicalValueAsNumberBigIntOrString(isolate, end));
RETURN_RESULT_OR_FAILURE(isolate, F(isolate, nf, x, y));
}
BUILTIN(NumberFormatPrototypeFormatRange) {
const char* const method_name = "Intl.NumberFormat.prototype.formatRange";
HandleScope handle_scope(isolate);
return NumberFormatRange<String, JSNumberFormat::FormatNumericRange>(
args, isolate, method_name);
}
BUILTIN(NumberFormatPrototypeFormatRangeToParts) {
const char* const method_name =
"Intl.NumberFormat.prototype.formatRangeToParts";
HandleScope handle_scope(isolate);
return NumberFormatRange<JSArray, JSNumberFormat::FormatNumericRangeToParts>(
args, isolate, method_name);
}
BUILTIN(DateTimeFormatConstructor) {
HandleScope scope(isolate);
......
......@@ -4427,7 +4427,6 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_error_cause)
#ifdef V8_INTL_SUPPORT
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_intl_best_fit_matcher)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_intl_number_format_v3)
#endif // V8_INTL_SUPPORT
#undef EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE
......@@ -5335,6 +5334,32 @@ void Genesis::InitializeGlobal_harmony_intl_locale_info() {
Builtin::kLocalePrototypeWeekInfo, true);
}
void Genesis::InitializeGlobal_harmony_intl_number_format_v3() {
if (!FLAG_harmony_intl_number_format_v3) return;
Handle<JSObject> intl = Handle<JSObject>::cast(
JSReceiver::GetProperty(
isolate(),
Handle<JSReceiver>(native_context()->global_object(), isolate()),
factory()->InternalizeUtf8String("Intl"))
.ToHandleChecked());
Handle<JSFunction> number_format_constructor = Handle<JSFunction>::cast(
JSReceiver::GetProperty(
isolate(), Handle<JSReceiver>(JSReceiver::cast(*intl), isolate()),
factory()->InternalizeUtf8String("NumberFormat"))
.ToHandleChecked());
Handle<JSObject> prototype(
JSObject::cast(number_format_constructor->prototype()), isolate());
SimpleInstallFunction(isolate(), prototype, "formatRange",
Builtin::kNumberFormatPrototypeFormatRange, 2, false);
SimpleInstallFunction(isolate(), prototype, "formatRangeToParts",
Builtin::kNumberFormatPrototypeFormatRangeToParts, 2,
false);
}
void Genesis::InitializeGlobal_harmony_intl_enumeration() {
if (!FLAG_harmony_intl_enumeration) return;
......
......@@ -85,6 +85,7 @@
V(_, minimumFractionDigits_string, "minimumFractionDigits") \
V(_, minimumIntegerDigits_string, "minimumIntegerDigits") \
V(_, minimumSignificantDigits_string, "minimumSignificantDigits") \
V(_, minus_0, "-0") \
V(_, minusSign_string, "minusSign") \
V(_, morePrecision_string, "morePrecision") \
V(_, nan_string, "nan") \
......
......@@ -2916,5 +2916,45 @@ MaybeHandle<Object> Intl::ToIntlMathematicalValueAsNumberBigIntOrString(
return input;
}
Intl::FormatRangeSourceTracker::FormatRangeSourceTracker() {
start_[0] = start_[1] = limit_[0] = limit_[1] = 0;
}
void Intl::FormatRangeSourceTracker::Add(int32_t field, int32_t start,
int32_t limit) {
DCHECK_LT(field, 2);
start_[field] = start;
limit_[field] = limit;
}
Intl::FormatRangeSource Intl::FormatRangeSourceTracker::GetSource(
int32_t start, int32_t limit) const {
FormatRangeSource source = FormatRangeSource::kShared;
if (FieldContains(0, start, limit)) {
source = FormatRangeSource::kStartRange;
} else if (FieldContains(1, start, limit)) {
source = FormatRangeSource::kEndRange;
}
return source;
}
bool Intl::FormatRangeSourceTracker::FieldContains(int32_t field, int32_t start,
int32_t limit) const {
DCHECK_LT(field, 2);
return (start_[field] <= start) && (start <= limit_[field]) &&
(start_[field] <= limit) && (limit <= limit_[field]);
}
Handle<String> Intl::SourceString(Isolate* isolate, FormatRangeSource source) {
switch (source) {
case FormatRangeSource::kShared:
return ReadOnlyRoots(isolate).shared_string_handle();
case FormatRangeSource::kStartRange:
return ReadOnlyRoots(isolate).startRange_string_handle();
case FormatRangeSource::kEndRange:
return ReadOnlyRoots(isolate).endRange_string_handle();
}
}
} // namespace internal
} // namespace v8
......@@ -59,6 +59,24 @@ class Intl {
kLength
};
enum class FormatRangeSource { kShared, kStartRange, kEndRange };
class FormatRangeSourceTracker {
public:
FormatRangeSourceTracker();
void Add(int32_t field, int32_t start, int32_t limit);
FormatRangeSource GetSource(int32_t start, int32_t limit) const;
private:
int32_t start_[2];
int32_t limit_[2];
bool FieldContains(int32_t field, int32_t start, int32_t limit) const;
};
static Handle<String> SourceString(Isolate* isolate,
FormatRangeSource source);
// Build a set of ICU locales from a list of Locales. If there is a locale
// with a script tag then the locales also include a locale without the
// script; eg, pa_Guru_IN (language=Panjabi, script=Gurmukhi, country-India)
......
......@@ -2101,56 +2101,12 @@ Handle<String> JSDateTimeFormat::HourCycleAsString() const {
}
}
enum Source { kShared, kStartRange, kEndRange };
namespace {
class SourceTracker {
public:
SourceTracker() { start_[0] = start_[1] = limit_[0] = limit_[1] = 0; }
void Add(int32_t field, int32_t start, int32_t limit) {
DCHECK_LT(field, 2);
start_[field] = start;
limit_[field] = limit;
}
Source GetSource(int32_t start, int32_t limit) const {
Source source = Source::kShared;
if (FieldContains(0, start, limit)) {
source = Source::kStartRange;
} else if (FieldContains(1, start, limit)) {
source = Source::kEndRange;
}
return source;
}
private:
int32_t start_[2];
int32_t limit_[2];
bool FieldContains(int32_t field, int32_t start, int32_t limit) const {
DCHECK_LT(field, 2);
return (start_[field] <= start) && (start <= limit_[field]) &&
(start_[field] <= limit) && (limit <= limit_[field]);
}
};
Handle<String> SourceString(Isolate* isolate, Source source) {
switch (source) {
case Source::kShared:
return ReadOnlyRoots(isolate).shared_string_handle();
case Source::kStartRange:
return ReadOnlyRoots(isolate).startRange_string_handle();
case Source::kEndRange:
return ReadOnlyRoots(isolate).endRange_string_handle();
UNREACHABLE();
}
}
Maybe<bool> AddPartForFormatRange(Isolate* isolate, Handle<JSArray> array,
const icu::UnicodeString& string,
int32_t index, int32_t field, int32_t start,
int32_t end, const SourceTracker& tracker) {
Maybe<bool> AddPartForFormatRange(
Isolate* isolate, Handle<JSArray> array, const icu::UnicodeString& string,
int32_t index, int32_t field, int32_t start, int32_t end,
const Intl::FormatRangeSourceTracker& tracker) {
Handle<String> substring;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, substring,
Intl::ToString(isolate, string, start, end),
......@@ -2158,7 +2114,7 @@ Maybe<bool> AddPartForFormatRange(Isolate* isolate, Handle<JSArray> array,
Intl::AddElement(isolate, array, index,
IcuDateFieldIdToDateType(field, isolate), substring,
isolate->factory()->source_string(),
SourceString(isolate, tracker.GetSource(start, end)));
Intl::SourceString(isolate, tracker.GetSource(start, end)));
return Just(true);
}
......@@ -2193,7 +2149,7 @@ MaybeHandle<JSArray> FormattedDateIntervalToJSArray(
icu::ConstrainedFieldPosition cfpos;
int index = 0;
int32_t previous_end_pos = 0;
SourceTracker tracker;
Intl::FormatRangeSourceTracker tracker;
*outputRange = false;
while (formatted.nextPosition(cfpos, status)) {
int32_t category = cfpos.getCategory();
......@@ -2241,13 +2197,11 @@ MaybeHandle<JSArray> FormattedDateIntervalToJSArray(
}
// The shared code between formatRange and formatRangeToParts
template <typename T>
MaybeHandle<T> FormatRangeCommon(
Isolate* isolate, Handle<JSDateTimeFormat> date_time_format, double x,
double y,
const std::function<MaybeHandle<T>(Isolate*, const icu::FormattedValue&,
bool*)>& formatToResult,
bool* outputRange) {
template <typename T,
MaybeHandle<T> (*F)(Isolate*, const icu::FormattedValue&, bool*)>
MaybeHandle<T> FormatRangeCommon(Isolate* isolate,
Handle<JSDateTimeFormat> date_time_format,
double x, double y, bool* outputRange) {
// Track newer feature formateRange and formatRangeToParts
isolate->CountUsage(v8::Isolate::UseCounterFeature::kDateTimeFormatRange);
......@@ -2290,7 +2244,7 @@ MaybeHandle<T> FormatRangeCommon(
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIcuError), T);
}
return formatToResult(isolate, formatted, outputRange);
return F(isolate, formatted, outputRange);
}
} // namespace
......@@ -2299,8 +2253,8 @@ MaybeHandle<String> JSDateTimeFormat::FormatRange(
Isolate* isolate, Handle<JSDateTimeFormat> date_time_format, double x,
double y) {
bool outputRange = true;
MaybeHandle<String> ret = FormatRangeCommon<String>(
isolate, date_time_format, x, y, FormattedToString, &outputRange);
MaybeHandle<String> ret = FormatRangeCommon<String, FormattedToString>(
isolate, date_time_format, x, y, &outputRange);
if (outputRange) {
return ret;
}
......@@ -2313,8 +2267,8 @@ MaybeHandle<JSArray> JSDateTimeFormat::FormatRangeToParts(
double y) {
bool outputRange = true;
MaybeHandle<JSArray> ret =
FormatRangeCommon<JSArray>(isolate, date_time_format, x, y,
FormattedDateIntervalToJSArray, &outputRange);
FormatRangeCommon<JSArray, FormattedDateIntervalToJSArray>(
isolate, date_time_format, x, y, &outputRange);
if (outputRange) {
return ret;
}
......
......@@ -25,6 +25,9 @@ TQ_OBJECT_CONSTRUCTORS_IMPL(JSNumberFormat)
ACCESSORS(JSNumberFormat, icu_number_formatter,
Managed<icu::number::LocalizedNumberFormatter>,
kIcuNumberFormatterOffset)
ACCESSORS(JSNumberFormat, icu_number_range_formatter,
Managed<icu::number::LocalizedNumberRangeFormatter>,
kIcuNumberRangeFormatterOffset)
} // namespace internal
} // namespace v8
......
This diff is collapsed.
......@@ -27,6 +27,7 @@ class UnicodeString;
namespace number {
class LocalizedNumberFormatter;
class UnlocalizedNumberFormatter;
class LocalizedNumberRangeFormatter;
} // namespace number
} // namespace U_ICU_NAMESPACE
......@@ -55,6 +56,16 @@ class JSNumberFormat
Isolate* isolate, Handle<JSNumberFormat> number_format,
Handle<Object> numeric_obj);
// ecma402/#sec-formatnumericrange
V8_WARN_UNUSED_RESULT static MaybeHandle<String> FormatNumericRange(
Isolate* isolate, Handle<JSNumberFormat> number_format, Handle<Object> x,
Handle<Object> y);
// ecma402/#sec-formatnumericrangetoparts
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> FormatNumericRangeToParts(
Isolate* isolate, Handle<JSNumberFormat> number_format, Handle<Object> x,
Handle<Object> y);
V8_WARN_UNUSED_RESULT static MaybeHandle<String> FormatNumeric(
Isolate* isolate,
const icu::number::LocalizedNumberFormatter& number_format,
......@@ -81,6 +92,8 @@ class JSNumberFormat
DECL_ACCESSORS(icu_number_formatter,
Managed<icu::number::LocalizedNumberFormatter>)
DECL_ACCESSORS(icu_number_range_formatter,
Managed<icu::number::LocalizedNumberRangeFormatter>)
TQ_OBJECT_CONSTRUCTORS(JSNumberFormat)
};
......
......@@ -8,5 +8,7 @@ extern class JSNumberFormat extends JSObject {
locale: String;
icu_number_formatter:
Foreign; // Managed<icu::number::LocalizedNumberFormatter>
icu_number_range_formatter:
Foreign; // Managed<icu::number::LocalizedNumberRangeFormatter>
bound_format: JSFunction|Undefined;
}
// Copyright 2022 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-number-format-v3
const validRanges = [[-12345, -5678], [-12345, 56789], [12345, 56789]];
const nf = new Intl.NumberFormat("en", {signDisplay: "exceptZero"});
['formatRange', 'formatRangeToParts'].forEach(function(method) {
assertEquals("function", typeof nf[method]);
// 2. Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]]).
// Assert if called without nf
let f = nf[method];
assertThrows(() => { f(1, 23) }, TypeError);
// Assert normal call success
assertDoesNotThrow(() => nf[method](1, 23));
// 3. If start is undefined ..., throw a TypeError exception.
assertThrows(() => { nf[method](undefined, 23) }, TypeError);
// 3. If ... end is undefined, throw a TypeError exception.
assertThrows(() => { nf[method](1, undefined) }, TypeError);
// 4. Let x be ? ToNumeric(start).
// Verify it won't throw error
assertDoesNotThrow(() => nf[method](null, 23));
assertDoesNotThrow(() => nf[method](false, 23));
assertDoesNotThrow(() => nf[method](true, 23));
assertDoesNotThrow(() => nf[method](12, 23));
assertDoesNotThrow(() => nf[method](12n, 23));
// Verify it will throw error
assertThrows(() => { nf[method](Symbol(12), 23) }, TypeError);
// 5. Let y be ? ToNumeric(end).
// Verify it won't throw error
assertDoesNotThrow(() => nf[method](-12, null));
assertDoesNotThrow(() => nf[method](-12, false));
assertDoesNotThrow(() => nf[method](-12, true));
assertDoesNotThrow(() => nf[method](12, 23));
assertDoesNotThrow(() => nf[method](12, 23n));
// Verify it will throw error
assertThrows(() => { nf[method](12, Symbol(23)) }, TypeError);
// 6. If x is NaN ..., throw a RangeError exception.
assertThrows(() => { nf[method](NaN, 23) }, RangeError);
// 6. If ... y is NaN, throw a RangeError exception.
assertThrows(() => { nf[method](12, NaN) }, RangeError);
// 8. If x is greater than y, throw a RangeError exception.
// neither x nor y are bigint.
assertThrows(() => { nf[method](23, 12) }, RangeError);
assertDoesNotThrow(() => nf[method](12, 23));
// x is not bigint but y is.
assertThrows(() => { nf[method](23, 12n) }, RangeError);
assertDoesNotThrow(() => nf[method](12, 23n));
// x is bigint but y is not.
assertThrows(() => { nf[method](23n, 12) }, RangeError);
assertDoesNotThrow(() => nf[method](12n, 23));
// both x and y are bigint.
assertThrows(() => { nf[method](23n, 12n) }, RangeError);
assertDoesNotThrow(() => nf[method](12n, 23n));
validRanges.forEach(
function([x, y]) {
const X = BigInt(x);
const Y = BigInt(y);
const formatted_x_y = nf[method](x, y);
const formatted_X_y = nf[method](X, y);
const formatted_x_Y = nf[method](x, Y);
const formatted_X_Y = nf[method](X, Y);
assertEquals(formatted_x_y, formatted_X_y);
assertEquals(formatted_x_y, formatted_x_Y);
assertEquals(formatted_x_y, formatted_X_Y);
});
});
// Check the number of part with type: "plusSign" and "minusSign" are corre
validRanges.forEach(
function([x, y]) {
const expectedPlus = (x > 0) ? ((y > 0) ? 2 : 1) : ((y > 0) ? 1 : 0);
const expectedMinus = (x < 0) ? ((y < 0) ? 2 : 1) : ((y < 0) ? 1 : 0);
let actualPlus = 0;
let actualMinus = 0;
const parts = nf.formatRangeToParts(x, y);
parts.forEach(function(part) {
if (part.type == "plusSign") actualPlus++;
if (part.type == "minusSign") actualMinus++;
});
const method = "formatRangeToParts(" + x + ", " + y + "): ";
assertEquals(expectedPlus, actualPlus,
method + "Number of type: 'plusSign' in parts is incorrect");
assertEquals(expectedMinus, actualMinus,
method + "Number of type: 'minusSign' in parts is incorrect");
});
// From https://github.com/tc39/proposal-intl-numberformat-v3#formatrange-ecma-402-393
const nf2 = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR",
maximumFractionDigits: 0,
});
// README.md said it expect "€3–5"
assertEquals("€3 – €5", nf2.formatRange(3, 5));
const nf3 = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR",
maximumFractionDigits: 0,
});
const actual3 = nf3.formatRangeToParts(3, 5);
/*
[
{type: "currency", value: "€", source: "startRange"}
{type: "integer", value: "3", source: "startRange"}
{type: "literal", value: "–", source: "shared"}
{type: "integer", value: "5", source: "endRange"}
]
*/
assertEquals(5, actual3.length);
assertEquals("currency", actual3[0].type);
assertEquals("€", actual3[0].value);
assertEquals("startRange", actual3[0].source);
assertEquals("integer", actual3[1].type);
assertEquals("3", actual3[1].value);
assertEquals("startRange", actual3[1].source);
assertEquals("literal", actual3[2].type);
assertEquals(" – ", actual3[2].value);
assertEquals("shared", actual3[2].source);
assertEquals("currency", actual3[3].type);
assertEquals("€", actual3[3].value);
assertEquals("endRange", actual3[3].source);
assertEquals("integer", actual3[4].type);
assertEquals("5", actual3[4].value);
assertEquals("endRange", actual3[4].source);
const nf4 = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR",
maximumFractionDigits: 0,
});
assertEquals("~€3", nf4.formatRange(2.9, 3.1));
const nf5 = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR",
signDisplay: "always",
});
assertEquals("~+€3.00", nf5.formatRange(2.999, 3.001));
const nf6 = new Intl.NumberFormat("en");
assertEquals("3–∞", nf6.formatRange(3, 1/0));
assertThrows(() => { nf6.formatRange(3, 0/0); }, RangeError);
......@@ -2451,23 +2451,10 @@
'intl402/NumberFormat/constructor-roundingIncrement': [FAIL],
'intl402/NumberFormat/test-option-roundingPriority': [FAIL],
# NumberFormat.prototype.formatRange
'intl402/NumberFormat/prototype/formatRange/builtin': [FAIL],
'intl402/NumberFormat/prototype/formatRange/en-US': [FAIL],
'intl402/NumberFormat/prototype/formatRange/invoked-as-func': [FAIL],
'intl402/NumberFormat/prototype/formatRange/length': [FAIL],
'intl402/NumberFormat/prototype/formatRange/name': [FAIL],
'intl402/NumberFormat/prototype/formatRange/nan-arguments-throws': [FAIL],
'intl402/NumberFormat/prototype/formatRange/prop-desc': [FAIL],
'intl402/NumberFormat/prototype/formatRange/pt-PT': [FAIL],
'intl402/NumberFormat/prototype/formatRange/x-greater-than-y-throws': [FAIL],
# NumberFormat.prototype.formatRangeToParts
'intl402/NumberFormat/prototype/formatRangeToParts/builtin': [FAIL],
'intl402/NumberFormat/prototype/formatRangeToParts/en-US': [FAIL],
'intl402/NumberFormat/prototype/formatRangeToParts/invoked-as-func': [FAIL],
'intl402/NumberFormat/prototype/formatRangeToParts/length': [FAIL],
'intl402/NumberFormat/prototype/formatRangeToParts/name': [FAIL],
'intl402/NumberFormat/prototype/formatRangeToParts/nan-arguments-throws': [FAIL],
'intl402/NumberFormat/prototype/formatRangeToParts/prop-desc': [FAIL],
'intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-throws': [FAIL],
# PluralRules.prototype.selectRange
......
......@@ -377,76 +377,76 @@ KNOWN_MAPS = {
("read_only_space", 0x03401): (131, "BasicBlockCountersMarkerMap"),
("read_only_space", 0x03445): (147, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x03545): (161, "InterceptorInfoMap"),
("read_only_space", 0x06005): (132, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x0602d): (133, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x06055): (134, "CallableTaskMap"),
("read_only_space", 0x0607d): (135, "CallbackTaskMap"),
("read_only_space", 0x060a5): (136, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x060cd): (139, "FunctionTemplateInfoMap"),
("read_only_space", 0x060f5): (140, "ObjectTemplateInfoMap"),
("read_only_space", 0x0611d): (141, "AccessCheckInfoMap"),
("read_only_space", 0x06145): (142, "AccessorInfoMap"),
("read_only_space", 0x0616d): (143, "AccessorPairMap"),
("read_only_space", 0x06195): (144, "AliasedArgumentsEntryMap"),
("read_only_space", 0x061bd): (145, "AllocationMementoMap"),
("read_only_space", 0x061e5): (148, "AsmWasmDataMap"),
("read_only_space", 0x0620d): (149, "AsyncGeneratorRequestMap"),
("read_only_space", 0x06235): (150, "BreakPointMap"),
("read_only_space", 0x0625d): (151, "BreakPointInfoMap"),
("read_only_space", 0x06285): (152, "CachedTemplateObjectMap"),
("read_only_space", 0x062ad): (154, "CallSiteInfoMap"),
("read_only_space", 0x062d5): (155, "ClassPositionsMap"),
("read_only_space", 0x062fd): (156, "DebugInfoMap"),
("read_only_space", 0x06325): (158, "ErrorStackDataMap"),
("read_only_space", 0x0634d): (160, "FunctionTemplateRareDataMap"),
("read_only_space", 0x06375): (162, "InterpreterDataMap"),
("read_only_space", 0x0639d): (163, "ModuleRequestMap"),
("read_only_space", 0x063c5): (164, "PromiseCapabilityMap"),
("read_only_space", 0x063ed): (165, "PromiseReactionMap"),
("read_only_space", 0x06415): (166, "PropertyDescriptorObjectMap"),
("read_only_space", 0x0643d): (167, "PrototypeInfoMap"),
("read_only_space", 0x06465): (168, "RegExpBoilerplateDescriptionMap"),
("read_only_space", 0x0648d): (169, "ScriptMap"),
("read_only_space", 0x064b5): (170, "ScriptOrModuleMap"),
("read_only_space", 0x064dd): (171, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x06505): (172, "StackFrameInfoMap"),
("read_only_space", 0x0652d): (173, "TemplateObjectDescriptionMap"),
("read_only_space", 0x06555): (174, "Tuple2Map"),
("read_only_space", 0x0657d): (175, "WasmContinuationObjectMap"),
("read_only_space", 0x065a5): (176, "WasmExceptionTagMap"),
("read_only_space", 0x065cd): (177, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x065f5): (197, "SloppyArgumentsElementsMap"),
("read_only_space", 0x0661d): (233, "DescriptorArrayMap"),
("read_only_space", 0x06645): (219, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x0666d): (217, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x06695): (220, "UncompiledDataWithoutPreparseDataWithJobMap"),
("read_only_space", 0x066bd): (218, "UncompiledDataWithPreparseDataAndJobMap"),
("read_only_space", 0x066e5): (251, "OnHeapBasicBlockProfilerDataMap"),
("read_only_space", 0x0670d): (198, "TurbofanBitsetTypeMap"),
("read_only_space", 0x06735): (202, "TurbofanUnionTypeMap"),
("read_only_space", 0x0675d): (201, "TurbofanRangeTypeMap"),
("read_only_space", 0x06785): (199, "TurbofanHeapConstantTypeMap"),
("read_only_space", 0x067ad): (200, "TurbofanOtherNumberConstantTypeMap"),
("read_only_space", 0x067d5): (247, "InternalClassMap"),
("read_only_space", 0x067fd): (258, "SmiPairMap"),
("read_only_space", 0x06825): (257, "SmiBoxMap"),
("read_only_space", 0x0684d): (225, "ExportedSubClassBaseMap"),
("read_only_space", 0x06875): (226, "ExportedSubClassMap"),
("read_only_space", 0x0689d): (231, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x068c5): (232, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x068ed): (196, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x06915): (248, "InternalClassWithStructElementsMap"),
("read_only_space", 0x0693d): (227, "ExportedSubClass2Map"),
("read_only_space", 0x06965): (259, "SortStateMap"),
("read_only_space", 0x0698d): (146, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x069b5): (146, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x069dd): (137, "LoadHandler1Map"),
("read_only_space", 0x06a05): (137, "LoadHandler2Map"),
("read_only_space", 0x06a2d): (137, "LoadHandler3Map"),
("read_only_space", 0x06a55): (138, "StoreHandler0Map"),
("read_only_space", 0x06a7d): (138, "StoreHandler1Map"),
("read_only_space", 0x06aa5): (138, "StoreHandler2Map"),
("read_only_space", 0x06acd): (138, "StoreHandler3Map"),
("read_only_space", 0x06015): (132, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x0603d): (133, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x06065): (134, "CallableTaskMap"),
("read_only_space", 0x0608d): (135, "CallbackTaskMap"),
("read_only_space", 0x060b5): (136, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x060dd): (139, "FunctionTemplateInfoMap"),
("read_only_space", 0x06105): (140, "ObjectTemplateInfoMap"),
("read_only_space", 0x0612d): (141, "AccessCheckInfoMap"),
("read_only_space", 0x06155): (142, "AccessorInfoMap"),
("read_only_space", 0x0617d): (143, "AccessorPairMap"),
("read_only_space", 0x061a5): (144, "AliasedArgumentsEntryMap"),
("read_only_space", 0x061cd): (145, "AllocationMementoMap"),
("read_only_space", 0x061f5): (148, "AsmWasmDataMap"),
("read_only_space", 0x0621d): (149, "AsyncGeneratorRequestMap"),
("read_only_space", 0x06245): (150, "BreakPointMap"),
("read_only_space", 0x0626d): (151, "BreakPointInfoMap"),
("read_only_space", 0x06295): (152, "CachedTemplateObjectMap"),
("read_only_space", 0x062bd): (154, "CallSiteInfoMap"),
("read_only_space", 0x062e5): (155, "ClassPositionsMap"),
("read_only_space", 0x0630d): (156, "DebugInfoMap"),
("read_only_space", 0x06335): (158, "ErrorStackDataMap"),
("read_only_space", 0x0635d): (160, "FunctionTemplateRareDataMap"),
("read_only_space", 0x06385): (162, "InterpreterDataMap"),
("read_only_space", 0x063ad): (163, "ModuleRequestMap"),
("read_only_space", 0x063d5): (164, "PromiseCapabilityMap"),
("read_only_space", 0x063fd): (165, "PromiseReactionMap"),
("read_only_space", 0x06425): (166, "PropertyDescriptorObjectMap"),
("read_only_space", 0x0644d): (167, "PrototypeInfoMap"),
("read_only_space", 0x06475): (168, "RegExpBoilerplateDescriptionMap"),
("read_only_space", 0x0649d): (169, "ScriptMap"),
("read_only_space", 0x064c5): (170, "ScriptOrModuleMap"),
("read_only_space", 0x064ed): (171, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x06515): (172, "StackFrameInfoMap"),
("read_only_space", 0x0653d): (173, "TemplateObjectDescriptionMap"),
("read_only_space", 0x06565): (174, "Tuple2Map"),
("read_only_space", 0x0658d): (175, "WasmContinuationObjectMap"),
("read_only_space", 0x065b5): (176, "WasmExceptionTagMap"),
("read_only_space", 0x065dd): (177, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x06605): (197, "SloppyArgumentsElementsMap"),
("read_only_space", 0x0662d): (233, "DescriptorArrayMap"),
("read_only_space", 0x06655): (219, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x0667d): (217, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x066a5): (220, "UncompiledDataWithoutPreparseDataWithJobMap"),
("read_only_space", 0x066cd): (218, "UncompiledDataWithPreparseDataAndJobMap"),
("read_only_space", 0x066f5): (251, "OnHeapBasicBlockProfilerDataMap"),
("read_only_space", 0x0671d): (198, "TurbofanBitsetTypeMap"),
("read_only_space", 0x06745): (202, "TurbofanUnionTypeMap"),
("read_only_space", 0x0676d): (201, "TurbofanRangeTypeMap"),
("read_only_space", 0x06795): (199, "TurbofanHeapConstantTypeMap"),
("read_only_space", 0x067bd): (200, "TurbofanOtherNumberConstantTypeMap"),
("read_only_space", 0x067e5): (247, "InternalClassMap"),
("read_only_space", 0x0680d): (258, "SmiPairMap"),
("read_only_space", 0x06835): (257, "SmiBoxMap"),
("read_only_space", 0x0685d): (225, "ExportedSubClassBaseMap"),
("read_only_space", 0x06885): (226, "ExportedSubClassMap"),
("read_only_space", 0x068ad): (231, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x068d5): (232, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x068fd): (196, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x06925): (248, "InternalClassWithStructElementsMap"),
("read_only_space", 0x0694d): (227, "ExportedSubClass2Map"),
("read_only_space", 0x06975): (259, "SortStateMap"),
("read_only_space", 0x0699d): (146, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x069c5): (146, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x069ed): (137, "LoadHandler1Map"),
("read_only_space", 0x06a15): (137, "LoadHandler2Map"),
("read_only_space", 0x06a3d): (137, "LoadHandler3Map"),
("read_only_space", 0x06a65): (138, "StoreHandler0Map"),
("read_only_space", 0x06a8d): (138, "StoreHandler1Map"),
("read_only_space", 0x06ab5): (138, "StoreHandler2Map"),
("read_only_space", 0x06add): (138, "StoreHandler3Map"),
("map_space", 0x02149): (1057, "ExternalMap"),
("map_space", 0x02171): (2115, "JSMessageObjectMap"),
}
......
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