From b78cbf88db383c16f7094975121b09b8822abdb3 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 30 Aug 2023 11:24:04 -0400 Subject: [PATCH] LibJS: Stop propagating small OOM errors from Intl.DateTimeFormat --- .../LibJS/Runtime/Intl/DateTimeFormat.cpp | 82 +++++++++---------- .../LibJS/Runtime/Intl/DateTimeFormat.h | 6 +- .../Intl/DateTimeFormatConstructor.cpp | 8 +- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp index 8b3161a60c..37f652bfff 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -15,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -68,7 +68,7 @@ StringView DateTimeFormat::style_to_string(Style style) } // 11.5.1 DateTimeStyleFormat ( dateStyle, timeStyle, styles ), https://tc39.es/ecma402/#sec-date-time-style-format -ThrowCompletionOr> date_time_style_format(VM& vm, StringView data_locale, DateTimeFormat& date_time_format) +Optional<::Locale::CalendarPattern> date_time_style_format(StringView data_locale, DateTimeFormat& date_time_format) { ::Locale::CalendarPattern time_format {}; ::Locale::CalendarPattern date_format {}; @@ -98,7 +98,7 @@ ThrowCompletionOr> date_time_style_format(VM // b. Let timeFormat be styles.[[TimeFormat]].[[]]. auto pattern = get_pattern(::Locale::CalendarFormatType::Time, date_time_format.time_style()); if (!pattern.has_value()) - return OptionalNone {}; + return {}; time_format = pattern.release_value(); } @@ -109,7 +109,7 @@ ThrowCompletionOr> date_time_style_format(VM // b. Let dateFormat be styles.[[DateFormat]].[[]]. auto pattern = get_pattern(::Locale::CalendarFormatType::Date, date_time_format.date_style()); if (!pattern.has_value()) - return OptionalNone {}; + return {}; date_format = pattern.release_value(); } @@ -133,11 +133,11 @@ ThrowCompletionOr> date_time_style_format(VM // d. Let connector be styles.[[DateTimeFormat]].[[]]. auto connector = get_pattern(::Locale::CalendarFormatType::DateTime, date_time_format.date_style()); if (!connector.has_value()) - return OptionalNone {}; + return {}; // e. Let pattern be the string connector with the substring "{0}" replaced with timeFormat.[[pattern]] and the substring "{1}" replaced with dateFormat.[[pattern]]. - auto pattern = TRY_OR_THROW_OOM(vm, connector->pattern.replace("{0}"sv, time_format.pattern, ReplaceMode::FirstOnly)); - pattern = TRY_OR_THROW_OOM(vm, pattern.replace("{1}"sv, date_format.pattern, ReplaceMode::FirstOnly)); + auto pattern = MUST(connector->pattern.replace("{0}"sv, time_format.pattern, ReplaceMode::FirstOnly)); + pattern = MUST(pattern.replace("{1}"sv, date_format.pattern, ReplaceMode::FirstOnly)); // f. Set format.[[pattern]] to pattern. format.pattern = move(pattern); @@ -145,8 +145,8 @@ ThrowCompletionOr> date_time_style_format(VM // g. If timeFormat has a [[pattern12]] field, then if (time_format.pattern12.has_value()) { // i. Let pattern12 be the string connector with the substring "{0}" replaced with timeFormat.[[pattern12]] and the substring "{1}" replaced with dateFormat.[[pattern]]. - auto pattern12 = TRY_OR_THROW_OOM(vm, connector->pattern.replace("{0}"sv, *time_format.pattern12, ReplaceMode::FirstOnly)); - pattern12 = TRY_OR_THROW_OOM(vm, pattern12.replace("{1}"sv, date_format.pattern, ReplaceMode::FirstOnly)); + auto pattern12 = MUST(connector->pattern.replace("{0}"sv, *time_format.pattern12, ReplaceMode::FirstOnly)); + pattern12 = MUST(pattern12.replace("{1}"sv, date_format.pattern, ReplaceMode::FirstOnly)); // ii. Set format.[[pattern12]] to pattern12. format.pattern12 = move(pattern12); @@ -526,7 +526,7 @@ ThrowCompletionOr> format_date_time_pattern(VM& vm, Dat // b. If p is "literal", then if (part == "literal"sv) { // i. Append a new Record { [[Type]]: "literal", [[Value]]: patternPart.[[Value]] } as the last element of the list result. - TRY_OR_THROW_OOM(vm, result.try_append({ "literal"sv, move(pattern_part.value) })); + result.append({ "literal"sv, move(pattern_part.value) }); } // c. Else if p is equal to "fractionalSecondDigits", then @@ -538,10 +538,10 @@ ThrowCompletionOr> format_date_time_pattern(VM& vm, Dat value = floor(value * pow(10, static_cast(*fractional_second_digits) - 3)); // iii. Let fv be FormatNumeric(nf3, v). - auto formatted_value = MUST_OR_THROW_OOM(format_numeric(vm, *number_format3, Value(value))); + auto formatted_value = MUST(format_numeric(vm, *number_format3, Value(value))); // iv. Append a new Record { [[Type]]: "fractionalSecond", [[Value]]: fv } as the last element of result. - TRY_OR_THROW_OOM(vm, result.try_append({ "fractionalSecond"sv, move(formatted_value) })); + result.append({ "fractionalSecond"sv, move(formatted_value) }); } // d. Else if p is equal to "dayPeriod", then @@ -554,10 +554,10 @@ ThrowCompletionOr> format_date_time_pattern(VM& vm, Dat // ii. Let fv be a String value representing the day period of tm in the form given by f; the String value depends upon the implementation and the effective locale of dateTimeFormat. auto symbol = resolve_day_period(data_locale, date_time_format.calendar(), style, pattern_parts, local_time); if (symbol.has_value()) - formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(*symbol)); + formatted_value = MUST(String::from_utf8(*symbol)); // iii. Append a new Record { [[Type]]: p, [[Value]]: fv } as the last element of the list result. - TRY_OR_THROW_OOM(vm, result.try_append({ "dayPeriod"sv, move(formatted_value) })); + result.append({ "dayPeriod"sv, move(formatted_value) }); } // e. Else if p is equal to "timeZoneName", then @@ -574,7 +574,7 @@ ThrowCompletionOr> format_date_time_pattern(VM& vm, Dat auto formatted_value = ::Locale::format_time_zone(data_locale, value, style, local_time.time_since_epoch()); // iv. Append a new Record { [[Type]]: p, [[Value]]: fv } as the last element of the list result. - TRY_OR_THROW_OOM(vm, result.try_append({ "timeZoneName"sv, move(formatted_value) })); + result.append({ "timeZoneName"sv, move(formatted_value) }); } // f. Else if p matches a Property column of the row in Table 6, then @@ -622,20 +622,20 @@ ThrowCompletionOr> format_date_time_pattern(VM& vm, Dat // viii. If f is "numeric", then case ::Locale::CalendarPatternStyle::Numeric: // 1. Let fv be FormatNumeric(nf, v). - formatted_value = MUST_OR_THROW_OOM(format_numeric(vm, *number_format, Value(value))); + formatted_value = MUST(format_numeric(vm, *number_format, Value(value))); break; // ix. Else if f is "2-digit", then case ::Locale::CalendarPatternStyle::TwoDigit: // 1. Let fv be FormatNumeric(nf2, v). - formatted_value = MUST_OR_THROW_OOM(format_numeric(vm, *number_format2, Value(value))); + formatted_value = MUST(format_numeric(vm, *number_format2, Value(value))); // 2. If the "length" property of fv is greater than 2, let fv be the substring of fv containing the last two characters. // NOTE: The first length check here isn't enough, but lets us avoid UTF-16 transcoding when the formatted value is ASCII. if (formatted_value.bytes_as_string_view().length() > 2) { auto utf16_formatted_value = Utf16String::create(formatted_value); if (utf16_formatted_value.length_in_code_units() > 2) - formatted_value = TRY_OR_THROW_OOM(vm, utf16_formatted_value.substring_view(utf16_formatted_value.length_in_code_units() - 2).to_utf8()); + formatted_value = MUST(utf16_formatted_value.substring_view(utf16_formatted_value.length_in_code_units() - 2).to_utf8()); } break; @@ -659,9 +659,9 @@ ThrowCompletionOr> format_date_time_pattern(VM& vm, Dat symbol = ::Locale::get_calendar_weekday_symbol(data_locale, date_time_format.calendar(), style, static_cast<::Locale::Weekday>(value)); if (symbol.has_value()) - formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(*symbol)); + formatted_value = MUST(String::from_utf8(*symbol)); else - formatted_value = TRY_OR_THROW_OOM(vm, String::number(value)); + formatted_value = MUST(String::number(value)); break; } @@ -671,7 +671,7 @@ ThrowCompletionOr> format_date_time_pattern(VM& vm, Dat } // xi. Append a new Record { [[Type]]: p, [[Value]]: fv } as the last element of the list result. - TRY_OR_THROW_OOM(vm, result.try_append({ style_and_value->name, move(formatted_value) })); + result.append({ style_and_value->name, move(formatted_value) }); } // g. Else if p is equal to "ampm", then @@ -685,17 +685,17 @@ ThrowCompletionOr> format_date_time_pattern(VM& vm, Dat if (value > 11) { // 1. Let fv be an implementation and locale dependent String value representing "post meridiem". auto symbol = ::Locale::get_calendar_day_period_symbol(data_locale, date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, ::Locale::DayPeriod::PM); - formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(symbol.value_or("PM"sv))); + formatted_value = MUST(String::from_utf8(symbol.value_or("PM"sv))); } // iii. Else, else { // 1. Let fv be an implementation and locale dependent String value representing "ante meridiem". auto symbol = ::Locale::get_calendar_day_period_symbol(data_locale, date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, ::Locale::DayPeriod::AM); - formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(symbol.value_or("AM"sv))); + formatted_value = MUST(String::from_utf8(symbol.value_or("AM"sv))); } // iv. Append a new Record { [[Type]]: "dayPeriod", [[Value]]: fv } as the last element of the list result. - TRY_OR_THROW_OOM(vm, result.try_append({ "dayPeriod"sv, move(formatted_value) })); + result.append({ "dayPeriod"sv, move(formatted_value) }); } // h. Else if p is equal to "relatedYear", then @@ -720,7 +720,7 @@ ThrowCompletionOr> format_date_time_pattern(VM& vm, Dat // to adhere to the selected locale. This depends on other generated data, so it is deferred to here. else if (part == "decimal"sv) { auto decimal_symbol = ::Locale::get_number_system_symbol(data_locale, date_time_format.numbering_system(), ::Locale::NumericSymbol::Decimal).value_or("."sv); - TRY_OR_THROW_OOM(vm, result.try_append({ "literal"sv, TRY_OR_THROW_OOM(vm, String::from_utf8(decimal_symbol)) })); + result.append({ "literal"sv, MUST(String::from_utf8(decimal_symbol)) }); } // j. Else, @@ -757,20 +757,20 @@ ThrowCompletionOr format_date_time(VM& vm, DateTimeFormat& date_time_for auto parts = TRY(partition_date_time_pattern(vm, date_time_format, time)); // 2. Let result be the empty String. - ThrowableStringBuilder result(vm); + StringBuilder result; // 3. For each Record { [[Type]], [[Value]] } part in parts, do for (auto& part : parts) { // a. Set result to the string-concatenation of result and part.[[Value]]. - TRY(result.append(part.value)); + result.append(part.value); } // 4. Return result. - return result.to_string(); + return MUST(result.to_string()); } // 11.5.8 FormatDateTimeToParts ( dateTimeFormat, x ), https://tc39.es/ecma402/#sec-formatdatetimetoparts -ThrowCompletionOr format_date_time_to_parts(VM& vm, DateTimeFormat& date_time_format, double time) +ThrowCompletionOr> format_date_time_to_parts(VM& vm, DateTimeFormat& date_time_format, double time) { auto& realm = *vm.current_realm(); @@ -802,7 +802,7 @@ ThrowCompletionOr format_date_time_to_parts(VM& vm, DateTimeFormat& date } // 5. Return result. - return result.ptr(); + return result; } template @@ -832,7 +832,7 @@ void for_each_range_pattern_field(LocalTime const& time1, LocalTime const& time2 } template -ThrowCompletionOr for_each_range_pattern_with_source(::Locale::CalendarRangePattern& pattern, Callback&& callback) +static ThrowCompletionOr for_each_range_pattern_with_source(::Locale::CalendarRangePattern& pattern, Callback&& callback) { TRY(callback(pattern.start_range, "startRange"sv)); TRY(callback(pattern.separator, "shared"sv)); @@ -1021,11 +1021,11 @@ ThrowCompletionOr> partition_date_time_range_ auto const& pattern = date_time_format.pattern(); if (range_pattern->start_range.contains("{0}"sv)) { - range_pattern->start_range = TRY_OR_THROW_OOM(vm, range_pattern->start_range.replace("{0}"sv, pattern, ReplaceMode::FirstOnly)); - range_pattern->end_range = TRY_OR_THROW_OOM(vm, range_pattern->end_range.replace("{1}"sv, pattern, ReplaceMode::FirstOnly)); + range_pattern->start_range = MUST(range_pattern->start_range.replace("{0}"sv, pattern, ReplaceMode::FirstOnly)); + range_pattern->end_range = MUST(range_pattern->end_range.replace("{1}"sv, pattern, ReplaceMode::FirstOnly)); } else { - range_pattern->start_range = TRY_OR_THROW_OOM(vm, range_pattern->start_range.replace("{1}"sv, pattern, ReplaceMode::FirstOnly)); - range_pattern->end_range = TRY_OR_THROW_OOM(vm, range_pattern->end_range.replace("{0}"sv, pattern, ReplaceMode::FirstOnly)); + range_pattern->start_range = MUST(range_pattern->start_range.replace("{1}"sv, pattern, ReplaceMode::FirstOnly)); + range_pattern->end_range = MUST(range_pattern->end_range.replace("{0}"sv, pattern, ReplaceMode::FirstOnly)); } // FIXME: The above is not sufficient. For example, if the start date is days before the end date, and only the timeStyle @@ -1058,7 +1058,7 @@ ThrowCompletionOr> partition_date_time_range_ } // h. Add all elements in partResult to result in order. - TRY_OR_THROW_OOM(vm, result.try_extend(move(part_result))); + result.extend(move(part_result)); return {}; })); @@ -1073,20 +1073,20 @@ ThrowCompletionOr format_date_time_range(VM& vm, DateTimeFormat& date_ti auto parts = TRY(partition_date_time_range_pattern(vm, date_time_format, start, end)); // 2. Let result be the empty String. - ThrowableStringBuilder result(vm); + StringBuilder result; // 3. For each Record { [[Type]], [[Value]], [[Source]] } part in parts, do for (auto& part : parts) { // a. Set result to the string-concatenation of result and part.[[Value]]. - TRY(result.append(part.value)); + result.append(part.value); } // 4. Return result. - return result.to_string(); + return MUST(result.to_string()); } // 11.5.11 FormatDateTimeRangeToParts ( dateTimeFormat, x, y ), https://tc39.es/ecma402/#sec-formatdatetimerangetoparts -ThrowCompletionOr format_date_time_range_to_parts(VM& vm, DateTimeFormat& date_time_format, double start, double end) +ThrowCompletionOr> format_date_time_range_to_parts(VM& vm, DateTimeFormat& date_time_format, double start, double end) { auto& realm = *vm.current_realm(); @@ -1121,7 +1121,7 @@ ThrowCompletionOr format_date_time_range_to_parts(VM& vm, DateTimeFormat } // 5. Return result. - return result.ptr(); + return result; } // 11.5.12 ToLocalTime ( epochNs, calendar, timeZone ), https://tc39.es/ecma402/#sec-tolocaltime diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h index fd7fbc1858..44721d0f80 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h @@ -168,16 +168,16 @@ struct LocalTime { u16 millisecond { 0 }; // [[Millisecond]] }; -ThrowCompletionOr> date_time_style_format(VM&, StringView data_locale, DateTimeFormat& date_time_format); +Optional<::Locale::CalendarPattern> date_time_style_format(StringView data_locale, DateTimeFormat& date_time_format); Optional<::Locale::CalendarPattern> basic_format_matcher(::Locale::CalendarPattern const& options, Vector<::Locale::CalendarPattern> formats); Optional<::Locale::CalendarPattern> best_fit_format_matcher(::Locale::CalendarPattern const& options, Vector<::Locale::CalendarPattern> formats); ThrowCompletionOr> format_date_time_pattern(VM&, DateTimeFormat&, Vector pattern_parts, double time, ::Locale::CalendarPattern const* range_format_options); ThrowCompletionOr> partition_date_time_pattern(VM&, DateTimeFormat&, double time); ThrowCompletionOr format_date_time(VM&, DateTimeFormat&, double time); -ThrowCompletionOr format_date_time_to_parts(VM&, DateTimeFormat&, double time); +ThrowCompletionOr> format_date_time_to_parts(VM&, DateTimeFormat&, double time); ThrowCompletionOr> partition_date_time_range_pattern(VM&, DateTimeFormat&, double start, double end); ThrowCompletionOr format_date_time_range(VM&, DateTimeFormat&, double start, double end); -ThrowCompletionOr format_date_time_range_to_parts(VM&, DateTimeFormat&, double start, double end); +ThrowCompletionOr> format_date_time_range_to_parts(VM&, DateTimeFormat&, double start, double end); ThrowCompletionOr to_local_time(VM&, Crypto::SignedBigInteger const& epoch_ns, StringView calendar, StringView time_zone); template diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp index 4ba6eb3bf8..4d99359d83 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp @@ -170,7 +170,7 @@ ThrowCompletionOr> create_date_time_format(VM& vm, // Non-standard, default_hour_cycle will be empty if Unicode data generation is disabled. if (!default_hour_cycle.has_value()) { - date_time_format->set_time_zone(TRY_OR_THROW_OOM(vm, String::from_utf8(default_time_zone()))); + date_time_format->set_time_zone(MUST(String::from_utf8(default_time_zone()))); return date_time_format; } @@ -217,7 +217,7 @@ ThrowCompletionOr> create_date_time_format(VM& vm, // 31. If timeZone is undefined, then if (time_zone_value.is_undefined()) { // a. Set timeZone to DefaultTimeZone(). - time_zone = TRY_OR_THROW_OOM(vm, String::from_utf8(default_time_zone())); + time_zone = MUST(String::from_utf8(default_time_zone())); } // 32. Else, else { @@ -231,7 +231,7 @@ ThrowCompletionOr> create_date_time_format(VM& vm, } // c. Set timeZone to CanonicalizeTimeZoneName(timeZone). - time_zone = MUST_OR_THROW_OOM(Temporal::canonicalize_time_zone_name(vm, time_zone)); + time_zone = MUST(Temporal::canonicalize_time_zone_name(vm, time_zone)); } // 33. Set dateTimeFormat.[[TimeZone]] to timeZone. @@ -327,7 +327,7 @@ ThrowCompletionOr> create_date_time_format(VM& vm, // d. Let styles be dataLocaleData.[[styles]].[[]]. // e. Let bestFormat be DateTimeStyleFormat(dateStyle, timeStyle, styles). - best_format = MUST_OR_THROW_OOM(date_time_style_format(vm, data_locale, date_time_format)); + best_format = date_time_style_format(data_locale, date_time_format); } // 44. Else, else {