From f6aa6a480c510a0972124cf077b20a1d572a65f0 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Tue, 5 Jul 2022 14:19:23 -0400 Subject: [PATCH] LibJS: Implement Intl.Locale.prototype.numberingSystems property --- .../LibJS/Runtime/CommonPropertyNames.h | 1 + .../Libraries/LibJS/Runtime/Intl/Locale.cpp | 19 ++++++++++ .../Libraries/LibJS/Runtime/Intl/Locale.h | 1 + .../LibJS/Runtime/Intl/LocalePrototype.cpp | 5 ++- .../LibJS/Runtime/Intl/LocalePrototype.h | 1 + .../Locale.prototype.numberingSystems.js | 35 +++++++++++++++++++ 6 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.numberingSystems.js diff --git a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h index bf6f945a9f..0fb65be1a3 100644 --- a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h +++ b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h @@ -355,6 +355,7 @@ namespace JS { P(notation) \ P(now) \ P(numberingSystem) \ + P(numberingSystems) \ P(numeric) \ P(of) \ P(offset) \ diff --git a/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp b/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp index 287ee78473..7b032afc46 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp @@ -126,4 +126,23 @@ Array* hour_cycles_of_locale(GlobalObject& global_object, Locale const& locale_o return create_array_from_list_or_restricted(global_object, move(list), move(restricted)); } +// 1.1.5 NumberingSystemsOfLocale ( loc ), https://tc39.es/proposal-intl-locale-info/#sec-numbering-systems-of-locale +Array* numbering_systems_of_locale(GlobalObject& global_object, Locale const& locale_object) +{ + // 1. Let restricted be loc.[[NumberingSystem]]. + Optional restricted = locale_object.has_numbering_system() ? locale_object.numbering_system() : Optional {}; + + // 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 canonical numbering system identifiers, which must be lower case String values conforming to the type sequence from UTS 35 Unicode Locale Identifier, section 3.2, sorted in descending preference of those in common use for formatting numeric values in locale. + auto list = Unicode::get_keywords_for_locale(locale, "nu"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 e83ba1f0c6..6db49aa405 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/Locale.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/Locale.h @@ -77,5 +77,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); +Array* numbering_systems_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 ab552447e8..768595b67c 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.cpp @@ -42,6 +42,7 @@ void LocalePrototype::initialize(GlobalObject& global_object) 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.numberingSystems, numbering_systems, {}, Attribute::Configurable); define_native_accessor(vm.names.numeric, numeric, {}, Attribute::Configurable); define_native_accessor(vm.names.language, language, {}, Attribute::Configurable); define_native_accessor(vm.names.script, script, {}, Attribute::Configurable); @@ -206,11 +207,13 @@ JS_DEFINE_NATIVE_FUNCTION(LocalePrototype::region) #define JS_ENUMERATE_LOCALE_INFO_PROPERTIES \ __JS_ENUMERATE(calendars) \ __JS_ENUMERATE(collations) \ - __JS_ENUMERATE(hour_cycles) + __JS_ENUMERATE(hour_cycles) \ + __JS_ENUMERATE(numbering_systems) // 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 +// 1.4.19 get Intl.Locale.prototype.numberingSystems, https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.numberingSystems #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 c999a7422b..5e3af11f97 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/LocalePrototype.h @@ -33,6 +33,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(hour_cycle); JS_DECLARE_NATIVE_FUNCTION(hour_cycles); JS_DECLARE_NATIVE_FUNCTION(numbering_system); + JS_DECLARE_NATIVE_FUNCTION(numbering_systems); JS_DECLARE_NATIVE_FUNCTION(numeric); JS_DECLARE_NATIVE_FUNCTION(language); JS_DECLARE_NATIVE_FUNCTION(script); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.numberingSystems.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.numberingSystems.js new file mode 100644 index 0000000000..473f596937 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/Locale/Locale.prototype.numberingSystems.js @@ -0,0 +1,35 @@ +describe("errors", () => { + test("called on non-Locale object", () => { + expect(() => { + Intl.Locale.prototype.numberingSystems; + }).toThrowWithMessage(TypeError, "Not an object of type Intl.Locale"); + }); +}); + +describe("normal behavior", () => { + test("basic functionality", () => { + expect(Array.isArray(new Intl.Locale("en").numberingSystems)).toBeTrue(); + expect(new Intl.Locale("en").numberingSystems).toEqual(["latn"]); + + expect(Array.isArray(new Intl.Locale("ar").numberingSystems)).toBeTrue(); + expect(new Intl.Locale("ar").numberingSystems).toEqual(["arab", "latn"]); + }); + + test("extension keyword overrides default data", () => { + expect(new Intl.Locale("en-u-nu-deva").numberingSystems).toEqual(["deva"]); + expect(new Intl.Locale("en", { numberingSystem: "deva" }).numberingSystems).toEqual([ + "deva", + ]); + + expect(new Intl.Locale("ar-u-nu-bali").numberingSystems).toEqual(["bali"]); + expect(new Intl.Locale("ar", { numberingSystem: "bali" }).numberingSystems).toEqual([ + "bali", + ]); + + // Invalid numberingSystems also take precedence. + expect(new Intl.Locale("en-u-nu-ladybird").numberingSystems).toEqual(["ladybird"]); + expect(new Intl.Locale("en", { numberingSystem: "ladybird" }).numberingSystems).toEqual([ + "ladybird", + ]); + }); +});