浏览代码

LibJS: Propagate OOM errors from the PartitionPattern Abstract Operation

Timothy Flynn 2 年之前
父节点
当前提交
1e6e719592

+ 1 - 1
Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp

@@ -74,7 +74,7 @@ JS_DEFINE_NATIVE_FUNCTION(BigIntPrototype::to_locale_string)
     auto* number_format = static_cast<Intl::NumberFormat*>(TRY(construct(vm, *realm.intrinsics().intl_number_format_constructor(), locales, options)).ptr());
 
     // 3. Return ? FormatNumeric(numberFormat, x).
-    auto formatted = Intl::format_numeric(vm, *number_format, Value(bigint));
+    auto formatted = TRY(Intl::format_numeric(vm, *number_format, Value(bigint)));
     return PrimitiveString::create(vm, move(formatted));
 }
 

+ 4 - 4
Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp

@@ -680,7 +680,7 @@ ThrowCompletionOr<Optional<int>> get_number_option(VM& vm, Object const& options
 }
 
 // 9.2.16 PartitionPattern ( pattern ), https://tc39.es/ecma402/#sec-partitionpattern
-Vector<PatternPartition> partition_pattern(StringView pattern)
+ThrowCompletionOr<Vector<PatternPartition>> partition_pattern(VM& vm, StringView pattern)
 {
     // 1. Let result be a new empty List.
     Vector<PatternPartition> result;
@@ -709,14 +709,14 @@ Vector<PatternPartition> partition_pattern(StringView pattern)
             auto literal = pattern.substring_view(next_index, *begin_index - next_index);
 
             // ii. Append a new Record { [[Type]]: "literal", [[Value]]: literal } as the last element of the list result.
-            result.append({ "literal"sv, literal });
+            TRY_OR_THROW_OOM(vm, result.try_append({ "literal"sv, literal }));
         }
 
         // d. Let p be the substring of pattern from position beginIndex, exclusive, to position endIndex, exclusive.
         auto partition = pattern.substring_view(*begin_index + 1, end_index - *begin_index - 1);
 
         // e. Append a new Record { [[Type]]: p, [[Value]]: undefined } as the last element of the list result.
-        result.append({ partition, {} });
+        TRY_OR_THROW_OOM(vm, result.try_append({ partition, {} }));
 
         // f. Set nextIndex to endIndex + 1.
         next_index = end_index + 1;
@@ -731,7 +731,7 @@ Vector<PatternPartition> partition_pattern(StringView pattern)
         auto literal = pattern.substring_view(next_index);
 
         // b. Append a new Record { [[Type]]: "literal", [[Value]]: literal } as the last element of the list result.
-        result.append({ "literal"sv, literal });
+        TRY_OR_THROW_OOM(vm, result.try_append({ "literal"sv, literal }));
     }
 
     // 8. Return result.

+ 1 - 1
Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.h

@@ -92,7 +92,7 @@ ThrowCompletionOr<Object*> coerce_options_to_object(VM&, Value options);
 ThrowCompletionOr<StringOrBoolean> get_string_or_boolean_option(VM&, Object const& options, PropertyKey const& property, Span<StringView const> values, StringOrBoolean true_value, StringOrBoolean falsy_value, StringOrBoolean fallback);
 ThrowCompletionOr<Optional<int>> default_number_option(VM&, Value value, int minimum, int maximum, Optional<int> fallback);
 ThrowCompletionOr<Optional<int>> get_number_option(VM&, Object const& options, PropertyKey const& property, int minimum, int maximum, Optional<int> fallback);
-Vector<PatternPartition> partition_pattern(StringView pattern);
+ThrowCompletionOr<Vector<PatternPartition>> partition_pattern(VM&, StringView pattern);
 
 template<size_t Size>
 ThrowCompletionOr<StringOrBoolean> get_string_or_boolean_option(VM& vm, Object const& options, PropertyKey const& property, StringView const (&values)[Size], StringOrBoolean true_value, StringOrBoolean falsy_value, StringOrBoolean fallback)

+ 6 - 6
Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp

@@ -621,7 +621,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
             value = floor(value * pow(10, static_cast<int>(*fractional_second_digits) - 3));
 
             // iii. Let fv be FormatNumeric(nf3, v).
-            auto formatted_value = format_numeric(vm, *number_format3, Value(value));
+            auto formatted_value = TRY(format_numeric(vm, *number_format3, Value(value)));
 
             // iv. Append a new Record { [[Type]]: "fractionalSecond", [[Value]]: fv } as the last element of result.
             result.append({ "fractionalSecond"sv, move(formatted_value) });
@@ -705,13 +705,13 @@ ThrowCompletionOr<Vector<PatternPartition>> 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 = format_numeric(vm, *number_format, Value(value));
+                formatted_value = TRY(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 = format_numeric(vm, *number_format2, Value(value));
+                formatted_value = TRY(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.
@@ -820,7 +820,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
 ThrowCompletionOr<Vector<PatternPartition>> partition_date_time_pattern(VM& vm, DateTimeFormat& date_time_format, double time)
 {
     // 1. Let patternParts be PartitionPattern(dateTimeFormat.[[Pattern]]).
-    auto pattern_parts = partition_pattern(date_time_format.pattern());
+    auto pattern_parts = TRY(partition_pattern(vm, date_time_format.pattern()));
 
     // 2. Let result be ? FormatDateTimePattern(dateTimeFormat, patternParts, x, undefined).
     auto result = TRY(format_date_time_pattern(vm, date_time_format, move(pattern_parts), time, nullptr));
@@ -1067,7 +1067,7 @@ ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_
         auto const& pattern = date_time_format.pattern();
 
         // b. Let patternParts be PartitionPattern(pattern).
-        auto pattern_parts = partition_pattern(pattern);
+        auto pattern_parts = TRY(partition_pattern(vm, pattern));
 
         // c. Let result be ? FormatDateTimePattern(dateTimeFormat, patternParts, x, undefined).
         auto raw_result = TRY(format_date_time_pattern(vm, date_time_format, move(pattern_parts), start, nullptr));
@@ -1124,7 +1124,7 @@ ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_
         auto time = ((source == "startRange") || (source == "shared")) ? start : end;
 
         // e. Let patternParts be PartitionPattern(pattern).
-        auto pattern_parts = partition_pattern(pattern);
+        auto pattern_parts = TRY(partition_pattern(vm, pattern));
 
         // f. Let partResult be ? FormatDateTimePattern(dateTimeFormat, patternParts, z, rangePattern).
         auto raw_part_result = TRY(format_date_time_pattern(vm, date_time_format, move(pattern_parts), time, &range_pattern.value()));

+ 7 - 4
Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp

@@ -336,7 +336,7 @@ ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(VM& vm, Depreca
 }
 
 // 1.1.7 PartitionDurationFormatPattern ( durationFormat, duration ), https://tc39.es/proposal-intl-duration-format/#sec-partitiondurationformatpattern
-Vector<PatternPartition> partition_duration_format_pattern(VM& vm, DurationFormat const& duration_format, Temporal::DurationRecord const& duration)
+ThrowCompletionOr<Vector<PatternPartition>> partition_duration_format_pattern(VM& vm, DurationFormat const& duration_format, Temporal::DurationRecord const& duration)
 {
     auto& realm = *vm.current_realm();
 
@@ -445,7 +445,8 @@ Vector<PatternPartition> partition_duration_format_pattern(VM& vm, DurationForma
                 // 3. Let dataLocaleData be %DurationFormat%.[[LocaleData]].[[<dataLocale>]].
 
                 // 4. Let num be ! FormatNumeric(nf, 𝔽(value)).
-                auto number = format_numeric(vm, *number_format, MathematicalValue(value));
+                // NOTE: We TRY this operation only to propagate OOM errors.
+                auto number = TRY(format_numeric(vm, *number_format, MathematicalValue(value)));
 
                 // 5. Append the new Record { [[Type]]: unit, [[Value]]: num} to the end of result.
                 result.append({ unit, number });
@@ -504,7 +505,8 @@ Vector<PatternPartition> partition_duration_format_pattern(VM& vm, DurationForma
                 auto* number_format = static_cast<NumberFormat*>(MUST(construct(vm, *realm.intrinsics().intl_number_format_constructor(), PrimitiveString::create(vm, duration_format.locale()), number_format_options)).ptr());
 
                 // 5. Let parts be ! PartitionNumberPattern(nf, 𝔽(value)).
-                auto parts = partition_number_pattern(vm, *number_format, MathematicalValue(value));
+                // NOTE: We TRY this operation only to propagate OOM errors.
+                auto parts = TRY(partition_number_pattern(vm, *number_format, MathematicalValue(value)));
 
                 // 6. Let concat be an empty String.
                 StringBuilder concat;
@@ -564,7 +566,8 @@ Vector<PatternPartition> partition_duration_format_pattern(VM& vm, DurationForma
     }
 
     // 10. Set result to ! CreatePartsFromList(lf, result).
-    auto final_result = create_parts_from_list(*list_format, string_result);
+    // NOTE: We TRY this operation only to propagate OOM errors.
+    auto final_result = TRY(create_parts_from_list(vm, *list_format, string_result));
 
     // 11. Return result.
     return final_result;

+ 1 - 1
Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h

@@ -225,6 +225,6 @@ ThrowCompletionOr<Temporal::DurationRecord> to_duration_record(VM&, Value input)
 i8 duration_record_sign(Temporal::DurationRecord const&);
 bool is_valid_duration_record(Temporal::DurationRecord const&);
 ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(VM&, DeprecatedString const& unit, Object const& options, StringView base_style, Span<StringView const> styles_list, StringView digital_base, StringView previous_style);
-Vector<PatternPartition> partition_duration_format_pattern(VM&, DurationFormat const&, Temporal::DurationRecord const& duration);
+ThrowCompletionOr<Vector<PatternPartition>> partition_duration_format_pattern(VM&, DurationFormat const&, Temporal::DurationRecord const& duration);
 
 }

+ 2 - 2
Userland/Libraries/LibJS/Runtime/Intl/DurationFormatPrototype.cpp

@@ -43,7 +43,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::format)
     auto record = TRY(to_duration_record(vm, vm.argument(0)));
 
     // 4. Let parts be PartitionDurationFormatPattern(df, record).
-    auto parts = partition_duration_format_pattern(vm, *duration_format, record);
+    auto parts = TRY(partition_duration_format_pattern(vm, *duration_format, record));
 
     // 5. Let result be a new empty String.
     StringBuilder result;
@@ -71,7 +71,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::format_to_parts)
     auto record = TRY(to_duration_record(vm, vm.argument(0)));
 
     // 4. Let parts be PartitionDurationFormatPattern(df, record).
-    auto parts = partition_duration_format_pattern(vm, *duration_format, record);
+    auto parts = TRY(partition_duration_format_pattern(vm, *duration_format, record));
 
     // 5. Let result be ! ArrayCreate(0).
     auto result = MUST(Array::create(realm, 0));

+ 16 - 12
Userland/Libraries/LibJS/Runtime/Intl/ListFormat.cpp

@@ -46,10 +46,11 @@ StringView ListFormat::type_string() const
 }
 
 // 13.5.1 DeconstructPattern ( pattern, placeables ), https://tc39.es/ecma402/#sec-deconstructpattern
-Vector<PatternPartition> deconstruct_pattern(StringView pattern, Placeables placeables)
+ThrowCompletionOr<Vector<PatternPartition>> deconstruct_pattern(VM& vm, StringView pattern, Placeables placeables)
 {
     // 1. Let patternParts be ! PartitionPattern(pattern).
-    auto pattern_parts = partition_pattern(pattern);
+    // NOTE: We TRY this operation only to propagate OOM errors.
+    auto pattern_parts = TRY(partition_pattern(vm, pattern));
 
     // 2. Let result be a new empty List.
     Vector<PatternPartition> result {};
@@ -93,11 +94,11 @@ Vector<PatternPartition> deconstruct_pattern(StringView pattern, Placeables plac
 }
 
 // 13.5.2 CreatePartsFromList ( listFormat, list ), https://tc39.es/ecma402/#sec-createpartsfromlist
-Vector<PatternPartition> create_parts_from_list(ListFormat const& list_format, Vector<DeprecatedString> const& list)
+ThrowCompletionOr<Vector<PatternPartition>> create_parts_from_list(VM& vm, ListFormat const& list_format, Vector<DeprecatedString> const& list)
 {
     auto list_patterns = ::Locale::get_locale_list_patterns(list_format.locale(), list_format.type_string(), list_format.style());
     if (!list_patterns.has_value())
-        return {};
+        return Vector<PatternPartition> {};
 
     // 1. Let size be the number of elements of list.
     auto size = list.size();
@@ -105,7 +106,7 @@ Vector<PatternPartition> create_parts_from_list(ListFormat const& list_format, V
     // 2. If size is 0, then
     if (size == 0) {
         // a. Return a new empty List.
-        return {};
+        return Vector<PatternPartition> {};
     }
 
     // 3. If size is 2, then
@@ -126,7 +127,7 @@ Vector<PatternPartition> create_parts_from_list(ListFormat const& list_format, V
         placeables.set("1"sv, move(second));
 
         // f. Return ! DeconstructPattern(pattern, placeables).
-        return deconstruct_pattern(pattern, move(placeables));
+        return deconstruct_pattern(vm, pattern, move(placeables));
     }
 
     // 4. Let last be a new Record { [[Type]]: "element", [[Value]]: list[size - 1] }.
@@ -172,7 +173,8 @@ Vector<PatternPartition> create_parts_from_list(ListFormat const& list_format, V
         placeables.set("1"sv, move(parts));
 
         // g. Set parts to ! DeconstructPattern(pattern, placeables).
-        parts = deconstruct_pattern(pattern, move(placeables));
+        // NOTE: We TRY this operation only to propagate OOM errors.
+        parts = TRY(deconstruct_pattern(vm, pattern, move(placeables)));
 
         // h. Decrement i by 1.
     } while (i-- != 0);
@@ -182,10 +184,11 @@ Vector<PatternPartition> create_parts_from_list(ListFormat const& list_format, V
 }
 
 // 13.5.3 FormatList ( listFormat, list ), https://tc39.es/ecma402/#sec-formatlist
-DeprecatedString format_list(ListFormat const& list_format, Vector<DeprecatedString> const& list)
+ThrowCompletionOr<DeprecatedString> format_list(VM& vm, ListFormat const& list_format, Vector<DeprecatedString> const& list)
 {
     // 1. Let parts be ! CreatePartsFromList(listFormat, list).
-    auto parts = create_parts_from_list(list_format, list);
+    // NOTE: We TRY this operation only to propagate OOM errors.
+    auto parts = TRY(create_parts_from_list(vm, list_format, list));
 
     // 2. Let result be an empty String.
     StringBuilder result;
@@ -201,12 +204,13 @@ DeprecatedString format_list(ListFormat const& list_format, Vector<DeprecatedStr
 }
 
 // 13.5.4 FormatListToParts ( listFormat, list ), https://tc39.es/ecma402/#sec-formatlisttoparts
-Array* format_list_to_parts(VM& vm, ListFormat const& list_format, Vector<DeprecatedString> const& list)
+ThrowCompletionOr<Array*> format_list_to_parts(VM& vm, ListFormat const& list_format, Vector<DeprecatedString> const& list)
 {
     auto& realm = *vm.current_realm();
 
     // 1. Let parts be ! CreatePartsFromList(listFormat, list).
-    auto parts = create_parts_from_list(list_format, list);
+    // NOTE: We TRY this operation only to propagate OOM errors.
+    auto parts = TRY(create_parts_from_list(vm, list_format, list));
 
     // 2. Let result be ! ArrayCreate(0).
     auto result = MUST(Array::create(realm, 0));
@@ -233,7 +237,7 @@ Array* format_list_to_parts(VM& vm, ListFormat const& list_format, Vector<Deprec
     }
 
     // 5. Return result.
-    return result;
+    return result.ptr();
 }
 
 // 13.5.5 StringListFromIterable ( iterable ), https://tc39.es/ecma402/#sec-createstringlistfromiterable

+ 4 - 4
Userland/Libraries/LibJS/Runtime/Intl/ListFormat.h

@@ -51,10 +51,10 @@ private:
 
 using Placeables = HashMap<StringView, Variant<PatternPartition, Vector<PatternPartition>>>;
 
-Vector<PatternPartition> deconstruct_pattern(StringView pattern, Placeables);
-Vector<PatternPartition> create_parts_from_list(ListFormat const&, Vector<DeprecatedString> const& list);
-DeprecatedString format_list(ListFormat const&, Vector<DeprecatedString> const& list);
-Array* format_list_to_parts(VM&, ListFormat const&, Vector<DeprecatedString> const& list);
+ThrowCompletionOr<Vector<PatternPartition>> deconstruct_pattern(VM&, StringView pattern, Placeables);
+ThrowCompletionOr<Vector<PatternPartition>> create_parts_from_list(VM&, ListFormat const&, Vector<DeprecatedString> const& list);
+ThrowCompletionOr<DeprecatedString> format_list(VM&, ListFormat const&, Vector<DeprecatedString> const& list);
+ThrowCompletionOr<Array*> format_list_to_parts(VM&, ListFormat const&, Vector<DeprecatedString> const& list);
 ThrowCompletionOr<Vector<DeprecatedString>> string_list_from_iterable(VM&, Value iterable);
 
 }

+ 4 - 2
Userland/Libraries/LibJS/Runtime/Intl/ListFormatPrototype.cpp

@@ -46,7 +46,8 @@ JS_DEFINE_NATIVE_FUNCTION(ListFormatPrototype::format)
     auto string_list = TRY(string_list_from_iterable(vm, list));
 
     // 4. Return ! FormatList(lf, stringList).
-    auto formatted = format_list(*list_format, string_list);
+    // NOTE: We TRY this operation only to propagate OOM errors.
+    auto formatted = TRY(format_list(vm, *list_format, string_list));
     return PrimitiveString::create(vm, move(formatted));
 }
 
@@ -63,7 +64,8 @@ JS_DEFINE_NATIVE_FUNCTION(ListFormatPrototype::format_to_parts)
     auto string_list = TRY(string_list_from_iterable(vm, list));
 
     // 4. Return ! FormatListToParts(lf, stringList).
-    return format_list_to_parts(vm, *list_format, string_list);
+    // NOTE: We TRY this operation only to propagate OOM errors.
+    return TRY(format_list_to_parts(vm, *list_format, string_list));
 }
 
 // 13.3.5 Intl.ListFormat.prototype.resolvedOptions ( ), https://tc39.es/ecma402/#sec-Intl.ListFormat.prototype.resolvedoptions

+ 15 - 17
Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp

@@ -518,7 +518,7 @@ FormatResult format_numeric_to_string(NumberFormatBase const& intl_object, Mathe
 
 // 15.5.4 PartitionNumberPattern ( numberFormat, x ), https://tc39.es/ecma402/#sec-partitionnumberpattern
 // 1.5.4 PartitionNumberPattern ( numberFormat, x ), https://tc39.es/proposal-intl-numberformat-v3/out/numberformat/proposed.html#sec-partitionnumberpattern
-Vector<PatternPartition> partition_number_pattern(VM& vm, NumberFormat& number_format, MathematicalValue number)
+ThrowCompletionOr<Vector<PatternPartition>> partition_number_pattern(VM& vm, NumberFormat& number_format, MathematicalValue number)
 {
     // 1. Let exponent be 0.
     int exponent = 0;
@@ -575,13 +575,13 @@ Vector<PatternPartition> partition_number_pattern(VM& vm, NumberFormat& number_f
     // 6. Let pattern be GetNumberFormatPattern(numberFormat, x).
     auto pattern = get_number_format_pattern(vm, number_format, number, found_pattern);
     if (!pattern.has_value())
-        return {};
+        return Vector<PatternPartition> {};
 
     // 7. Let result be a new empty List.
     Vector<PatternPartition> result;
 
     // 8. Let patternParts be PartitionPattern(pattern).
-    auto pattern_parts = pattern->visit([](auto const& p) { return partition_pattern(p); });
+    auto pattern_parts = TRY(pattern->visit([&](auto const& p) { return partition_pattern(vm, p); }));
 
     // 9. For each Record { [[Type]], [[Value]] } patternPart of patternParts, do
     for (auto& pattern_part : pattern_parts) {
@@ -597,7 +597,7 @@ Vector<PatternPartition> partition_number_pattern(VM& vm, NumberFormat& number_f
         // c. Else if p is equal to "number", then
         else if (part == "number"sv) {
             // i. Let notationSubParts be PartitionNotationSubPattern(numberFormat, x, n, exponent).
-            auto notation_sub_parts = partition_notation_sub_pattern(number_format, number, formatted_string, exponent);
+            auto notation_sub_parts = TRY(partition_notation_sub_pattern(vm, number_format, number, formatted_string, exponent));
             // ii. Append all elements of notationSubParts to result.
             result.extend(move(notation_sub_parts));
         }
@@ -715,14 +715,14 @@ static Vector<StringView> separate_integer_into_groups(::Locale::NumberGroupings
 
 // 15.5.5 PartitionNotationSubPattern ( numberFormat, x, n, exponent ), https://tc39.es/ecma402/#sec-partitionnotationsubpattern
 // 1.5.5 PartitionNotationSubPattern ( numberFormat, x, n, exponent ), https://tc39.es/proposal-intl-numberformat-v3/out/numberformat/proposed.html#sec-partitionnotationsubpattern
-Vector<PatternPartition> partition_notation_sub_pattern(NumberFormat& number_format, MathematicalValue const& number, DeprecatedString formatted_string, int exponent)
+ThrowCompletionOr<Vector<PatternPartition>> partition_notation_sub_pattern(VM& vm, NumberFormat& number_format, MathematicalValue const& number, DeprecatedString formatted_string, int exponent)
 {
     // 1. Let result be a new empty List.
     Vector<PatternPartition> result;
 
     auto grouping_sizes = ::Locale::get_number_system_groupings(number_format.data_locale(), number_format.numbering_system());
     if (!grouping_sizes.has_value())
-        return {};
+        return Vector<PatternPartition> {};
 
     // 2. If x is NaN, then
     if (number.is_nan()) {
@@ -739,10 +739,10 @@ Vector<PatternPartition> partition_notation_sub_pattern(NumberFormat& number_for
         // a. Let notationSubPattern be GetNotationSubPattern(numberFormat, exponent).
         auto notation_sub_pattern = get_notation_sub_pattern(number_format, exponent);
         if (!notation_sub_pattern.has_value())
-            return {};
+            return Vector<PatternPartition> {};
 
         // b. Let patternParts be PartitionPattern(notationSubPattern).
-        auto pattern_parts = partition_pattern(*notation_sub_pattern);
+        auto pattern_parts = TRY(partition_pattern(vm, *notation_sub_pattern));
 
         // c. For each Record { [[Type]], [[Value]] } patternPart of patternParts, do
         for (auto& pattern_part : pattern_parts) {
@@ -898,11 +898,10 @@ Vector<PatternPartition> partition_notation_sub_pattern(NumberFormat& number_for
 }
 
 // 15.5.6 FormatNumeric ( numberFormat, x ), https://tc39.es/ecma402/#sec-formatnumber
-DeprecatedString format_numeric(VM& vm, NumberFormat& number_format, MathematicalValue number)
+ThrowCompletionOr<DeprecatedString> format_numeric(VM& vm, NumberFormat& number_format, MathematicalValue number)
 {
     // 1. Let parts be ? PartitionNumberPattern(numberFormat, x).
-    // Note: Our implementation of PartitionNumberPattern does not throw.
-    auto parts = partition_number_pattern(vm, number_format, move(number));
+    auto parts = TRY(partition_number_pattern(vm, number_format, move(number)));
 
     // 2. Let result be the empty String.
     StringBuilder result;
@@ -918,13 +917,12 @@ DeprecatedString format_numeric(VM& vm, NumberFormat& number_format, Mathematica
 }
 
 // 15.5.7 FormatNumericToParts ( numberFormat, x ), https://tc39.es/ecma402/#sec-formatnumbertoparts
-Array* format_numeric_to_parts(VM& vm, NumberFormat& number_format, MathematicalValue number)
+ThrowCompletionOr<Array*> format_numeric_to_parts(VM& vm, NumberFormat& number_format, MathematicalValue number)
 {
     auto& realm = *vm.current_realm();
 
     // 1. Let parts be ? PartitionNumberPattern(numberFormat, x).
-    // Note: Our implementation of PartitionNumberPattern does not throw.
-    auto parts = partition_number_pattern(vm, number_format, move(number));
+    auto parts = TRY(partition_number_pattern(vm, number_format, move(number)));
 
     // 2. Let result be ! ArrayCreate(0).
     auto result = MUST(Array::create(realm, 0));
@@ -951,7 +949,7 @@ Array* format_numeric_to_parts(VM& vm, NumberFormat& number_format, Mathematical
     }
 
     // 5. Return result.
-    return result;
+    return result.ptr();
 }
 
 static DeprecatedString cut_trailing_zeroes(StringView string, int cut)
@@ -1738,11 +1736,11 @@ ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_number_range_pat
     Vector<PatternPartitionWithSource> result;
 
     // 3. Let xResult be ? PartitionNumberPattern(numberFormat, x).
-    auto raw_start_result = partition_number_pattern(vm, number_format, move(start));
+    auto raw_start_result = TRY(partition_number_pattern(vm, number_format, move(start)));
     auto start_result = PatternPartitionWithSource::create_from_parent_list(move(raw_start_result));
 
     // 4. Let yResult be ? PartitionNumberPattern(numberFormat, y).
-    auto raw_end_result = partition_number_pattern(vm, number_format, move(end));
+    auto raw_end_result = TRY(partition_number_pattern(vm, number_format, move(end)));
     auto end_result = PatternPartitionWithSource::create_from_parent_list(move(raw_end_result));
 
     // 5. If xResult is equal to yResult, then

+ 4 - 4
Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.h

@@ -277,10 +277,10 @@ enum class RoundingDecision {
 
 int currency_digits(StringView currency);
 FormatResult format_numeric_to_string(NumberFormatBase const& intl_object, MathematicalValue number);
-Vector<PatternPartition> partition_number_pattern(VM&, NumberFormat&, MathematicalValue number);
-Vector<PatternPartition> partition_notation_sub_pattern(NumberFormat&, MathematicalValue const& number, DeprecatedString formatted_string, int exponent);
-DeprecatedString format_numeric(VM&, NumberFormat&, MathematicalValue number);
-Array* format_numeric_to_parts(VM&, NumberFormat&, MathematicalValue number);
+ThrowCompletionOr<Vector<PatternPartition>> partition_number_pattern(VM&, NumberFormat&, MathematicalValue number);
+ThrowCompletionOr<Vector<PatternPartition>> partition_notation_sub_pattern(VM&, NumberFormat&, MathematicalValue const& number, DeprecatedString formatted_string, int exponent);
+ThrowCompletionOr<DeprecatedString> format_numeric(VM&, NumberFormat&, MathematicalValue number);
+ThrowCompletionOr<Array*> format_numeric_to_parts(VM&, NumberFormat&, MathematicalValue number);
 RawFormatResult to_raw_precision(MathematicalValue const& number, int min_precision, int max_precision, Optional<NumberFormat::UnsignedRoundingMode> const& unsigned_rounding_mode);
 RawFormatResult to_raw_fixed(MathematicalValue const& number, int min_fraction, int max_fraction, int rounding_increment, Optional<NumberFormat::UnsignedRoundingMode> const& unsigned_rounding_mode);
 Optional<Variant<StringView, DeprecatedString>> get_number_format_pattern(VM&, NumberFormat&, MathematicalValue const& number, ::Locale::NumberFormat& found_pattern);

+ 1 - 2
Userland/Libraries/LibJS/Runtime/Intl/NumberFormatFunction.cpp

@@ -45,8 +45,7 @@ ThrowCompletionOr<Value> NumberFormatFunction::call()
     auto mathematical_value = TRY(to_intl_mathematical_value(vm, value));
 
     // 5. Return ? FormatNumeric(nf, x).
-    // Note: Our implementation of FormatNumeric does not throw.
-    auto formatted = format_numeric(vm, m_number_format, move(mathematical_value));
+    auto formatted = TRY(format_numeric(vm, m_number_format, move(mathematical_value)));
     return PrimitiveString::create(vm, move(formatted));
 }
 

+ 1 - 2
Userland/Libraries/LibJS/Runtime/Intl/NumberFormatPrototype.cpp

@@ -76,8 +76,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberFormatPrototype::format_to_parts)
     auto mathematical_value = TRY(to_intl_mathematical_value(vm, value));
 
     // 4. Return ? FormatNumericToParts(nf, x).
-    // Note: Our implementation of FormatNumericToParts does not throw.
-    return format_numeric_to_parts(vm, *number_format, move(mathematical_value));
+    return TRY(format_numeric_to_parts(vm, *number_format, move(mathematical_value)));
 }
 
 // 1.3.5 Intl.NumberFormat.prototype.formatRange ( start, end ), https://tc39.es/proposal-intl-numberformat-v3/out/numberformat/proposed.html#sec-intl.numberformat.prototype.formatrange

+ 5 - 4
Userland/Libraries/LibJS/Runtime/Intl/RelativeTimeFormat.cpp

@@ -174,7 +174,8 @@ ThrowCompletionOr<Vector<PatternPartitionWithUnit>> partition_relative_time_patt
     auto patterns = find_patterns_for_tense_or_number(tense);
 
     // 20. Let fv be ! PartitionNumberPattern(relativeTimeFormat.[[NumberFormat]], value).
-    auto value_partitions = partition_number_pattern(vm, relative_time_format.number_format(), Value(value));
+    // NOTE: We TRY this operation only to propagate OOM errors.
+    auto value_partitions = TRY(partition_number_pattern(vm, relative_time_format.number_format(), Value(value)));
 
     // 21. Let pr be ! ResolvePlural(relativeTimeFormat.[[PluralRules]], value).
     auto plurality = resolve_plural(relative_time_format.plural_rules(), Value(value));
@@ -185,14 +186,14 @@ ThrowCompletionOr<Vector<PatternPartitionWithUnit>> partition_relative_time_patt
         return Vector<PatternPartitionWithUnit> {};
 
     // 23. Return ! MakePartsList(pattern, unit, fv).
-    return make_parts_list(pattern->pattern, ::Locale::time_unit_to_string(time_unit), move(value_partitions));
+    return make_parts_list(vm, pattern->pattern, ::Locale::time_unit_to_string(time_unit), move(value_partitions));
 }
 
 // 17.5.3 MakePartsList ( pattern, unit, parts ), https://tc39.es/ecma402/#sec-makepartslist
-Vector<PatternPartitionWithUnit> make_parts_list(StringView pattern, StringView unit, Vector<PatternPartition> parts)
+ThrowCompletionOr<Vector<PatternPartitionWithUnit>> make_parts_list(VM& vm, StringView pattern, StringView unit, Vector<PatternPartition> parts)
 {
     // 1. Let patternParts be PartitionPattern(pattern).
-    auto pattern_parts = partition_pattern(pattern);
+    auto pattern_parts = TRY(partition_pattern(vm, pattern));
 
     // 2. Let result be a new empty List.
     Vector<PatternPartitionWithUnit> result;

+ 1 - 1
Userland/Libraries/LibJS/Runtime/Intl/RelativeTimeFormat.h

@@ -84,7 +84,7 @@ struct PatternPartitionWithUnit : public PatternPartition {
 
 ThrowCompletionOr<::Locale::TimeUnit> singular_relative_time_unit(VM&, StringView unit);
 ThrowCompletionOr<Vector<PatternPartitionWithUnit>> partition_relative_time_pattern(VM&, RelativeTimeFormat&, double value, StringView unit);
-Vector<PatternPartitionWithUnit> make_parts_list(StringView pattern, StringView unit, Vector<PatternPartition> parts);
+ThrowCompletionOr<Vector<PatternPartitionWithUnit>> make_parts_list(VM&, StringView pattern, StringView unit, Vector<PatternPartition> parts);
 ThrowCompletionOr<DeprecatedString> format_relative_time(VM&, RelativeTimeFormat&, double value, StringView unit);
 ThrowCompletionOr<Array*> format_relative_time_to_parts(VM&, RelativeTimeFormat&, double value, StringView unit);
 

+ 1 - 2
Userland/Libraries/LibJS/Runtime/NumberPrototype.cpp

@@ -287,8 +287,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_locale_string)
     auto* number_format = static_cast<Intl::NumberFormat*>(TRY(construct(vm, *realm.intrinsics().intl_number_format_constructor(), locales, options)).ptr());
 
     // 3. Return ? FormatNumeric(numberFormat, x).
-    // Note: Our implementation of FormatNumeric does not throw.
-    auto formatted = Intl::format_numeric(vm, *number_format, number_value);
+    auto formatted = TRY(Intl::format_numeric(vm, *number_format, number_value));
     return PrimitiveString::create(vm, move(formatted));
 }