mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 06:27:45 +00:00
LibJS: Implement Intl.NumberFormat V3's [[RoundingIncrement]] changes
This commit is contained in:
parent
8ee485c350
commit
4b415a23c1
2 changed files with 137 additions and 3 deletions
|
@ -377,6 +377,20 @@ static ALWAYS_INLINE int log10floor(Value number)
|
||||||
return as_string.length() - 1;
|
return as_string.length() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value increment(GlobalObject& global_object, Value lhs)
|
||||||
|
{
|
||||||
|
if (lhs.is_number())
|
||||||
|
return Value(lhs.as_double() + 1);
|
||||||
|
return js_bigint(global_object.vm(), lhs.as_bigint().big_integer().plus("1"_bigint));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Value decrement(GlobalObject& global_object, Value lhs)
|
||||||
|
{
|
||||||
|
if (lhs.is_number())
|
||||||
|
return Value(lhs.as_double() - 1);
|
||||||
|
return js_bigint(global_object.vm(), lhs.as_bigint().big_integer().minus("1"_bigint));
|
||||||
|
}
|
||||||
|
|
||||||
static Value subtract(GlobalObject& global_object, Value lhs, Value rhs)
|
static Value subtract(GlobalObject& global_object, Value lhs, Value rhs)
|
||||||
{
|
{
|
||||||
if (lhs.is_number())
|
if (lhs.is_number())
|
||||||
|
@ -1262,9 +1276,6 @@ RawFormatResult to_raw_precision(GlobalObject& global_object, Value number, int
|
||||||
// ToRawFixedFn, https://tc39.es/proposal-intl-numberformat-v3/out/numberformat/proposed.html#eqn-ToRawFixedFn
|
// ToRawFixedFn, https://tc39.es/proposal-intl-numberformat-v3/out/numberformat/proposed.html#eqn-ToRawFixedFn
|
||||||
static auto to_raw_fixed_function(GlobalObject& global_object, Value number, int fraction, int rounding_increment, PreferredResult mode)
|
static auto to_raw_fixed_function(GlobalObject& global_object, Value number, int fraction, int rounding_increment, PreferredResult mode)
|
||||||
{
|
{
|
||||||
// FIXME: Handle NumberFormat V3's [[RoundingIncrement]] option.
|
|
||||||
(void)rounding_increment;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
Value number;
|
Value number;
|
||||||
Value rounded;
|
Value rounded;
|
||||||
|
@ -1296,6 +1307,17 @@ static auto to_raw_fixed_function(GlobalObject& global_object, Value number, int
|
||||||
result.number = js_bigint(global_object.vm(), result.number.as_bigint().big_integer().plus("1"_bigint));
|
result.number = js_bigint(global_object.vm(), result.number.as_bigint().big_integer().plus("1"_bigint));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!modulo_is_zero(result.number, rounding_increment)) {
|
||||||
|
switch (mode) {
|
||||||
|
case PreferredResult::LessThanNumber:
|
||||||
|
result.number = decrement(global_object, result.number);
|
||||||
|
break;
|
||||||
|
case PreferredResult::GreaterThanNumber:
|
||||||
|
result.number = increment(global_object, result.number);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result.rounded = divide_by_power(global_object, result.number, fraction);
|
result.rounded = divide_by_power(global_object, result.number, fraction);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -784,6 +784,118 @@ describe("style=decimal", () => {
|
||||||
expect(ar.format(-1.2)).toBe("\u061c-\u0661\u066b\u0662");
|
expect(ar.format(-1.2)).toBe("\u061c-\u0661\u066b\u0662");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("roundingIncrement", () => {
|
||||||
|
const nf = (roundingIncrement, fractionDigits) => {
|
||||||
|
return new Intl.NumberFormat([], {
|
||||||
|
roundingIncrement: roundingIncrement,
|
||||||
|
minimumFractionDigits: fractionDigits,
|
||||||
|
maximumFractionDigits: fractionDigits,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const nf1 = nf(1, 2);
|
||||||
|
expect(nf1.format(1.01)).toBe("1.01");
|
||||||
|
expect(nf1.format(1.02)).toBe("1.02");
|
||||||
|
expect(nf1.format(1.03)).toBe("1.03");
|
||||||
|
expect(nf1.format(1.04)).toBe("1.04");
|
||||||
|
expect(nf1.format(1.05)).toBe("1.05");
|
||||||
|
|
||||||
|
const nf2 = nf(2, 2);
|
||||||
|
expect(nf2.format(1.01)).toBe("1.02");
|
||||||
|
expect(nf2.format(1.02)).toBe("1.02");
|
||||||
|
expect(nf2.format(1.03)).toBe("1.04");
|
||||||
|
expect(nf2.format(1.04)).toBe("1.04");
|
||||||
|
expect(nf2.format(1.05)).toBe("1.06");
|
||||||
|
|
||||||
|
const nf5 = nf(5, 2);
|
||||||
|
expect(nf5.format(1.01)).toBe("1.00");
|
||||||
|
expect(nf5.format(1.02)).toBe("1.00");
|
||||||
|
expect(nf5.format(1.03)).toBe("1.05");
|
||||||
|
expect(nf5.format(1.04)).toBe("1.05");
|
||||||
|
expect(nf5.format(1.05)).toBe("1.05");
|
||||||
|
|
||||||
|
const nf10 = nf(10, 2);
|
||||||
|
expect(nf10.format(1.1)).toBe("1.10");
|
||||||
|
expect(nf10.format(1.12)).toBe("1.10");
|
||||||
|
expect(nf10.format(1.15)).toBe("1.20");
|
||||||
|
expect(nf10.format(1.2)).toBe("1.20");
|
||||||
|
|
||||||
|
const nf20 = nf(20, 2);
|
||||||
|
expect(nf20.format(1.05)).toBe("1.00");
|
||||||
|
expect(nf20.format(1.1)).toBe("1.20");
|
||||||
|
expect(nf20.format(1.15)).toBe("1.20");
|
||||||
|
expect(nf20.format(1.2)).toBe("1.20");
|
||||||
|
|
||||||
|
const nf25 = nf(25, 2);
|
||||||
|
expect(nf25.format(1.25)).toBe("1.25");
|
||||||
|
expect(nf25.format(1.3125)).toBe("1.25");
|
||||||
|
expect(nf25.format(1.375)).toBe("1.50");
|
||||||
|
expect(nf25.format(1.5)).toBe("1.50");
|
||||||
|
|
||||||
|
const nf50 = nf(50, 2);
|
||||||
|
expect(nf50.format(1.5)).toBe("1.50");
|
||||||
|
expect(nf50.format(1.625)).toBe("1.50");
|
||||||
|
expect(nf50.format(1.75)).toBe("2.00");
|
||||||
|
expect(nf50.format(1.875)).toBe("2.00");
|
||||||
|
expect(nf50.format(2.0)).toBe("2.00");
|
||||||
|
|
||||||
|
const nf100 = nf(100, 3);
|
||||||
|
expect(nf100.format(1.1)).toBe("1.100");
|
||||||
|
expect(nf100.format(1.125)).toBe("1.100");
|
||||||
|
expect(nf100.format(1.15)).toBe("1.200");
|
||||||
|
expect(nf100.format(1.175)).toBe("1.200");
|
||||||
|
expect(nf100.format(1.2)).toBe("1.200");
|
||||||
|
|
||||||
|
const nf200 = nf(200, 3);
|
||||||
|
expect(nf200.format(1.2)).toBe("1.200");
|
||||||
|
expect(nf200.format(1.25)).toBe("1.200");
|
||||||
|
expect(nf200.format(1.3)).toBe("1.400");
|
||||||
|
expect(nf200.format(1.35)).toBe("1.400");
|
||||||
|
expect(nf200.format(1.4)).toBe("1.400");
|
||||||
|
|
||||||
|
const nf250 = nf(250, 3);
|
||||||
|
expect(nf250.format(1.25)).toBe("1.250");
|
||||||
|
expect(nf250.format(1.3125)).toBe("1.250");
|
||||||
|
expect(nf250.format(1.375)).toBe("1.500");
|
||||||
|
expect(nf250.format(1.4375)).toBe("1.500");
|
||||||
|
expect(nf250.format(1.5)).toBe("1.500");
|
||||||
|
|
||||||
|
const nf500 = nf(500, 3);
|
||||||
|
expect(nf500.format(1.5)).toBe("1.500");
|
||||||
|
expect(nf500.format(1.625)).toBe("1.500");
|
||||||
|
expect(nf500.format(1.75)).toBe("2.000");
|
||||||
|
expect(nf500.format(1.875)).toBe("2.000");
|
||||||
|
expect(nf500.format(2.0)).toBe("2.000");
|
||||||
|
|
||||||
|
const nf1000 = nf(1000, 4);
|
||||||
|
expect(nf1000.format(1.1)).toBe("1.1000");
|
||||||
|
expect(nf1000.format(1.125)).toBe("1.1000");
|
||||||
|
expect(nf1000.format(1.15)).toBe("1.2000");
|
||||||
|
expect(nf1000.format(1.175)).toBe("1.2000");
|
||||||
|
expect(nf1000.format(1.2)).toBe("1.2000");
|
||||||
|
|
||||||
|
const nf2000 = nf(2000, 4);
|
||||||
|
expect(nf2000.format(1.2)).toBe("1.2000");
|
||||||
|
expect(nf2000.format(1.25)).toBe("1.2000");
|
||||||
|
expect(nf2000.format(1.3)).toBe("1.4000");
|
||||||
|
expect(nf2000.format(1.35)).toBe("1.4000");
|
||||||
|
expect(nf2000.format(1.4)).toBe("1.4000");
|
||||||
|
|
||||||
|
const nf2500 = nf(2500, 4);
|
||||||
|
expect(nf2500.format(1.25)).toBe("1.2500");
|
||||||
|
expect(nf2500.format(1.3125)).toBe("1.2500");
|
||||||
|
expect(nf2500.format(1.375)).toBe("1.5000");
|
||||||
|
expect(nf2500.format(1.4375)).toBe("1.5000");
|
||||||
|
expect(nf2500.format(1.5)).toBe("1.5000");
|
||||||
|
|
||||||
|
const nf5000 = nf(5000, 4);
|
||||||
|
expect(nf5000.format(1.5)).toBe("1.5000");
|
||||||
|
expect(nf5000.format(1.625)).toBe("1.5000");
|
||||||
|
expect(nf5000.format(1.75)).toBe("2.0000");
|
||||||
|
expect(nf5000.format(1.875)).toBe("2.0000");
|
||||||
|
expect(nf5000.format(2.0)).toBe("2.0000");
|
||||||
|
});
|
||||||
|
|
||||||
test("trailingZeroDisplay=auto", () => {
|
test("trailingZeroDisplay=auto", () => {
|
||||||
const en = new Intl.NumberFormat("en", {
|
const en = new Intl.NumberFormat("en", {
|
||||||
trailingZeroDisplay: "auto",
|
trailingZeroDisplay: "auto",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue