summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2022-06-30 16:49:37 +0300
committerIdan Horowitz <idan.horowitz@gmail.com>2022-07-01 01:00:05 +0300
commitb6b8356c0cf96a29193ec640b3cda505e36962bb (patch)
tree73336fe1c8314c38de03a470e0c7f2523dc97384 /Userland/Libraries
parent706ff5ac8385029d870c7465d7aeeae152ad376e (diff)
downloadserenity-b6b8356c0cf96a29193ec640b3cda505e36962bb.zip
LibJS: Implement Intl.DurationFormat.prototype.formatToParts
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.cpp42
-rw-r--r--Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.h1
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Intl/DurationFormat/DurationFormat.prototype.formatToParts.js265
3 files changed, 308 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.cpp b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.cpp
index abd2f22540..a8862093d3 100644
--- a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.cpp
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Intl/DurationFormatPrototype.h>
@@ -26,6 +27,7 @@ void DurationFormatPrototype::initialize(GlobalObject& global_object)
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function(vm.names.format, format, 1, attr);
+ define_native_function(vm.names.formatToParts, format_to_parts, 1, attr);
define_native_function(vm.names.resolvedOptions, resolved_options, 0, attr);
}
@@ -55,6 +57,46 @@ JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::format)
return js_string(vm, result.build());
}
+// 1.4.4 Intl.DurationFormat.prototype.formatToParts ( duration ), https://tc39.es/proposal-intl-duration-format/#sec-Intl.DurationFormat.prototype.formatToParts
+JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::format_to_parts)
+{
+ // 1. Let df be this value.
+ // 2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
+ auto* duration_format = TRY(typed_this_object(global_object));
+
+ // 3. Let record be ? ToDurationRecord(duration).
+ auto record = TRY(to_duration_record(global_object, vm.argument(0)));
+
+ // 4. Let formatted be ? PartitionDurationFormatPattern(df, record).
+ auto formatted = TRY(partition_duration_format_pattern(global_object, *duration_format, record));
+
+ // 5. Let result be ! ArrayCreate(0).
+ auto* result = MUST(Array::create(global_object, 0));
+
+ // 6. Let n be 0.
+ // 7. For each element part in formatted, in List order, do
+ for (size_t n = 0; n < formatted.size(); ++n) {
+ auto const& part = formatted[n];
+
+ // a. Let obj be ! OrdinaryObjectCreate(%ObjectPrototype%).
+ auto* object = Object::create(global_object, global_object.object_prototype());
+
+ // b. Perform ! CreateDataPropertyOrThrow(obj, "type", part.[[Type]]).
+ MUST(object->create_data_property_or_throw(vm.names.type, js_string(vm, part.type)));
+
+ // c. Perform ! CreateDataPropertyOrThrow(obj, "value", part.[[Value]]).
+ MUST(object->create_data_property_or_throw(vm.names.value, js_string(vm, part.value)));
+
+ // d. Perform ! CreateDataPropertyOrThrow(result, ! ToString(n), obj).
+ MUST(result->create_data_property_or_throw(n, object));
+
+ // e. Increment n by 1.
+ }
+
+ // 7. Return result.
+ return result;
+}
+
// 1.4.5 Intl.DurationFormat.prototype.resolvedOptions ( ), https://tc39.es/proposal-intl-duration-format/#sec-Intl.DurationFormat.prototype.resolvedOptions
JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::resolved_options)
{
diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.h b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.h
index 4689fcb5aa..50140b12b7 100644
--- a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.h
+++ b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.h
@@ -21,6 +21,7 @@ public:
private:
JS_DECLARE_NATIVE_FUNCTION(format);
+ JS_DECLARE_NATIVE_FUNCTION(format_to_parts);
JS_DECLARE_NATIVE_FUNCTION(resolved_options);
};
diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/DurationFormat/DurationFormat.prototype.formatToParts.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/DurationFormat/DurationFormat.prototype.formatToParts.js
new file mode 100644
index 0000000000..56c96a4aaa
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/DurationFormat/DurationFormat.prototype.formatToParts.js
@@ -0,0 +1,265 @@
+describe("correct behavior", () => {
+ test("length is 1", () => {
+ expect(Intl.DurationFormat.prototype.formatToParts).toHaveLength(1);
+ });
+
+ test("formats duration correctly", () => {
+ const duration = {
+ years: 1,
+ months: 2,
+ weeks: 3,
+ days: 3,
+ hours: 4,
+ minutes: 5,
+ seconds: 6,
+ milliseconds: 7,
+ microseconds: 8,
+ nanoseconds: 9,
+ };
+ expect(new Intl.DurationFormat().formatToParts(duration)).toEqual([
+ { type: "element", value: "1 year" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2 months" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 weeks" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 days" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "4 hours" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "5 minutes" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "6 seconds" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "7 milliseconds" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "8 microseconds" },
+ { type: "literal", value: ", and " },
+ { type: "element", value: "9 nanoseconds" },
+ ]);
+ expect(new Intl.DurationFormat("en").formatToParts(duration)).toEqual([
+ { type: "element", value: "1 year" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2 months" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 weeks" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 days" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "4 hours" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "5 minutes" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "6 seconds" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "7 milliseconds" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "8 microseconds" },
+ { type: "literal", value: ", and " },
+ { type: "element", value: "9 nanoseconds" },
+ ]);
+ expect(new Intl.DurationFormat("en", { style: "long" }).formatToParts(duration)).toEqual([
+ { type: "element", value: "1 year" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2 months" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 weeks" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 days" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "4 hours" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "5 minutes" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "6 seconds" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "7 milliseconds" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "8 microseconds" },
+ { type: "literal", value: ", and " },
+ { type: "element", value: "9 nanoseconds" },
+ ]);
+ expect(new Intl.DurationFormat("en", { style: "short" }).formatToParts(duration)).toEqual([
+ { type: "element", value: "1 yr" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2 mths" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 wks" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 days" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "4 hr" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "5 min" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "6 sec" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "7 ms" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "8 μs" },
+ { type: "literal", value: ", and " },
+ { type: "element", value: "9 ns" },
+ ]);
+ expect(new Intl.DurationFormat("en", { style: "narrow" }).formatToParts(duration)).toEqual([
+ { type: "element", value: "1y" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2m" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3w" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3d" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "4h" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "5m" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "6s" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "7ms" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "8μs" },
+ { type: "literal", value: ", and " },
+ { type: "element", value: "9ns" },
+ ]);
+ expect(new Intl.DurationFormat("en", { style: "digital" }).formatToParts(duration)).toEqual(
+ [
+ { type: "element", value: "1y" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2m" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3w" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3d" },
+ { type: "literal", value: ", and " },
+ { type: "element", value: "4:05:06.007" },
+ ]
+ );
+ expect(
+ new Intl.DurationFormat("en", {
+ style: "narrow",
+ nanoseconds: "numeric",
+ fractionalDigits: 7,
+ }).formatToParts(duration)
+ ).toEqual([
+ { type: "element", value: "1y" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2m" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3w" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3d" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "4h" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "5m" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "6s" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "7ms" },
+ { type: "literal", value: ", and " },
+ { type: "element", value: "8.009μs" },
+ ]);
+
+ expect(new Intl.DurationFormat("de", { style: "long" }).formatToParts(duration)).toEqual([
+ { type: "element", value: "1 Jahr" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2 Monate" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 Wochen" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 Tage" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "4 Stunden" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "5 Minuten" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "6 Sekunden" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "7 Millisekunden" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "8 Mikrosekunden" },
+ { type: "literal", value: " und " },
+ { type: "element", value: "9 Nanosekunden" },
+ ]);
+ expect(new Intl.DurationFormat("de", { style: "short" }).formatToParts(duration)).toEqual([
+ { type: "element", value: "1 J" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2 Mon." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 Wo." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 Tg." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "4 Std." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "5 Min." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "6 Sek." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "7 ms" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "8 μs" },
+ { type: "literal", value: " und " },
+ { type: "element", value: "9 ns" },
+ ]);
+ expect(new Intl.DurationFormat("de", { style: "narrow" }).formatToParts(duration)).toEqual([
+ { type: "element", value: "1 J" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2 M" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 W" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 T" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "4 Std." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "5 Min." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "6 Sek." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "7 ms" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "8 μs" },
+ { type: "literal", value: " und " },
+ { type: "element", value: "9 ns" },
+ ]);
+ expect(new Intl.DurationFormat("de", { style: "digital" }).formatToParts(duration)).toEqual(
+ [
+ { type: "element", value: "1 J" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2 M" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 W" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 T" },
+ { type: "literal", value: " und " },
+ { type: "element", value: "4:05:06,007" },
+ ]
+ );
+ expect(
+ new Intl.DurationFormat("de", {
+ style: "narrow",
+ nanoseconds: "numeric",
+ fractionalDigits: 7,
+ }).formatToParts(duration)
+ ).toEqual([
+ { type: "element", value: "1 J" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "2 M" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 W" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "3 T" },
+ { type: "literal", value: ", " },
+ { type: "element", value: "4 Std." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "5 Min." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "6 Sek." },
+ { type: "literal", value: ", " },
+ { type: "element", value: "7 ms" },
+ { type: "literal", value: " und " },
+ { type: "element", value: "8,009 μs" },
+ ]);
+ });
+});