diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2022-06-30 16:49:37 +0300 |
---|---|---|
committer | Idan Horowitz <idan.horowitz@gmail.com> | 2022-07-01 01:00:05 +0300 |
commit | b6b8356c0cf96a29193ec640b3cda505e36962bb (patch) | |
tree | 73336fe1c8314c38de03a470e0c7f2523dc97384 /Userland/Libraries | |
parent | 706ff5ac8385029d870c7465d7aeeae152ad376e (diff) | |
download | serenity-b6b8356c0cf96a29193ec640b3cda505e36962bb.zip |
LibJS: Implement Intl.DurationFormat.prototype.formatToParts
Diffstat (limited to 'Userland/Libraries')
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" }, + ]); + }); +}); |