diff --git a/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp index fbc8816be1..f600d3ba0c 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp @@ -80,7 +80,7 @@ ThrowCompletionOr> is_structurally_valid_language_t } // 6.2.3 CanonicalizeUnicodeLocaleId ( locale ), https://tc39.es/ecma402/#sec-canonicalizeunicodelocaleid -ThrowCompletionOr canonicalize_unicode_locale_id(VM& vm, ::Locale::LocaleID& locale) +ThrowCompletionOr canonicalize_unicode_locale_id(VM& vm, ::Locale::LocaleID& locale) { // Note: This implementation differs from the spec in how Step 3 is implemented. The spec assumes // the input to this method is a string, and is written such that operations are performed on parts @@ -118,7 +118,7 @@ ThrowCompletionOr canonicalize_unicode_locale_id(VM& vm, ::Loc VERIFY(locale_id.has_value()); // 4. Return localeId. - return locale_id->to_deprecated_string(); + return locale_id.release_value(); } // 6.3.1 IsWellFormedCurrencyCode ( currency ), https://tc39.es/ecma402/#sec-iswellformedcurrencycode @@ -183,18 +183,18 @@ bool is_well_formed_unit_identifier(StringView unit_identifier) } // 9.2.1 CanonicalizeLocaleList ( locales ), https://tc39.es/ecma402/#sec-canonicalizelocalelist -ThrowCompletionOr> canonicalize_locale_list(VM& vm, Value locales) +ThrowCompletionOr> canonicalize_locale_list(VM& vm, Value locales) { auto& realm = *vm.current_realm(); // 1. If locales is undefined, then if (locales.is_undefined()) { // a. Return a new empty List. - return Vector {}; + return Vector {}; } // 2. Let seen be a new empty List. - Vector seen; + Vector seen; Object* object = nullptr; // 3. If Type(locales) is String or Type(locales) is Object and locales has an [[InitializedLocale]] internal slot, then @@ -228,9 +228,9 @@ ThrowCompletionOr> canonicalize_locale_list(VM& vm, Val // ii. If Type(kValue) is not String or Object, throw a TypeError exception. if (!key_value.is_string() && !key_value.is_object()) - return vm.throw_completion(ErrorType::NotAnObjectOrString, key_value.to_string_without_side_effects()); + return vm.throw_completion(ErrorType::NotAnObjectOrString, key_value); - DeprecatedString tag; + String tag; // iii. If Type(kValue) is Object and kValue has an [[InitializedLocale]] internal slot, then if (key_value.is_object() && is(key_value.as_object())) { @@ -240,7 +240,7 @@ ThrowCompletionOr> canonicalize_locale_list(VM& vm, Val // iv. Else, else { // 1. Let tag be ? ToString(kValue). - tag = TRY(key_value.to_deprecated_string(vm)); + tag = TRY(key_value.to_string(vm)); } // v. If ! IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. @@ -264,7 +264,7 @@ ThrowCompletionOr> canonicalize_locale_list(VM& vm, Val } // 9.2.2 BestAvailableLocale ( availableLocales, locale ), https://tc39.es/ecma402/#sec-bestavailablelocale -Optional best_available_locale(StringView locale) +Optional best_available_locale(StringView locale) { // 1. Let candidate be locale. StringView candidate = locale; @@ -290,12 +290,12 @@ Optional best_available_locale(StringView locale) } struct MatcherResult { - DeprecatedString locale; + String locale; Vector<::Locale::Extension> extensions {}; }; // 9.2.3 LookupMatcher ( availableLocales, requestedLocales ), https://tc39.es/ecma402/#sec-lookupmatcher -static ThrowCompletionOr lookup_matcher(VM& vm, Vector const& requested_locales) +static ThrowCompletionOr lookup_matcher(VM& vm, Vector const& requested_locales) { // 1. Let result be a new Record. MatcherResult result {}; @@ -307,7 +307,7 @@ static ThrowCompletionOr lookup_matcher(VM& vm, Vectorremove_extension_type<::Locale::LocaleExtension>(); - auto no_extensions_locale = locale_id->to_deprecated_string(); + auto no_extensions_locale = TRY_OR_THROW_OOM(vm, locale_id->to_string()); // b. Let availableLocale be ! BestAvailableLocale(availableLocales, noExtensionsLocale). auto available_locale = best_available_locale(no_extensions_locale); @@ -315,7 +315,7 @@ static ThrowCompletionOr lookup_matcher(VM& vm, Vector lookup_matcher(VM& vm, Vector best_fit_matcher(VM& vm, Vector const& requested_locales) +static ThrowCompletionOr best_fit_matcher(VM& vm, Vector const& requested_locales) { // The algorithm is implementation dependent, but should produce results that a typical user of the requested locales would // perceive as at least as good as those produced by the LookupMatcher abstract operation. @@ -346,14 +346,14 @@ static ThrowCompletionOr best_fit_matcher(VM& vm, Vector insert_unicode_extension_and_canonicalize(VM& vm, ::Locale::LocaleID locale, ::Locale::LocaleExtension extension) +ThrowCompletionOr insert_unicode_extension_and_canonicalize(VM& vm, ::Locale::LocaleID locale, ::Locale::LocaleExtension extension) { // Note: This implementation differs from the spec in how the extension is inserted. The spec assumes // the input to this method is a string, and is written such that operations are performed on parts // of that string. LibUnicode gives us the parsed locale in a structure, so we can mutate that // structure directly. TRY_OR_THROW_OOM(vm, locale.extensions.try_append(move(extension))); - return TRY(canonicalize_unicode_locale_id(vm, locale)); + return canonicalize_unicode_locale_id(vm, locale); } template @@ -377,7 +377,7 @@ static auto& find_key_in_value(T& value, StringView key) } // 9.2.7 ResolveLocale ( availableLocales, requestedLocales, options, relevantExtensionKeys, localeData ), https://tc39.es/ecma402/#sec-resolvelocale -ThrowCompletionOr resolve_locale(VM& vm, Vector const& requested_locales, LocaleOptions const& options, Span relevant_extension_keys) +ThrowCompletionOr resolve_locale(VM& vm, Vector const& requested_locales, LocaleOptions const& options, Span relevant_extension_keys) { // 1. Let matcher be options.[[localeMatcher]]. auto const& matcher = options.locale_matcher; @@ -434,9 +434,9 @@ ThrowCompletionOr resolve_locale(VM& vm, Vector // f. Assert: Type(value) is either String or Null. // NOTE: ECMA-402 assumes keyLocaleData is sorted by locale preference. Our list is sorted // alphabetically, so we get the locale's preferred value from LibUnicode. - Optional value; + Optional value; if (auto preference = ::Locale::get_preferred_keyword_value_for_locale(found_locale, key); preference.has_value()) - value = *preference; + value = TRY_OR_THROW_OOM(vm, String::from_utf8(*preference)); // g. Let supportedExtensionAddition be "". Optional<::Locale::Keyword> supported_extension_addition {}; @@ -456,7 +456,7 @@ ThrowCompletionOr resolve_locale(VM& vm, Vector // a. If keyLocaleData contains requestedValue, then if (key_locale_data.contains_slow(requested_value)) { // i. Let value be requestedValue. - value = requested_value.to_deprecated_string(); + value = move(requested_value); // ii. Let supportedExtensionAddition be the string-concatenation of "-", key, "-", and value. supported_extension_addition = ::Locale::Keyword { TRY_OR_THROW_OOM(vm, String::from_utf8(key)), move(entry.value) }; @@ -465,7 +465,7 @@ ThrowCompletionOr resolve_locale(VM& vm, Vector // 4. Else if keyLocaleData contains "true", then else if (key_locale_data.contains_slow("true"sv)) { // a. Let value be "true". - value = "true"sv; + value = TRY_OR_THROW_OOM(vm, String::from_utf8("true"sv)); // b. Let supportedExtensionAddition be the string-concatenation of "-" and key. supported_extension_addition = ::Locale::Keyword { TRY_OR_THROW_OOM(vm, String::from_utf8(key)), {} }; @@ -483,14 +483,12 @@ ThrowCompletionOr resolve_locale(VM& vm, Vector if (options_value.has_value()) { // 1. Let optionsValue be the string optionsValue after performing the algorithm steps to transform Unicode extension values to canonical syntax per Unicode Technical Standard #35 LDML § 3.2.1 Canonical Unicode Locale Identifiers, treating key as ukey and optionsValue as uvalue productions. // 2. Let optionsValue be the string optionsValue after performing the algorithm steps to replace Unicode extension values with their canonical form per Unicode Technical Standard #35 LDML § 3.2.1 Canonical Unicode Locale Identifiers, treating key as ukey and optionsValue as uvalue productions. - auto options_value_string = TRY_OR_THROW_OOM(vm, String::from_deprecated_string(*options_value)); - TRY_OR_THROW_OOM(vm, ::Locale::canonicalize_unicode_extension_values(key, options_value_string, true)); - options_value = options_value_string.to_deprecated_string(); + TRY_OR_THROW_OOM(vm, ::Locale::canonicalize_unicode_extension_values(key, *options_value, true)); // 3. If optionsValue is the empty String, then if (options_value->is_empty()) { // a. Let optionsValue be "true". - options_value = "true"sv; + options_value = TRY_OR_THROW_OOM(vm, String::from_utf8("true"sv)); } } @@ -528,10 +526,10 @@ ThrowCompletionOr resolve_locale(VM& vm, Vector } // 9.2.8 LookupSupportedLocales ( availableLocales, requestedLocales ), https://tc39.es/ecma402/#sec-lookupsupportedlocales -static ThrowCompletionOr> lookup_supported_locales(VM& vm, Vector const& requested_locales) +static ThrowCompletionOr> lookup_supported_locales(VM& vm, Vector const& requested_locales) { // 1. Let subset be a new empty List. - Vector subset; + Vector subset; // 2. For each element locale of requestedLocales, do for (auto const& locale : requested_locales) { @@ -540,7 +538,7 @@ static ThrowCompletionOr> lookup_supported_locales(VM& // a. Let noExtensionsLocale be the String value that is locale with any Unicode locale extension sequences removed. locale_id->remove_extension_type<::Locale::LocaleExtension>(); - auto no_extensions_locale = locale_id->to_deprecated_string(); + auto no_extensions_locale = TRY_OR_THROW_OOM(vm, locale_id->to_string()); // b. Let availableLocale be ! BestAvailableLocale(availableLocales, noExtensionsLocale). auto available_locale = best_available_locale(no_extensions_locale); @@ -555,7 +553,7 @@ static ThrowCompletionOr> lookup_supported_locales(VM& } // 9.2.9 BestFitSupportedLocales ( availableLocales, requestedLocales ), https://tc39.es/ecma402/#sec-bestfitsupportedlocales -static ThrowCompletionOr> best_fit_supported_locales(VM& vm, Vector const& requested_locales) +static ThrowCompletionOr> best_fit_supported_locales(VM& vm, Vector const& requested_locales) { // The BestFitSupportedLocales abstract operation returns the subset of the provided BCP 47 // language priority list requestedLocales for which availableLocales has a matching locale @@ -567,7 +565,7 @@ static ThrowCompletionOr> best_fit_supported_locales(VM } // 9.2.10 SupportedLocales ( availableLocales, requestedLocales, options ), https://tc39.es/ecma402/#sec-supportedlocales -ThrowCompletionOr supported_locales(VM& vm, Vector const& requested_locales, Value options) +ThrowCompletionOr supported_locales(VM& vm, Vector const& requested_locales, Value options) { auto& realm = *vm.current_realm(); @@ -577,7 +575,7 @@ ThrowCompletionOr supported_locales(VM& vm, Vector con // 2. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit"). auto matcher = TRY(get_option(vm, *options_object, vm.names.localeMatcher, OptionType::String, { "lookup"sv, "best fit"sv }, "best fit"sv)); - Vector supported_locales; + Vector supported_locales; // 3. If matcher is "best fit", then if (TRY(matcher.as_string().utf8_string_view()) == "best fit"sv) { @@ -591,7 +589,7 @@ ThrowCompletionOr supported_locales(VM& vm, Vector con } // 5. Return CreateArrayFromList(supportedLocales). - return Array::create_from(realm, supported_locales, [&vm](auto& locale) { return PrimitiveString::create(vm, locale); }).ptr(); + return Array::create_from(realm, supported_locales, [&vm](auto& locale) { return PrimitiveString::create(vm, move(locale)); }).ptr(); } // 9.2.12 CoerceOptionsToObject ( options ), https://tc39.es/ecma402/#sec-coerceoptionstoobject diff --git a/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.h index c892857f04..3257eaa54f 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -21,23 +22,23 @@ namespace JS::Intl { struct LocaleOptions { Value locale_matcher; - Optional ca; // [[Calendar]] - Optional co; // [[Collation]] - Optional hc; // [[HourCycle]] - Optional kf; // [[CaseFirst]] - Optional kn; // [[Numeric]] - Optional nu; // [[NumberingSystem]] + Optional ca; // [[Calendar]] + Optional co; // [[Collation]] + Optional hc; // [[HourCycle]] + Optional kf; // [[CaseFirst]] + Optional kn; // [[Numeric]] + Optional nu; // [[NumberingSystem]] }; struct LocaleResult { - DeprecatedString locale; - DeprecatedString data_locale; - Optional ca; // [[Calendar]] - Optional co; // [[Collation]] - Optional hc; // [[HourCycle]] - Optional kf; // [[CaseFirst]] - Optional kn; // [[Numeric]] - Optional nu; // [[NumberingSystem]] + String locale; + String data_locale; + Optional ca; // [[Calendar]] + Optional co; // [[Collation]] + Optional hc; // [[HourCycle]] + Optional kf; // [[CaseFirst]] + Optional kn; // [[Numeric]] + Optional nu; // [[NumberingSystem]] }; struct PatternPartition { @@ -80,14 +81,14 @@ struct PatternPartitionWithSource : public PatternPartition { using StringOrBoolean = Variant; ThrowCompletionOr> is_structurally_valid_language_tag(VM&, StringView locale); -ThrowCompletionOr canonicalize_unicode_locale_id(VM&, ::Locale::LocaleID& locale); +ThrowCompletionOr canonicalize_unicode_locale_id(VM&, ::Locale::LocaleID& locale); bool is_well_formed_currency_code(StringView currency); bool is_well_formed_unit_identifier(StringView unit_identifier); -ThrowCompletionOr> canonicalize_locale_list(VM&, Value locales); -Optional best_available_locale(StringView locale); -ThrowCompletionOr insert_unicode_extension_and_canonicalize(VM&, ::Locale::LocaleID locale_id, ::Locale::LocaleExtension extension); -ThrowCompletionOr resolve_locale(VM&, Vector const& requested_locales, LocaleOptions const& options, Span relevant_extension_keys); -ThrowCompletionOr supported_locales(VM&, Vector const& requested_locales, Value options); +ThrowCompletionOr> canonicalize_locale_list(VM&, Value locales); +Optional best_available_locale(StringView locale); +ThrowCompletionOr insert_unicode_extension_and_canonicalize(VM&, ::Locale::LocaleID locale_id, ::Locale::LocaleExtension extension); +ThrowCompletionOr resolve_locale(VM&, Vector const& requested_locales, LocaleOptions const& options, Span relevant_extension_keys); +ThrowCompletionOr supported_locales(VM&, Vector const& requested_locales, Value options); ThrowCompletionOr coerce_options_to_object(VM&, Value options); ThrowCompletionOr get_string_or_boolean_option(VM&, Object const& options, PropertyKey const& property, Span values, StringOrBoolean true_value, StringOrBoolean falsy_value, StringOrBoolean fallback); ThrowCompletionOr> default_number_option(VM&, Value value, int minimum, int maximum, Optional fallback); diff --git a/Userland/Libraries/LibJS/Runtime/Intl/Collator.h b/Userland/Libraries/LibJS/Runtime/Intl/Collator.h index 72d0c84bda..bd319bc801 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/Collator.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/Collator.h @@ -7,7 +7,7 @@ #pragma once #include -#include +#include #include #include #include @@ -45,8 +45,8 @@ public: virtual ~Collator() override = default; - DeprecatedString const& locale() const { return m_locale; } - void set_locale(DeprecatedString locale) { m_locale = move(locale); } + String const& locale() const { return m_locale; } + void set_locale(String locale) { m_locale = move(locale); } Usage usage() const { return m_usage; } void set_usage(StringView usage); @@ -60,8 +60,8 @@ public: void set_case_first(StringView case_first); StringView case_first_string() const; - DeprecatedString const& collation() const { return m_collation; } - void set_collation(DeprecatedString collation) { m_collation = move(collation); } + String const& collation() const { return m_collation; } + void set_collation(String collation) { m_collation = move(collation); } bool ignore_punctuation() const { return m_ignore_punctuation; } void set_ignore_punctuation(bool ignore_punctuation) { m_ignore_punctuation = ignore_punctuation; } @@ -77,11 +77,11 @@ private: virtual void visit_edges(Visitor&) override; - DeprecatedString m_locale; // [[Locale]] + String m_locale; // [[Locale]] Usage m_usage { Usage::Sort }; // [[Usage]] Sensitivity m_sensitivity { Sensitivity::Variant }; // [[Sensitivity]] CaseFirst m_case_first { CaseFirst::False }; // [[CaseFirst]] - DeprecatedString m_collation; // [[Collation]] + String m_collation; // [[Collation]] bool m_ignore_punctuation { false }; // [[IgnorePunctuation]] bool m_numeric { false }; // [[Numeric]] CollatorCompareFunction* m_bound_compare { nullptr }; // [[BoundCompare]] diff --git a/Userland/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp index 705576ea4c..1718d76356 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp @@ -53,7 +53,7 @@ static ThrowCompletionOr initialize_collator(VM& vm, Collator& collat return vm.throw_completion(ErrorType::OptionIsNotValidValue, collation, "collation"sv); // 12. Set opt.[[co]] to collation. - opt.co = TRY(collation.as_string().deprecated_string()); + opt.co = TRY(collation.as_string().utf8_string()); } // 13. Let numeric be ? GetOption(options, "numeric", boolean, empty, undefined). @@ -62,14 +62,16 @@ static ThrowCompletionOr initialize_collator(VM& vm, Collator& collat // 14. If numeric is not undefined, then // a. Let numeric be ! ToString(numeric). // 15. Set opt.[[kn]] to numeric. - if (!numeric.is_undefined()) - opt.kn = MUST(numeric.to_deprecated_string(vm)); + if (!numeric.is_undefined()) { + // NOTE: We TRY this operation only to propagate OOM errors. + opt.kn = TRY(numeric.to_string(vm)); + } // 16. Let caseFirst be ? GetOption(options, "caseFirst", string, « "upper", "lower", "false" », undefined). // 17. Set opt.[[kf]] to caseFirst. auto case_first = TRY(get_option(vm, *options, vm.names.caseFirst, OptionType::String, { "upper"sv, "lower"sv, "false"sv }, Empty {})); if (!case_first.is_undefined()) - opt.kf = TRY(case_first.as_string().deprecated_string()); + opt.kf = TRY(case_first.as_string().utf8_string()); // 18. Let relevantExtensionKeys be %Collator%.[[RelevantExtensionKeys]]. auto relevant_extension_keys = Collator::relevant_extension_keys(); @@ -83,7 +85,7 @@ static ThrowCompletionOr initialize_collator(VM& vm, Collator& collat // 21. Let collation be r.[[co]]. // 22. If collation is null, let collation be "default". // 23. Set collator.[[Collation]] to collation. - collator.set_collation(result.co.has_value() ? result.co.release_value() : "default"); + collator.set_collation(result.co.has_value() ? result.co.release_value() : TRY_OR_THROW_OOM(vm, String::from_utf8("default"sv))); // 24. If relevantExtensionKeys contains "kn", then if (relevant_extension_keys.span().contains_slow("kn"sv) && result.kn.has_value()) { diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h index 7e9ac01710..4077f664c9 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -43,17 +44,17 @@ public: virtual ~DateTimeFormat() override = default; - DeprecatedString const& locale() const { return m_locale; } - void set_locale(DeprecatedString locale) { m_locale = move(locale); } + String const& locale() const { return m_locale; } + void set_locale(String locale) { m_locale = move(locale); } - DeprecatedString const& data_locale() const { return m_data_locale; } - void set_data_locale(DeprecatedString data_locale) { m_data_locale = move(data_locale); } + String const& data_locale() const { return m_data_locale; } + void set_data_locale(String data_locale) { m_data_locale = move(data_locale); } - DeprecatedString const& calendar() const { return m_calendar; } - void set_calendar(DeprecatedString calendar) { m_calendar = move(calendar); } + String const& calendar() const { return m_calendar; } + void set_calendar(String calendar) { m_calendar = move(calendar); } - DeprecatedString const& numbering_system() const { return m_numbering_system; } - void set_numbering_system(DeprecatedString numbering_system) { m_numbering_system = move(numbering_system); } + String const& numbering_system() const { return m_numbering_system; } + void set_numbering_system(String numbering_system) { m_numbering_system = move(numbering_system); } bool has_hour_cycle() const { return m_hour_cycle.has_value(); } ::Locale::HourCycle hour_cycle() const { return *m_hour_cycle; } @@ -134,9 +135,9 @@ private: virtual void visit_edges(Visitor&) override; - DeprecatedString m_locale; // [[Locale]] - DeprecatedString m_calendar; // [[Calendar]] - DeprecatedString m_numbering_system; // [[NumberingSystem]] + String m_locale; // [[Locale]] + String m_calendar; // [[Calendar]] + String m_numbering_system; // [[NumberingSystem]] Optional<::Locale::HourCycle> m_hour_cycle; // [[HourCycle]] DeprecatedString m_time_zone; // [[TimeZone]] Optional