diff --git a/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.cpp b/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.cpp index e0808a8e4f..a8e11e443f 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.cpp @@ -47,6 +47,11 @@ void LocalePrototype::initialize(GlobalObject& global_object) define_direct_property(*vm.well_known_symbol_to_string_tag(), js_string(vm, "Intl.Locale"), Attribute::Configurable); define_native_accessor(vm.names.baseName, base_name, {}, Attribute::Configurable); + define_native_accessor(vm.names.calendar, calendar, {}, Attribute::Configurable); + define_native_accessor(vm.names.caseFirst, case_first, {}, Attribute::Configurable); + define_native_accessor(vm.names.collation, collation, {}, Attribute::Configurable); + define_native_accessor(vm.names.hourCycle, hour_cycle, {}, Attribute::Configurable); + define_native_accessor(vm.names.numberingSystem, numbering_system, {}, Attribute::Configurable); } // 14.3.5 Intl.Locale.prototype.toString ( ), https://tc39.es/ecma402/#sec-Intl.Locale.prototype.toString @@ -79,4 +84,29 @@ JS_DEFINE_NATIVE_GETTER(LocalePrototype::base_name) return js_string(vm, locale->language_id.to_string()); } +#define JS_ENUMERATE_LOCALE_KEYWORD_PROPERTIES \ + __JS_ENUMERATE(calendar) \ + __JS_ENUMERATE(case_first) \ + __JS_ENUMERATE(collation) \ + __JS_ENUMERATE(hour_cycle) \ + __JS_ENUMERATE(numbering_system) + +// 14.3.7 get Intl.Locale.prototype.calendar, https://tc39.es/ecma402/#sec-Intl.Locale.prototype.calendar +// 14.3.8 get Intl.Locale.prototype.caseFirst, https://tc39.es/ecma402/#sec-Intl.Locale.prototype.caseFirst +// 14.3.9 get Intl.Locale.prototype.collation, https://tc39.es/ecma402/#sec-Intl.Locale.prototype.collation +// 14.3.10 get Intl.Locale.prototype.hourCycle, https://tc39.es/ecma402/#sec-Intl.Locale.prototype.hourCycle +// 14.3.12 get Intl.Locale.prototype.numberingSystem, https://tc39.es/ecma402/#sec-Intl.Locale.prototype.numberingSystem +#define __JS_ENUMERATE(keyword) \ + JS_DEFINE_NATIVE_GETTER(LocalePrototype::keyword) \ + { \ + auto* locale_object = typed_this(global_object); \ + if (!locale_object) \ + return {}; \ + if (!locale_object->has_##keyword()) \ + return js_undefined(); \ + return js_string(vm, locale_object->keyword()); \ + } +JS_ENUMERATE_LOCALE_KEYWORD_PROPERTIES +#undef __JS_ENUMERATE + } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.h b/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.h index b6b6b76f6e..02880cb91d 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.h @@ -22,6 +22,11 @@ private: JS_DECLARE_NATIVE_FUNCTION(to_string); JS_DECLARE_NATIVE_GETTER(base_name); + JS_DECLARE_NATIVE_GETTER(calendar); + JS_DECLARE_NATIVE_GETTER(case_first); + JS_DECLARE_NATIVE_GETTER(collation); + JS_DECLARE_NATIVE_GETTER(hour_cycle); + JS_DECLARE_NATIVE_GETTER(numbering_system); }; } diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.calendar.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.calendar.js new file mode 100644 index 0000000000..de372899ad --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.calendar.js @@ -0,0 +1,16 @@ +describe("errors", () => { + test("called on non-Locale object", () => { + expect(() => { + Intl.Locale.prototype.calendar; + }).toThrowWithMessage(TypeError, "Not a Intl.Locale object"); + }); +}); + +describe("normal behavior", () => { + test("basic functionality", () => { + expect(new Intl.Locale("en").calendar).toBeUndefined(); + expect(new Intl.Locale("en-u-ca-abc").calendar).toBe("abc"); + expect(new Intl.Locale("en", { calendar: "abc" }).calendar).toBe("abc"); + expect(new Intl.Locale("en-u-ca-abc", { calendar: "def" }).calendar).toBe("def"); + }); +}); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.caseFirst.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.caseFirst.js new file mode 100644 index 0000000000..852f4ea88c --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.caseFirst.js @@ -0,0 +1,16 @@ +describe("errors", () => { + test("called on non-Locale object", () => { + expect(() => { + Intl.Locale.prototype.caseFirst; + }).toThrowWithMessage(TypeError, "Not a Intl.Locale object"); + }); +}); + +describe("normal behavior", () => { + test("basic functionality", () => { + expect(new Intl.Locale("en").caseFirst).toBeUndefined(); + expect(new Intl.Locale("en-u-kf-upper").caseFirst).toBe("upper"); + expect(new Intl.Locale("en", { caseFirst: "lower" }).caseFirst).toBe("lower"); + expect(new Intl.Locale("en-u-kf-upper", { caseFirst: "false" }).caseFirst).toBe("false"); + }); +}); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.collation.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.collation.js new file mode 100644 index 0000000000..363a679ae5 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.collation.js @@ -0,0 +1,16 @@ +describe("errors", () => { + test("called on non-Locale object", () => { + expect(() => { + Intl.Locale.prototype.collation; + }).toThrowWithMessage(TypeError, "Not a Intl.Locale object"); + }); +}); + +describe("normal behavior", () => { + test("basic functionality", () => { + expect(new Intl.Locale("en").collation).toBeUndefined(); + expect(new Intl.Locale("en-u-co-abc").collation).toBe("abc"); + expect(new Intl.Locale("en", { collation: "abc" }).collation).toBe("abc"); + expect(new Intl.Locale("en-u-co-abc", { collation: "def" }).collation).toBe("def"); + }); +}); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.hourCycle.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.hourCycle.js new file mode 100644 index 0000000000..53c8e3c44f --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.hourCycle.js @@ -0,0 +1,16 @@ +describe("errors", () => { + test("called on non-Locale object", () => { + expect(() => { + Intl.Locale.prototype.hourCycle; + }).toThrowWithMessage(TypeError, "Not a Intl.Locale object"); + }); +}); + +describe("normal behavior", () => { + test("basic functionality", () => { + expect(new Intl.Locale("en").hourCycle).toBeUndefined(); + expect(new Intl.Locale("en-u-hc-h11").hourCycle).toBe("h11"); + expect(new Intl.Locale("en", { hourCycle: "h12" }).hourCycle).toBe("h12"); + expect(new Intl.Locale("en-u-hc-h23", { hourCycle: "h24" }).hourCycle).toBe("h24"); + }); +}); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.numberingSystem.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.numberingSystem.js new file mode 100644 index 0000000000..ff1563cbbc --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.numberingSystem.js @@ -0,0 +1,18 @@ +describe("errors", () => { + test("called on non-Locale object", () => { + expect(() => { + Intl.Locale.prototype.numberingSystem; + }).toThrowWithMessage(TypeError, "Not a Intl.Locale object"); + }); +}); + +describe("normal behavior", () => { + test("basic functionality", () => { + expect(new Intl.Locale("en").numberingSystem).toBeUndefined(); + expect(new Intl.Locale("en-u-nu-abc").numberingSystem).toBe("abc"); + expect(new Intl.Locale("en", { numberingSystem: "abc" }).numberingSystem).toBe("abc"); + expect(new Intl.Locale("en-u-nu-abc", { numberingSystem: "def" }).numberingSystem).toBe( + "def" + ); + }); +});