diff options
Diffstat (limited to 'Userland')
6 files changed, 55 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h index f3ef49871c..bf6f945a9f 100644 --- a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h +++ b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h @@ -258,6 +258,7 @@ namespace JS { P(hour) \ P(hour12) \ P(hourCycle) \ + P(hourCycles) \ P(hours) \ P(hoursDisplay) \ P(hoursInDay) \ diff --git a/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp b/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp index 27dd2fafb5..287ee78473 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp @@ -107,4 +107,23 @@ Array* collations_of_locale(GlobalObject& global_object, Locale const& locale_ob return create_array_from_list_or_restricted(global_object, move(list), move(restricted)); } +// 1.1.4 HourCyclesOfLocale ( loc ), https://tc39.es/proposal-intl-locale-info/#sec-hour-cycles-of-locale +Array* hour_cycles_of_locale(GlobalObject& global_object, Locale const& locale_object) +{ + // 1. Let restricted be loc.[[HourCycle]]. + Optional<String> restricted = locale_object.has_hour_cycle() ? locale_object.hour_cycle() : Optional<String> {}; + + // 2. Let locale be loc.[[Locale]]. + auto const& locale = locale_object.locale(); + + // 3. Assert: locale matches the unicode_locale_id production. + VERIFY(Unicode::parse_unicode_locale_id(locale).has_value()); + + // 4. Let list be a List of 1 or more unique hour cycle identifiers, which must be lower case String values indicating either the 12-hour format ("h11", "h12") or the 24-hour format ("h23", "h24"), sorted in descending preference of those in common use for date and time formatting in locale. + auto list = Unicode::get_keywords_for_locale(locale, "hc"sv); + + // 5. Return ! CreateArrayFromListOrRestricted( list, restricted ). + return create_array_from_list_or_restricted(global_object, move(list), move(restricted)); +} + } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/Locale.h b/Userland/Libraries/LibJS/Runtime/Intl/Locale.h index 1e8430e33e..e83ba1f0c6 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/Locale.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/Locale.h @@ -76,5 +76,6 @@ private: Array* calendars_of_locale(GlobalObject& global_object, Locale const& locale); Array* collations_of_locale(GlobalObject& global_object, Locale const& locale); +Array* hour_cycles_of_locale(GlobalObject& global_object, Locale const& locale); } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.cpp b/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.cpp index 099598de8a..ab552447e8 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.cpp @@ -40,6 +40,7 @@ void LocalePrototype::initialize(GlobalObject& global_object) define_native_accessor(vm.names.collation, collation, {}, Attribute::Configurable); define_native_accessor(vm.names.collations, collations, {}, Attribute::Configurable); define_native_accessor(vm.names.hourCycle, hour_cycle, {}, Attribute::Configurable); + define_native_accessor(vm.names.hourCycles, hour_cycles, {}, Attribute::Configurable); define_native_accessor(vm.names.numberingSystem, numbering_system, {}, Attribute::Configurable); define_native_accessor(vm.names.numeric, numeric, {}, Attribute::Configurable); define_native_accessor(vm.names.language, language, {}, Attribute::Configurable); @@ -204,10 +205,12 @@ JS_DEFINE_NATIVE_FUNCTION(LocalePrototype::region) #define JS_ENUMERATE_LOCALE_INFO_PROPERTIES \ __JS_ENUMERATE(calendars) \ - __JS_ENUMERATE(collations) + __JS_ENUMERATE(collations) \ + __JS_ENUMERATE(hour_cycles) // 1.4.16 get Intl.Locale.prototype.calendars, https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.calendars // 1.4.17 get Intl.Locale.prototype.collations, https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.collations +// 1.4.18 get Intl.Locale.prototype.hourCycles, https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.hourCycles #define __JS_ENUMERATE(keyword) \ JS_DEFINE_NATIVE_FUNCTION(LocalePrototype::keyword) \ { \ diff --git a/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.h b/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.h index 6c304d3a83..c999a7422b 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.h @@ -31,6 +31,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(collation); JS_DECLARE_NATIVE_FUNCTION(collations); JS_DECLARE_NATIVE_FUNCTION(hour_cycle); + JS_DECLARE_NATIVE_FUNCTION(hour_cycles); JS_DECLARE_NATIVE_FUNCTION(numbering_system); JS_DECLARE_NATIVE_FUNCTION(numeric); JS_DECLARE_NATIVE_FUNCTION(language); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.hourCycles.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.hourCycles.js new file mode 100644 index 0000000000..ba6620a118 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.hourCycles.js @@ -0,0 +1,29 @@ +describe("errors", () => { + test("called on non-Locale object", () => { + expect(() => { + Intl.Locale.prototype.hourCycles; + }).toThrowWithMessage(TypeError, "Not an object of type Intl.Locale"); + }); +}); + +describe("normal behavior", () => { + test("basic functionality", () => { + expect(Array.isArray(new Intl.Locale("en").hourCycles)).toBeTrue(); + expect(new Intl.Locale("en").hourCycles).toContain("h12"); + + expect(Array.isArray(new Intl.Locale("ha").hourCycles)).toBeTrue(); + expect(new Intl.Locale("ha").hourCycles).toContain("h23"); + }); + + test("extension keyword overrides default data", () => { + expect(new Intl.Locale("en-u-hc-h24").hourCycles).toEqual(["h24"]); + expect(new Intl.Locale("en", { hourCycle: "h24" }).hourCycles).toEqual(["h24"]); + + expect(new Intl.Locale("ar-u-hc-h24").hourCycles).toEqual(["h24"]); + expect(new Intl.Locale("ar", { hourCycle: "h24" }).hourCycles).toEqual(["h24"]); + + // Invalid hourCycles also take precedence when specified in the locale string. Unlike other + // properties, Locale("en", { hourCycle: "ladybird" }) will explictly throw. + expect(new Intl.Locale("en-u-hc-ladybird").hourCycles).toEqual(["ladybird"]); + }); +}); |