summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2022-01-30 13:11:19 -0500
committerLinus Groh <mail@linusgroh.de>2022-01-30 20:05:27 +0000
commit687276fc384fe91ba0d5d62fd943d676fc7e4eb5 (patch)
treec6709bbc5079b8709e41558970a676b95e8d9f75 /Userland/Libraries
parentd6e926e5b1cdb629b8faff05453190de90f3727c (diff)
downloadserenity-687276fc384fe91ba0d5d62fd943d676fc7e4eb5.zip
LibJS: Implement ECMA-402 BigInt.prototype.toLocaleString
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp17
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js79
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");
+});