diff options
author | Timothy Flynn <trflynn89@pm.me> | 2022-01-30 17:36:23 -0500 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-01-31 00:32:41 +0000 |
commit | fb08a5a896a36326ddadde02bc883b4f0cac36a9 (patch) | |
tree | 3132331633bca96ea8e0b264abf605dc728cd438 /Userland/Libraries/LibJS/Runtime | |
parent | a120e85596cc671a60ed1f29c7e6d8f95870f203 (diff) | |
download | serenity-fb08a5a896a36326ddadde02bc883b4f0cac36a9.zip |
LibJS: Implement Intl.supportedValuesOf
This is a stage 3 ECMA-402 proposal:
https://tc39.es/proposal-intl-enumeration/
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/ErrorTypes.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Intl/Intl.cpp | 88 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Intl/Intl.h | 1 |
4 files changed, 91 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h index 8accef01f5..32873d98f8 100644 --- a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h +++ b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h @@ -449,6 +449,7 @@ namespace JS { P(subtract) \ P(sup) \ P(supportedLocalesOf) \ + P(supportedValuesOf) \ P(tan) \ P(tanh) \ P(test) \ diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h index b29a550493..ccb86058cf 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h @@ -37,6 +37,7 @@ M(InOperatorWithObject, "'in' operator must be used on an object") \ M(InstanceOfOperatorBadPrototype, "'prototype' property of {} is not an object") \ M(IntlInvalidDateTimeFormatOption, "Option {} cannot be set when also providing {}") \ + M(IntlInvalidKey, "{} is not a valid key") \ M(IntlInvalidLanguageTag, "{} is not a structurally valid language tag") \ M(IntlInvalidTime, "Time value must be between -8.64E15 and 8.64E15") \ M(IntlInvalidUnit, "Unit {} is not a valid time unit") \ diff --git a/Userland/Libraries/LibJS/Runtime/Intl/Intl.cpp b/Userland/Libraries/LibJS/Runtime/Intl/Intl.cpp index d404dc84a0..8bdfcb4153 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/Intl.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/Intl.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <AK/QuickSort.h> #include <LibJS/Runtime/Array.h> #include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/Intl/AbstractOperations.h> @@ -17,6 +18,11 @@ #include <LibJS/Runtime/Intl/PluralRulesConstructor.h> #include <LibJS/Runtime/Intl/RelativeTimeFormatConstructor.h> #include <LibJS/Runtime/Intl/SegmenterConstructor.h> +#include <LibJS/Runtime/Temporal/TimeZone.h> +#include <LibUnicode/CurrencyCode.h> +#include <LibUnicode/DateTimeFormat.h> +#include <LibUnicode/Locale.h> +#include <LibUnicode/NumberFormat.h> namespace JS::Intl { @@ -47,6 +53,7 @@ void Intl::initialize(GlobalObject& global_object) define_direct_property(vm.names.Segmenter, global_object.intl_segmenter_constructor(), attr); define_native_function(vm.names.getCanonicalLocales, get_canonical_locales, 1, attr); + define_native_function(vm.names.supportedValuesOf, supported_values_of, 1, attr); } // 8.3.1 Intl.getCanonicalLocales ( locales ), https://tc39.es/ecma402/#sec-intl.getcanonicallocales @@ -66,4 +73,85 @@ JS_DEFINE_NATIVE_FUNCTION(Intl::get_canonical_locales) return Array::create_from(global_object, marked_locale_list); } +// 1.4.4 AvailableTimeZones (), https://tc39.es/proposal-intl-enumeration/#sec-availablecurrencies +static Vector<StringView> available_time_zones() +{ + // 1. Let names be a List of all supported Zone and Link names in the IANA Time Zone Database. + auto names = TimeZone::all_time_zones(); + + // 2. Let result be a new empty List. + Vector<StringView> result; + + // 3. For each element name of names, do + for (auto name : names) { + // a. Assert: ! IsValidTimeZoneName( name ) is true. + // b. Let canonical be ! CanonicalizeTimeZoneName( name ). + auto canonical = TimeZone::canonicalize_time_zone(name).value(); + + // c. If result does not contain an element equal to canonical, then + if (!result.contains_slow(canonical)) { + // i. Append canonical to the end of result. + result.append(canonical); + } + } + + // 4. Sort result in order as if an Array of the same values had been sorted using %Array.prototype.sort% using undefined as comparefn. + quick_sort(result); + + // 5. Return result. + return result; +} + +// 2.2.2 Intl.supportedValuesOf ( key ), https://tc39.es/proposal-intl-enumeration/#sec-intl.supportedvaluesof +JS_DEFINE_NATIVE_FUNCTION(Intl::supported_values_of) +{ + // 1. Let key be ? ToString(key). + auto key = TRY(vm.argument(0).to_string(global_object)); + + Span<StringView const> list; + + // 2. If key is "calendar", then + if (key == "calendar"sv) { + // a. Let list be ! AvailableCalendars( ). + list = Unicode::get_available_calendars(); + } + // 3. Else if key is "collation", then + else if (key == "collation"sv) { + // a. Let list be ! AvailableCollations( ). + // NOTE: We don't yet parse any collation data, but "default" is allowed. + static constexpr auto collations = AK::Array { "default"sv }; + list = collations.span(); + } + // 4. Else if key is "currency", then + else if (key == "currency"sv) { + // a. Let list be ! AvailableCurrencies( ). + list = Unicode::get_available_currencies(); + } + // 5. Else if key is "numberingSystem", then + else if (key == "numberingSystem"sv) { + // a. Let list be ! AvailableNumberingSystems( ). + list = Unicode::get_available_number_systems(); + } + // 6. Else if key is "timeZone", then + else if (key == "timeZone"sv) { + // a. Let list be ! AvailableTimeZones( ). + static auto time_zones = available_time_zones(); + list = time_zones.span(); + } + // 7. Else if key is "unit", then + else if (key == "unit"sv) { + // a. Let list be ! AvailableUnits( ). + static auto units = sanctioned_simple_unit_identifiers(); + list = units.span(); + } + // 8. Else, + else { + // a. Throw a RangeError exception. + return vm.throw_completion<RangeError>(global_object, ErrorType::IntlInvalidKey, key); + } + + // 9. Return ! CreateArrayFromList( list ). + return Array::create_from<StringView>(global_object, list, [&](auto value) { return js_string(vm, value); }); +} + } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/Intl.h b/Userland/Libraries/LibJS/Runtime/Intl/Intl.h index fa1f69673e..603a46ff82 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/Intl.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/Intl.h @@ -20,6 +20,7 @@ public: private: JS_DECLARE_NATIVE_FUNCTION(get_canonical_locales); + JS_DECLARE_NATIVE_FUNCTION(supported_values_of); }; } |