From d56205f991147de14b11737363471a0af69154d5 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Fri, 4 Nov 2022 08:53:23 -0400 Subject: [PATCH] LibJS: Use more accurate number-to-string method in Intl.NumberFormat Intl.NumberFormat only ever wants literal number-to-digits here, without extra exponential formatting. --- .../LibJS/Runtime/Intl/MathematicalValue.cpp | 2 +- .../Libraries/LibJS/Runtime/Intl/NumberFormat.cpp | 5 ----- .../NumberFormat/NumberFormat.prototype.format.js | 13 +++++++++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Intl/MathematicalValue.cpp b/Userland/Libraries/LibJS/Runtime/Intl/MathematicalValue.cpp index 690cdce492..f53a451b8b 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/MathematicalValue.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/MathematicalValue.cpp @@ -296,7 +296,7 @@ bool MathematicalValue::is_zero() const String MathematicalValue::to_string() const { return m_value.visit( - [](double value) { return Value(value).to_string_without_side_effects(); }, + [](double value) { return number_to_string(value, NumberToStringMode::WithoutExponent); }, [](Crypto::SignedBigInteger const& value) { return value.to_base(10); }, [](auto) -> String { VERIFY_NOT_REACHED(); }); } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp index 7cc87860ba..b32fe12752 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp @@ -1032,11 +1032,6 @@ RawFormatResult to_raw_precision(MathematicalValue const& number, int min_precis } // 3. Else, else { - // FIXME: The result of these steps isn't entirely accurate for large values of 'p' (which - // defaults to 21, resulting in numbers on the order of 10^21). Either AK::format or - // our Number::toString AO (double_to_string in Value.cpp) will need to be improved - // to produce more accurate results. - // a. Let n1 and e1 each be an integer and r1 a mathematical value, with r1 = ToRawPrecisionFn(n1, e1, p), such that r1 ≤ x and r1 is maximized. auto [number1, exponent1, rounded1] = to_raw_precision_function(number, precision, PreferredResult::LessThanNumber); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js index 597c7f652c..cd9db5bfbe 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js @@ -135,6 +135,12 @@ describe("style=decimal", () => { expect(en.format(1.23456)).toBe("1.23456"); expect(en.format(1.234567)).toBe("1.23457"); expect(en.format(1.234561)).toBe("1.23456"); + expect(en.format("12344501000000000000000000000000000")).toBe( + "12,344,501,000,000,000,000,000,000,000,000,000.000" + ); + expect(en.format("-12344501000000000000000000000000000")).toBe( + "-12,344,501,000,000,000,000,000,000,000,000,000.000" + ); const ar = new Intl.NumberFormat("ar", { minimumFractionDigits: 3, @@ -149,6 +155,13 @@ describe("style=decimal", () => { expect(ar.format(1.23456)).toBe("\u0661\u066b\u0662\u0663\u0664\u0665\u0666"); expect(ar.format(1.234567)).toBe("\u0661\u066b\u0662\u0663\u0664\u0665\u0667"); expect(ar.format(1.234561)).toBe("\u0661\u066b\u0662\u0663\u0664\u0665\u0666"); + + let digits = "\u0661\u0662\u066c\u0663\u0664\u0664\u066c\u0665\u0660\u0661"; + digits += "\u066c\u0660\u0660\u0660".repeat(9); + digits += "\u066b\u0660\u0660\u0660"; + + expect(ar.format("12344501000000000000000000000000000")).toBe(digits); + expect(ar.format("-12344501000000000000000000000000000")).toBe("\u061c-" + digits); }); test("notation=scientific", () => {