mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 20:07:36 +00:00
LibJS: Allow specifying only roundingIncrement in NumberFormat options
This is a normative change in the Intl.NumberFormat v3 spec. See:
a260aa3
This commit is contained in:
parent
e3b8a8f7c8
commit
675e5bfdce
3 changed files with 27 additions and 32 deletions
|
@ -159,31 +159,38 @@ ThrowCompletionOr<NumberFormat*> initialize_number_format(VM& vm, NumberFormat&
|
||||||
default_max_fraction_digits = style == NumberFormat::Style::Percent ? 0 : 3;
|
default_max_fraction_digits = style == NumberFormat::Style::Percent ? 0 : 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 18. Let notation be ? GetOption(options, "notation", "string", « "standard", "scientific", "engineering", "compact" », "standard").
|
// 18. Let roundingIncrement be ? GetNumberOption(options, "roundingIncrement", 1, 5000, 1).
|
||||||
auto notation = TRY(get_option(vm, *options, vm.names.notation, OptionType::String, { "standard"sv, "scientific"sv, "engineering"sv, "compact"sv }, "standard"sv));
|
|
||||||
|
|
||||||
// 19. Set numberFormat.[[Notation]] to notation.
|
|
||||||
number_format.set_notation(notation.as_string().string());
|
|
||||||
|
|
||||||
// 20. Perform ? SetNumberFormatDigitOptions(numberFormat, options, mnfdDefault, mxfdDefault, notation).
|
|
||||||
TRY(set_number_format_digit_options(vm, number_format, *options, default_min_fraction_digits, default_max_fraction_digits, number_format.notation()));
|
|
||||||
|
|
||||||
// 21. Let roundingIncrement be ? GetNumberOption(options, "roundingIncrement", 1, 5000, 1).
|
|
||||||
auto rounding_increment = TRY(get_number_option(vm, *options, vm.names.roundingIncrement, 1, 5000, 1));
|
auto rounding_increment = TRY(get_number_option(vm, *options, vm.names.roundingIncrement, 1, 5000, 1));
|
||||||
|
|
||||||
// 22. If roundingIncrement is not in « 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000 », throw a RangeError exception.
|
// 19. If roundingIncrement is not in « 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000 », throw a RangeError exception.
|
||||||
static constexpr auto sanctioned_rounding_increments = AK::Array { 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000 };
|
static constexpr auto sanctioned_rounding_increments = AK::Array { 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000 };
|
||||||
|
|
||||||
if (!sanctioned_rounding_increments.span().contains_slow(*rounding_increment))
|
if (!sanctioned_rounding_increments.span().contains_slow(*rounding_increment))
|
||||||
return vm.throw_completion<RangeError>(ErrorType::IntlInvalidRoundingIncrement, *rounding_increment);
|
return vm.throw_completion<RangeError>(ErrorType::IntlInvalidRoundingIncrement, *rounding_increment);
|
||||||
|
|
||||||
// 23. If roundingIncrement is not 1 and numberFormat.[[RoundingType]] is not fractionDigits, throw a TypeError exception.
|
// 20. If roundingIncrement is not 1, set mxfdDefault to mnfdDefault.
|
||||||
if ((rounding_increment != 1) && (number_format.rounding_type() != NumberFormatBase::RoundingType::FractionDigits))
|
if (rounding_increment != 1)
|
||||||
return vm.throw_completion<TypeError>(ErrorType::IntlInvalidRoundingIncrementForRoundingType, *rounding_increment, number_format.rounding_type_string());
|
default_max_fraction_digits = default_min_fraction_digits;
|
||||||
|
|
||||||
// 24. If roundingIncrement is not 1 and numberFormat.[[MaximumFractionDigits]] is not equal to numberFormat.[[MinimumFractionDigits]], throw a RangeError exception.
|
// 21. Let notation be ? GetOption(options, "notation", "string", « "standard", "scientific", "engineering", "compact" », "standard").
|
||||||
if ((rounding_increment != 1) && (number_format.max_fraction_digits() != number_format.min_fraction_digits()))
|
auto notation = TRY(get_option(vm, *options, vm.names.notation, OptionType::String, { "standard"sv, "scientific"sv, "engineering"sv, "compact"sv }, "standard"sv));
|
||||||
return vm.throw_completion<RangeError>(ErrorType::IntlInvalidRoundingIncrementForFractionDigits, *rounding_increment);
|
|
||||||
|
// 22. Set numberFormat.[[Notation]] to notation.
|
||||||
|
number_format.set_notation(notation.as_string().string());
|
||||||
|
|
||||||
|
// 23. Perform ? SetNumberFormatDigitOptions(numberFormat, options, mnfdDefault, mxfdDefault, notation).
|
||||||
|
TRY(set_number_format_digit_options(vm, number_format, *options, default_min_fraction_digits, default_max_fraction_digits, number_format.notation()));
|
||||||
|
|
||||||
|
// 24. If roundingIncrement is not 1, then
|
||||||
|
if (rounding_increment != 1) {
|
||||||
|
// a. If numberFormat.[[RoundingType]] is not fractionDigits, throw a TypeError exception.
|
||||||
|
if (number_format.rounding_type() != NumberFormatBase::RoundingType::FractionDigits)
|
||||||
|
return vm.throw_completion<TypeError>(ErrorType::IntlInvalidRoundingIncrementForRoundingType, *rounding_increment, number_format.rounding_type_string());
|
||||||
|
|
||||||
|
// b. If numberFormat.[[MaximumFractionDigits]] is not equal to numberFormat.[[MinimumFractionDigits]], throw a RangeError exception.
|
||||||
|
if (number_format.max_fraction_digits() != number_format.min_fraction_digits())
|
||||||
|
return vm.throw_completion<RangeError>(ErrorType::IntlInvalidRoundingIncrementForFractionDigits, *rounding_increment);
|
||||||
|
}
|
||||||
|
|
||||||
// 25. Set numberFormat.[[RoundingIncrement]] to roundingIncrement.
|
// 25. Set numberFormat.[[RoundingIncrement]] to roundingIncrement.
|
||||||
number_format.set_rounding_increment(*rounding_increment);
|
number_format.set_rounding_increment(*rounding_increment);
|
||||||
|
|
|
@ -244,11 +244,7 @@ describe("errors", () => {
|
||||||
}).toThrowWithMessage(RangeError, "Value 5001 is NaN or is not between 1 and 5000");
|
}).toThrowWithMessage(RangeError, "Value 5001 is NaN or is not between 1 and 5000");
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
new Intl.NumberFormat("en", {
|
new Intl.NumberFormat("en", { roundingIncrement: 3 });
|
||||||
roundingIncrement: 3,
|
|
||||||
minimumFractionDigits: 2,
|
|
||||||
maximumFractionDigits: 2,
|
|
||||||
});
|
|
||||||
}).toThrowWithMessage(RangeError, "3 is not a valid rounding increment");
|
}).toThrowWithMessage(RangeError, "3 is not a valid rounding increment");
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
|
@ -459,11 +455,7 @@ describe("normal behavior", () => {
|
||||||
[1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000].forEach(
|
[1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000].forEach(
|
||||||
roundingIncrement => {
|
roundingIncrement => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
new Intl.NumberFormat("en", {
|
new Intl.NumberFormat("en", { roundingIncrement: roundingIncrement });
|
||||||
roundingIncrement: roundingIncrement,
|
|
||||||
minimumFractionDigits: 2,
|
|
||||||
maximumFractionDigits: 2,
|
|
||||||
});
|
|
||||||
}).not.toThrow();
|
}).not.toThrow();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -348,11 +348,7 @@ describe("correct behavior", () => {
|
||||||
|
|
||||||
[1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000].forEach(
|
[1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000].forEach(
|
||||||
roundingIncrement => {
|
roundingIncrement => {
|
||||||
const en2 = new Intl.NumberFormat("en", {
|
const en2 = new Intl.NumberFormat("en", { roundingIncrement: roundingIncrement });
|
||||||
roundingIncrement: roundingIncrement,
|
|
||||||
minimumFractionDigits: 2,
|
|
||||||
maximumFractionDigits: 2,
|
|
||||||
});
|
|
||||||
expect(en2.resolvedOptions().roundingIncrement).toBe(roundingIncrement);
|
expect(en2.resolvedOptions().roundingIncrement).toBe(roundingIncrement);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue