diff options
author | Timothy Flynn <trflynn89@pm.me> | 2022-01-25 12:20:44 -0500 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-01-25 19:02:59 +0000 |
commit | 0c630d568721f1efba2d5c0ee72c52c08b43d6e8 (patch) | |
tree | 857269bb2ac41e2a39fe71a087f00faa91c7d329 /Userland/Libraries/LibJS | |
parent | b50880f28c6498c8458e60e2e6d2df75be44af86 (diff) | |
download | serenity-0c630d568721f1efba2d5c0ee72c52c08b43d6e8.zip |
LibJS: Implement Intl.RelativeTimeFormat.prototype.resolvedOptions
Diffstat (limited to 'Userland/Libraries/LibJS')
3 files changed, 109 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Intl/RelativeTimeFormatPrototype.cpp b/Userland/Libraries/LibJS/Runtime/Intl/RelativeTimeFormatPrototype.cpp index bccb8dbf4e..e61f12f97f 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/RelativeTimeFormatPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/RelativeTimeFormatPrototype.cpp @@ -23,6 +23,33 @@ void RelativeTimeFormatPrototype::initialize(GlobalObject& global_object) // 17.4.2 Intl.RelativeTimeFormat.prototype[ @@toStringTag ], https://tc39.es/ecma402/#sec-Intl.RelativeTimeFormat.prototype-toStringTag define_direct_property(*vm.well_known_symbol_to_string_tag(), js_string(vm, "Intl.RelativeTimeFormat"sv), Attribute::Configurable); + + u8 attr = Attribute::Writable | Attribute::Configurable; + define_native_function(vm.names.resolvedOptions, resolved_options, 0, attr); +} + +// 17.4.5 Intl.RelativeTimeFormat.prototype.resolvedOptions ( ), https://tc39.es/ecma402/#sec-intl.relativetimeformat.prototype.resolvedoptions +JS_DEFINE_NATIVE_FUNCTION(RelativeTimeFormatPrototype::resolved_options) +{ + // 1. Let relativeTimeFormat be the this value. + // 2. Perform ? RequireInternalSlot(relativeTimeFormat, [[InitializedRelativeTimeFormat]]). + auto* relative_time_format = TRY(typed_this_object(global_object)); + + // 3. Let options be ! OrdinaryObjectCreate(%Object.prototype%). + auto* options = Object::create(global_object, global_object.object_prototype()); + + // 4. For each row of Table 15, except the header row, in table order, do + // a. Let p be the Property value of the current row. + // b. Let v be the value of relativeTimeFormat's internal slot whose name is the Internal Slot value of the current row. + // c. Assert: v is not undefined. + // d. Perform ! CreateDataPropertyOrThrow(options, p, v). + MUST(options->create_data_property_or_throw(vm.names.locale, js_string(vm, relative_time_format->locale()))); + MUST(options->create_data_property_or_throw(vm.names.style, js_string(vm, relative_time_format->style_string()))); + MUST(options->create_data_property_or_throw(vm.names.numeric, js_string(vm, relative_time_format->numeric_string()))); + MUST(options->create_data_property_or_throw(vm.names.numberingSystem, js_string(vm, relative_time_format->numbering_system()))); + + // 5. Return options. + return options; } } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/RelativeTimeFormatPrototype.h b/Userland/Libraries/LibJS/Runtime/Intl/RelativeTimeFormatPrototype.h index 8d40bc1595..5df2a3d52b 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/RelativeTimeFormatPrototype.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/RelativeTimeFormatPrototype.h @@ -18,6 +18,9 @@ public: explicit RelativeTimeFormatPrototype(GlobalObject&); virtual void initialize(GlobalObject&) override; virtual ~RelativeTimeFormatPrototype() override = default; + +private: + JS_DECLARE_NATIVE_FUNCTION(resolved_options); }; } diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/RelativeTimeFormat/RelativeTimeFormat.prototype.resolvedOptions.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/RelativeTimeFormat/RelativeTimeFormat.prototype.resolvedOptions.js new file mode 100644 index 0000000000..913901855a --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/RelativeTimeFormat/RelativeTimeFormat.prototype.resolvedOptions.js @@ -0,0 +1,79 @@ +describe("correct behavior", () => { + test("length is 0", () => { + expect(Intl.RelativeTimeFormat.prototype.resolvedOptions).toHaveLength(0); + }); + + test("locale only contains relevant extension keys", () => { + const en1 = new Intl.RelativeTimeFormat("en-u-ca-islamicc"); + expect(en1.resolvedOptions().locale).toBe("en"); + + const en2 = new Intl.RelativeTimeFormat("en-u-nu-latn"); + expect(en2.resolvedOptions().locale).toBe("en-u-nu-latn"); + + const en3 = new Intl.RelativeTimeFormat("en-u-ca-islamicc-nu-latn"); + expect(en3.resolvedOptions().locale).toBe("en-u-nu-latn"); + }); + + test("numberingSystem may be set by option", () => { + const en = new Intl.RelativeTimeFormat("en", { numberingSystem: "latn" }); + expect(en.resolvedOptions().numberingSystem).toBe("latn"); + + const el = new Intl.RelativeTimeFormat("el", { numberingSystem: "latn" }); + expect(el.resolvedOptions().numberingSystem).toBe("latn"); + }); + + test("numberingSystem may be set by locale extension", () => { + const en = new Intl.RelativeTimeFormat("en-u-nu-latn"); + expect(en.resolvedOptions().numberingSystem).toBe("latn"); + + const el = new Intl.RelativeTimeFormat("el-u-nu-latn"); + expect(el.resolvedOptions().numberingSystem).toBe("latn"); + }); + + test("numberingSystem option overrides locale extension", () => { + const el = new Intl.RelativeTimeFormat("el-u-nu-latn", { numberingSystem: "grek" }); + expect(el.resolvedOptions().numberingSystem).toBe("grek"); + }); + + test("numberingSystem option limited to known 'nu' values", () => { + ["latn", "arab"].forEach(numberingSystem => { + const en = new Intl.RelativeTimeFormat("en", { numberingSystem: numberingSystem }); + expect(en.resolvedOptions().numberingSystem).toBe("latn"); + }); + + ["latn", "arab"].forEach(numberingSystem => { + const en = new Intl.RelativeTimeFormat(`en-u-nu-${numberingSystem}`); + expect(en.resolvedOptions().numberingSystem).toBe("latn"); + }); + + ["latn", "grek"].forEach(numberingSystem => { + const el = new Intl.RelativeTimeFormat("el", { numberingSystem: numberingSystem }); + expect(el.resolvedOptions().numberingSystem).toBe(numberingSystem); + }); + + ["latn", "grek"].forEach(numberingSystem => { + const el = new Intl.RelativeTimeFormat(`el-u-nu-${numberingSystem}`); + expect(el.resolvedOptions().numberingSystem).toBe(numberingSystem); + }); + }); + + test("style", () => { + const en1 = new Intl.RelativeTimeFormat("en"); + expect(en1.resolvedOptions().style).toBe("long"); + + ["long", "short", "narrow"].forEach(style => { + const en2 = new Intl.RelativeTimeFormat("en", { style: style }); + expect(en2.resolvedOptions().style).toBe(style); + }); + }); + + test("numeric", () => { + const en1 = new Intl.RelativeTimeFormat("en"); + expect(en1.resolvedOptions().numeric).toBe("always"); + + ["always", "auto"].forEach(numeric => { + const en2 = new Intl.RelativeTimeFormat("en", { numeric: numeric }); + expect(en2.resolvedOptions().numeric).toBe(numeric); + }); + }); +}); |