diff options
author | Timothy Flynn <trflynn89@pm.me> | 2022-01-30 13:11:19 -0500 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-01-30 20:05:27 +0000 |
commit | 687276fc384fe91ba0d5d62fd943d676fc7e4eb5 (patch) | |
tree | c6709bbc5079b8709e41558970a676b95e8d9f75 /Userland/Libraries | |
parent | d6e926e5b1cdb629b8faff05453190de90f3727c (diff) | |
download | serenity-687276fc384fe91ba0d5d62fd943d676fc7e4eb5.zip |
LibJS: Implement ECMA-402 BigInt.prototype.toLocaleString
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp | 17 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js | 79 |
2 files changed, 95 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp b/Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp index d2e2092111..ff1ef54b53 100644 --- a/Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp @@ -6,11 +6,14 @@ #include <AK/Function.h> #include <AK/TypeCasts.h> +#include <LibJS/Runtime/AbstractOperations.h> #include <LibJS/Runtime/BigIntObject.h> #include <LibJS/Runtime/BigIntPrototype.h> #include <LibJS/Runtime/Completion.h> #include <LibJS/Runtime/Error.h> #include <LibJS/Runtime/GlobalObject.h> +#include <LibJS/Runtime/Intl/NumberFormat.h> +#include <LibJS/Runtime/Intl/NumberFormatConstructor.h> namespace JS { @@ -61,9 +64,21 @@ JS_DEFINE_NATIVE_FUNCTION(BigIntPrototype::to_string) } // 21.2.3.2 BigInt.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-bigint.prototype.tolocalestring +// 19.3.1 BigInt.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sup-bigint.prototype.tolocalestring JS_DEFINE_NATIVE_FUNCTION(BigIntPrototype::to_locale_string) { - return to_string(vm, global_object); + auto locales = vm.argument(0); + auto options = vm.argument(1); + + // 1. Let x be ? thisBigIntValue(this value). + auto* bigint = TRY(this_bigint_value(global_object, vm.this_value(global_object))); + + // 2. Let numberFormat be ? Construct(%NumberFormat%, ยซ locales, options ยป). + auto* number_format = static_cast<Intl::NumberFormat*>(TRY(construct(global_object, *global_object.intl_number_format_constructor(), locales, options))); + + // 3. Return ? FormatNumeric(numberFormat, x). + auto formatted = Intl::format_numeric(global_object, *number_format, bigint); + return js_string(vm, move(formatted)); } // 21.2.3.4 BigInt.prototype.valueOf ( ), https://tc39.es/ecma262/#sec-bigint.prototype.valueof diff --git a/Userland/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js b/Userland/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js index d7b8b3484a..0fd1692292 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js +++ b/Userland/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js @@ -8,3 +8,82 @@ test("calling with non-BigInt |this|", () => { BigInt.prototype.toLocaleString.call("foo"); }).toThrowWithMessage(TypeError, "Not an object of type BigInt"); }); + +test("default", () => { + expect(1n.toLocaleString("en")).toBe("1"); + expect(12n.toLocaleString("en")).toBe("12"); + expect(123n.toLocaleString("en")).toBe("123"); + expect(123456789123456789123456789123456789n.toLocaleString("en")).toBe( + "123,456,789,123,456,789,123,456,789,123,456,789" + ); + + const ar = new Intl.NumberFormat("ar"); + expect(1n.toLocaleString("ar")).toBe("\u0661"); + expect(12n.toLocaleString("ar")).toBe("\u0661\u0662"); + expect(123n.toLocaleString("ar")).toBe("\u0661\u0662\u0663"); + expect(123456789123456789123456789123456789n.toLocaleString("ar")).toBe( + "\u0661\u0662\u0663\u066c\u0664\u0665\u0666\u066c\u0667\u0668\u0669\u066c\u0661\u0662\u0663\u066c\u0664\u0665\u0666\u066c\u0667\u0668\u0669\u066c\u0661\u0662\u0663\u066c\u0664\u0665\u0666\u066c\u0667\u0668\u0669\u066c\u0661\u0662\u0663\u066c\u0664\u0665\u0666\u066c\u0667\u0668\u0669" + ); +}); + +test("integer digits", () => { + expect(1n.toLocaleString("en", { minimumIntegerDigits: 2 })).toBe("01"); + expect(12n.toLocaleString("en", { minimumIntegerDigits: 2 })).toBe("12"); + expect(123n.toLocaleString("en", { minimumIntegerDigits: 2 })).toBe("123"); + + expect(1n.toLocaleString("ar", { minimumIntegerDigits: 2 })).toBe("\u0660\u0661"); + expect(12n.toLocaleString("ar", { minimumIntegerDigits: 2 })).toBe("\u0661\u0662"); + expect(123n.toLocaleString("ar", { minimumIntegerDigits: 2 })).toBe("\u0661\u0662\u0663"); +}); + +test("significant digits", () => { + expect( + 1n.toLocaleString("en", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("1.000"); + expect( + 12n.toLocaleString("en", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("12.00"); + expect( + 123n.toLocaleString("en", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("123.0"); + expect( + 1234n.toLocaleString("en", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("1,234"); + expect( + 12345n.toLocaleString("en", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("12,345"); + expect( + 123456n.toLocaleString("en", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("123,456"); + expect( + 1234567n.toLocaleString("en", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("1,234,570"); + expect( + 1234561n.toLocaleString("en", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("1,234,560"); + + expect( + 1n.toLocaleString("ar", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("\u0661\u066b\u0660\u0660\u0660"); + expect( + 12n.toLocaleString("ar", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("\u0661\u0662\u066b\u0660\u0660"); + expect( + 123n.toLocaleString("ar", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("\u0661\u0662\u0663\u066b\u0660"); + expect( + 1234n.toLocaleString("ar", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("\u0661\u066c\u0662\u0663\u0664"); + expect( + 12345n.toLocaleString("ar", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("\u0661\u0662\u066c\u0663\u0664\u0665"); + expect( + 123456n.toLocaleString("ar", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("\u0661\u0662\u0663\u066c\u0664\u0665\u0666"); + expect( + 1234567n.toLocaleString("ar", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("\u0661\u066c\u0662\u0663\u0664\u066c\u0665\u0667\u0660"); + expect( + 1234561n.toLocaleString("ar", { minimumSignificantDigits: 4, maximumSignificantDigits: 6 }) + ).toBe("\u0661\u066c\u0662\u0663\u0664\u066c\u0665\u0666\u0660"); +}); |