1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 12:37:40 +00:00

LibJS: Make JS::number_to_string() infallible

Work towards #20449.
This commit is contained in:
Andreas Kling 2023-08-09 08:03:12 +02:00
parent 09547ec975
commit b8f78c0adc
9 changed files with 66 additions and 68 deletions

View file

@ -1168,7 +1168,7 @@ Object* create_mapped_arguments_object(VM& vm, FunctionObject& function, Vector<
} }
// 7.1.21 CanonicalNumericIndexString ( argument ), https://tc39.es/ecma262/#sec-canonicalnumericindexstring // 7.1.21 CanonicalNumericIndexString ( argument ), https://tc39.es/ecma262/#sec-canonicalnumericindexstring
ThrowCompletionOr<CanonicalIndex> canonical_numeric_index_string(VM& vm, PropertyKey const& property_key, CanonicalIndexMode mode) CanonicalIndex canonical_numeric_index_string(PropertyKey const& property_key, CanonicalIndexMode mode)
{ {
// NOTE: If the property name is a number type (An implementation-defined optimized // NOTE: If the property name is a number type (An implementation-defined optimized
// property key type), it can be treated as a string property that has already been // property key type), it can be treated as a string property that has already been
@ -1221,7 +1221,7 @@ ThrowCompletionOr<CanonicalIndex> canonical_numeric_index_string(VM& vm, Propert
// FIXME: We return 0 instead of n but it might not observable? // FIXME: We return 0 instead of n but it might not observable?
// 3. If SameValue(! ToString(n), argument) is true, return n. // 3. If SameValue(! ToString(n), argument) is true, return n.
if (TRY_OR_THROW_OOM(vm, number_to_string(*maybe_double)) == argument.view()) if (number_to_string(*maybe_double) == argument.view())
return CanonicalIndex(CanonicalIndex::Type::Numeric, 0); return CanonicalIndex(CanonicalIndex::Type::Numeric, 0);
// 4. Return undefined. // 4. Return undefined.

View file

@ -60,7 +60,7 @@ enum class CanonicalIndexMode {
DetectNumericRoundtrip, DetectNumericRoundtrip,
IgnoreNumericRoundtrip, IgnoreNumericRoundtrip,
}; };
ThrowCompletionOr<CanonicalIndex> canonical_numeric_index_string(VM&, PropertyKey const&, CanonicalIndexMode needs_numeric); [[nodiscard]] CanonicalIndex canonical_numeric_index_string(PropertyKey const&, CanonicalIndexMode needs_numeric);
ThrowCompletionOr<String> get_substitution(VM&, Utf16View const& matched, Utf16View const& str, size_t position, Span<Value> captures, Value named_captures, Value replacement); ThrowCompletionOr<String> get_substitution(VM&, Utf16View const& matched, Utf16View const& str, size_t position, Span<Value> captures, Value named_captures, Value replacement);
enum class CallerMode { enum class CallerMode {

View file

@ -298,7 +298,7 @@ ThrowCompletionOr<String> MathematicalValue::to_string(VM& vm) const
{ {
return m_value.visit( return m_value.visit(
[&](double value) -> ThrowCompletionOr<String> { [&](double value) -> ThrowCompletionOr<String> {
return TRY_OR_THROW_OOM(vm, number_to_string(value, NumberToStringMode::WithoutExponent)); return number_to_string(value, NumberToStringMode::WithoutExponent);
}, },
[&](Crypto::SignedBigInteger const& value) -> ThrowCompletionOr<String> { [&](Crypto::SignedBigInteger const& value) -> ThrowCompletionOr<String> {
return TRY_OR_THROW_OOM(vm, value.to_base(10)); return TRY_OR_THROW_OOM(vm, value.to_base(10));

View file

@ -144,7 +144,7 @@ ThrowCompletionOr<Optional<Value>> PrimitiveString::get(VM& vm, PropertyKey cons
return Value(static_cast<double>(length)); return Value(static_cast<double>(length));
} }
} }
auto index = MUST_OR_THROW_OOM(canonical_numeric_index_string(vm, property_key, CanonicalIndexMode::IgnoreNumericRoundtrip)); auto index = canonical_numeric_index_string(property_key, CanonicalIndexMode::IgnoreNumericRoundtrip);
if (!index.is_index()) if (!index.is_index())
return Optional<Value> {}; return Optional<Value> {};
auto str = utf16_string_view(); auto str = utf16_string_view();

View file

@ -63,7 +63,7 @@ static ThrowCompletionOr<Optional<PropertyDescriptor>> string_get_own_property(S
return Optional<PropertyDescriptor> {}; return Optional<PropertyDescriptor> {};
// 2. Let index be CanonicalNumericIndexString(P). // 2. Let index be CanonicalNumericIndexString(P).
auto index = MUST_OR_THROW_OOM(canonical_numeric_index_string(vm, property_key, CanonicalIndexMode::IgnoreNumericRoundtrip)); auto index = canonical_numeric_index_string(property_key, CanonicalIndexMode::IgnoreNumericRoundtrip);
// 3. If index is undefined, return undefined. // 3. If index is undefined, return undefined.
// 4. If IsIntegralNumber(index) is false, return undefined. // 4. If IsIntegralNumber(index) is false, return undefined.

View file

@ -191,7 +191,7 @@ public:
// NOTE: This includes an implementation-defined optimization, see note above! // NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) { if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be CanonicalNumericIndexString(P). // a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = MUST_OR_THROW_OOM(canonical_numeric_index_string(vm(), property_key, CanonicalIndexMode::DetectNumericRoundtrip)); auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, then // b. If numericIndex is not undefined, then
if (!numeric_index.is_undefined()) { if (!numeric_index.is_undefined()) {
// i. Let value be IntegerIndexedElementGet(O, numericIndex). // i. Let value be IntegerIndexedElementGet(O, numericIndex).
@ -228,7 +228,7 @@ public:
// NOTE: This includes an implementation-defined optimization, see note above! // NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) { if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be CanonicalNumericIndexString(P). // a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = MUST_OR_THROW_OOM(canonical_numeric_index_string(vm(), property_key, CanonicalIndexMode::DetectNumericRoundtrip)); auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, return IsValidIntegerIndex(O, numericIndex). // b. If numericIndex is not undefined, return IsValidIntegerIndex(O, numericIndex).
if (!numeric_index.is_undefined()) if (!numeric_index.is_undefined())
return is_valid_integer_index(*this, numeric_index); return is_valid_integer_index(*this, numeric_index);
@ -251,7 +251,7 @@ public:
// NOTE: This includes an implementation-defined optimization, see note above! // NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) { if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be CanonicalNumericIndexString(P). // a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = MUST_OR_THROW_OOM(canonical_numeric_index_string(vm(), property_key, CanonicalIndexMode::DetectNumericRoundtrip)); auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, then // b. If numericIndex is not undefined, then
if (!numeric_index.is_undefined()) { if (!numeric_index.is_undefined()) {
// i. If IsValidIntegerIndex(O, numericIndex) is false, return false. // i. If IsValidIntegerIndex(O, numericIndex) is false, return false.
@ -301,7 +301,7 @@ public:
// NOTE: This includes an implementation-defined optimization, see note above! // NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) { if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be CanonicalNumericIndexString(P). // a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = MUST_OR_THROW_OOM(canonical_numeric_index_string(vm(), property_key, CanonicalIndexMode::DetectNumericRoundtrip)); auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, then // b. If numericIndex is not undefined, then
if (!numeric_index.is_undefined()) { if (!numeric_index.is_undefined()) {
// i. Return IntegerIndexedElementGet(O, numericIndex). // i. Return IntegerIndexedElementGet(O, numericIndex).
@ -328,7 +328,7 @@ public:
// NOTE: This includes an implementation-defined optimization, see note above! // NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) { if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be CanonicalNumericIndexString(P). // a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = MUST_OR_THROW_OOM(canonical_numeric_index_string(vm(), property_key, CanonicalIndexMode::DetectNumericRoundtrip)); auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, then // b. If numericIndex is not undefined, then
if (!numeric_index.is_undefined()) { if (!numeric_index.is_undefined()) {
// i. If SameValue(O, Receiver) is true, then // i. If SameValue(O, Receiver) is true, then
@ -363,7 +363,7 @@ public:
// NOTE: This includes an implementation-defined optimization, see note above! // NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) { if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be CanonicalNumericIndexString(P). // a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = MUST_OR_THROW_OOM(canonical_numeric_index_string(vm(), property_key, CanonicalIndexMode::DetectNumericRoundtrip)); auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, then // b. If numericIndex is not undefined, then
if (!numeric_index.is_undefined()) { if (!numeric_index.is_undefined()) {
// i. If IsValidIntegerIndex(O, numericIndex) is false, return true; else return false. // i. If IsValidIntegerIndex(O, numericIndex) is false, return true; else return false.

View file

@ -72,7 +72,7 @@ ALWAYS_INLINE bool both_bigint(Value const& lhs, Value const& rhs)
// 6.1.6.1.20 Number::toString ( x ), https://tc39.es/ecma262/#sec-numeric-types-number-tostring // 6.1.6.1.20 Number::toString ( x ), https://tc39.es/ecma262/#sec-numeric-types-number-tostring
// Implementation for radix = 10 // Implementation for radix = 10
static ErrorOr<void> number_to_string_impl(StringBuilder& builder, double d, NumberToStringMode mode) static void number_to_string_impl(StringBuilder& builder, double d, NumberToStringMode mode)
{ {
auto convert_to_decimal_digits_array = [](auto x, auto& digits, auto& length) { auto convert_to_decimal_digits_array = [](auto x, auto& digits, auto& length) {
for (; x; x /= 10) for (; x; x /= 10)
@ -83,25 +83,25 @@ static ErrorOr<void> number_to_string_impl(StringBuilder& builder, double d, Num
// 1. If x is NaN, return "NaN". // 1. If x is NaN, return "NaN".
if (isnan(d)) { if (isnan(d)) {
TRY(builder.try_append("NaN"sv)); builder.append("NaN"sv);
return {}; return;
} }
// 2. If x is +0𝔽 or -0𝔽, return "0". // 2. If x is +0𝔽 or -0𝔽, return "0".
if (d == +0.0 || d == -0.0) { if (d == +0.0 || d == -0.0) {
TRY(builder.try_append("0"sv)); builder.append("0"sv);
return {}; return;
} }
// 4. If x is +∞𝔽, return "Infinity". // 4. If x is +∞𝔽, return "Infinity".
if (isinf(d)) { if (isinf(d)) {
if (d > 0) { if (d > 0) {
TRY(builder.try_append("Infinity"sv)); builder.append("Infinity"sv);
return {}; return;
} }
TRY(builder.try_append("-Infinity"sv)); builder.append("-Infinity"sv);
return {}; return;
} }
// 5. Let n, k, and s be integers such that k ≥ 1, radix ^ (k - 1) ≤ s < radix ^ k, // 5. Let n, k, and s be integers such that k ≥ 1, radix ^ (k - 1) ≤ s < radix ^ k,
@ -120,7 +120,7 @@ static ErrorOr<void> number_to_string_impl(StringBuilder& builder, double d, Num
// 3. If x < -0𝔽, return the string-concatenation of "-" and Number::toString(-x, radix). // 3. If x < -0𝔽, return the string-concatenation of "-" and Number::toString(-x, radix).
if (sign) if (sign)
TRY(builder.try_append('-')); builder.append('-');
// Non-standard: Intl needs number-to-string conversions for extremely large numbers without any // Non-standard: Intl needs number-to-string conversions for extremely large numbers without any
// exponential formatting, as it will handle such formatting itself in a locale-aware way. // exponential formatting, as it will handle such formatting itself in a locale-aware way.
@ -132,34 +132,34 @@ static ErrorOr<void> number_to_string_impl(StringBuilder& builder, double d, Num
if (n >= k) { if (n >= k) {
// i. Return the string-concatenation of: // i. Return the string-concatenation of:
// the code units of the k digits of the representation of s using radix radix // the code units of the k digits of the representation of s using radix radix
TRY(builder.try_append(mantissa_digits.data(), k)); builder.append(mantissa_digits.data(), k);
// n - k occurrences of the code unit 0x0030 (DIGIT ZERO) // n - k occurrences of the code unit 0x0030 (DIGIT ZERO)
TRY(builder.try_append_repeated('0', n - k)); builder.append_repeated('0', n - k);
// b. Else if n > 0, then // b. Else if n > 0, then
} else if (n > 0) { } else if (n > 0) {
// i. Return the string-concatenation of: // i. Return the string-concatenation of:
// the code units of the most significant n digits of the representation of s using radix radix // the code units of the most significant n digits of the representation of s using radix radix
TRY(builder.try_append(mantissa_digits.data(), n)); builder.append(mantissa_digits.data(), n);
// the code unit 0x002E (FULL STOP) // the code unit 0x002E (FULL STOP)
TRY(builder.try_append('.')); builder.append('.');
// the code units of the remaining k - n digits of the representation of s using radix radix // the code units of the remaining k - n digits of the representation of s using radix radix
TRY(builder.try_append(mantissa_digits.data() + n, k - n)); builder.append(mantissa_digits.data() + n, k - n);
// c. Else, // c. Else,
} else { } else {
// i. Assert: n ≤ 0. // i. Assert: n ≤ 0.
VERIFY(n <= 0); VERIFY(n <= 0);
// ii. Return the string-concatenation of: // ii. Return the string-concatenation of:
// the code unit 0x0030 (DIGIT ZERO) // the code unit 0x0030 (DIGIT ZERO)
TRY(builder.try_append('0')); builder.append('0');
// the code unit 0x002E (FULL STOP) // the code unit 0x002E (FULL STOP)
TRY(builder.try_append('.')); builder.append('.');
// -n occurrences of the code unit 0x0030 (DIGIT ZERO) // -n occurrences of the code unit 0x0030 (DIGIT ZERO)
TRY(builder.try_append_repeated('0', -n)); builder.append_repeated('0', -n);
// the code units of the k digits of the representation of s using radix radix // the code units of the k digits of the representation of s using radix radix
TRY(builder.try_append(mantissa_digits.data(), k)); builder.append(mantissa_digits.data(), k);
} }
return {}; return;
} }
// 7. NOTE: In this case, the input will be represented using scientific E notation, such as 1.2e+3. // 7. NOTE: In this case, the input will be represented using scientific E notation, such as 1.2e+3.
@ -178,45 +178,43 @@ static ErrorOr<void> number_to_string_impl(StringBuilder& builder, double d, Num
if (k == 1) { if (k == 1) {
// a. Return the string-concatenation of: // a. Return the string-concatenation of:
// the code unit of the single digit of s // the code unit of the single digit of s
TRY(builder.try_append(mantissa_digits[0])); builder.append(mantissa_digits[0]);
// the code unit 0x0065 (LATIN SMALL LETTER E) // the code unit 0x0065 (LATIN SMALL LETTER E)
TRY(builder.try_append('e')); builder.append('e');
// exponentSign // exponentSign
TRY(builder.try_append(exponent_sign)); builder.append(exponent_sign);
// the code units of the decimal representation of abs(n - 1) // the code units of the decimal representation of abs(n - 1)
TRY(builder.try_append(exponent_digits.data(), exponent_length)); builder.append(exponent_digits.data(), exponent_length);
return {}; return;
} }
// 12. Return the string-concatenation of: // 12. Return the string-concatenation of:
// the code unit of the most significant digit of the decimal representation of s // the code unit of the most significant digit of the decimal representation of s
TRY(builder.try_append(mantissa_digits[0])); builder.append(mantissa_digits[0]);
// the code unit 0x002E (FULL STOP) // the code unit 0x002E (FULL STOP)
TRY(builder.try_append('.')); builder.append('.');
// the code units of the remaining k - 1 digits of the decimal representation of s // the code units of the remaining k - 1 digits of the decimal representation of s
TRY(builder.try_append(mantissa_digits.data() + 1, k - 1)); builder.append(mantissa_digits.data() + 1, k - 1);
// the code unit 0x0065 (LATIN SMALL LETTER E) // the code unit 0x0065 (LATIN SMALL LETTER E)
TRY(builder.try_append('e')); builder.append('e');
// exponentSign // exponentSign
TRY(builder.try_append(exponent_sign)); builder.append(exponent_sign);
// the code units of the decimal representation of abs(n - 1) // the code units of the decimal representation of abs(n - 1)
TRY(builder.try_append(exponent_digits.data(), exponent_length)); builder.append(exponent_digits.data(), exponent_length);
return {};
} }
ErrorOr<String> number_to_string(double d, NumberToStringMode mode) String number_to_string(double d, NumberToStringMode mode)
{ {
StringBuilder builder; StringBuilder builder;
TRY(number_to_string_impl(builder, d, mode)); number_to_string_impl(builder, d, mode);
return builder.to_string(); return builder.to_string().release_value();
} }
DeprecatedString number_to_deprecated_string(double d, NumberToStringMode mode) DeprecatedString number_to_deprecated_string(double d, NumberToStringMode mode)
{ {
StringBuilder builder; StringBuilder builder;
MUST(number_to_string_impl(builder, d, mode)); number_to_string_impl(builder, d, mode);
return builder.to_deprecated_string(); return builder.to_deprecated_string();
} }
@ -398,7 +396,7 @@ ThrowCompletionOr<NonnullGCPtr<PrimitiveString>> Value::to_primitive_string(VM&
ThrowCompletionOr<String> Value::to_string(VM& vm) const ThrowCompletionOr<String> Value::to_string(VM& vm) const
{ {
if (is_double()) if (is_double())
return TRY_OR_THROW_OOM(vm, number_to_string(m_value.as_double)); return number_to_string(m_value.as_double);
switch (m_value.tag) { switch (m_value.tag) {
// 1. If argument is a String, return argument. // 1. If argument is a String, return argument.

View file

@ -561,8 +561,8 @@ enum class NumberToStringMode {
WithExponent, WithExponent,
WithoutExponent, WithoutExponent,
}; };
ErrorOr<String> number_to_string(double, NumberToStringMode = NumberToStringMode::WithExponent); [[nodiscard]] String number_to_string(double, NumberToStringMode = NumberToStringMode::WithExponent);
DeprecatedString number_to_deprecated_string(double, NumberToStringMode = NumberToStringMode::WithExponent); [[nodiscard]] DeprecatedString number_to_deprecated_string(double, NumberToStringMode = NumberToStringMode::WithExponent);
double string_to_number(StringView); double string_to_number(StringView);
inline bool Value::operator==(Value const& value) const { return same_value(*this, value); } inline bool Value::operator==(Value const& value) const { return same_value(*this, value); }

View file

@ -302,83 +302,83 @@ WebIDL::ExceptionOr<String> DOMMatrixReadOnly::to_string() const
TRY_OR_THROW_OOM(vm, builder.try_append("matrix3d("sv)); TRY_OR_THROW_OOM(vm, builder.try_append("matrix3d("sv));
// 2. Append ! ToString(m11 element) to string. // 2. Append ! ToString(m11 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m11())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m11())));
// 3. Append ", " to string. // 3. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 4. Append ! ToString(m12 element) to string. // 4. Append ! ToString(m12 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m12())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m12())));
// 5. Append ", " to string. // 5. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 6. Append ! ToString(m13 element) to string. // 6. Append ! ToString(m13 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m13())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m13())));
// 7. Append ", " to string. // 7. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 8. Append ! ToString(m14 element) to string. // 8. Append ! ToString(m14 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m14())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m14())));
// 9. Append ", " to string. // 9. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 10. Append ! ToString(m21 element) to string. // 10. Append ! ToString(m21 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m21())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m21())));
// 11. Append ", " to string. // 11. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 12. Append ! ToString(m22 element) to string. // 12. Append ! ToString(m22 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m22())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m22())));
// 13. Append ", " to string. // 13. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 14. Append ! ToString(m23 element) to string. // 14. Append ! ToString(m23 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m23())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m23())));
// 15. Append ", " to string. // 15. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 16. Append ! ToString(m24 element) to string. // 16. Append ! ToString(m24 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m24())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m24())));
// 17. Append ", " to string. // 17. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// NOTE: The spec doesn't include the steps to append m31 to m34, but they are required as matrix3d requires 16 elements. // NOTE: The spec doesn't include the steps to append m31 to m34, but they are required as matrix3d requires 16 elements.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m31())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m31())));
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m32())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m32())));
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m33())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m33())));
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m34())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m34())));
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 18. Append ! ToString(m41 element) to string. // 18. Append ! ToString(m41 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m41())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m41())));
// 19. Append ", " to string. // 19. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 20. Append ! ToString(m42 element) to string. // 20. Append ! ToString(m42 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m42())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m42())));
// 21. Append ", " to string. // 21. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 22. Append ! ToString(m43 element) to string. // 22. Append ! ToString(m43 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m43())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m43())));
// 23. Append ", " to string. // 23. Append ", " to string.
TRY_OR_THROW_OOM(vm, builder.try_append(", "sv)); TRY_OR_THROW_OOM(vm, builder.try_append(", "sv));
// 24. Append ! ToString(m44 element) to string. // 24. Append ! ToString(m44 element) to string.
TRY_OR_THROW_OOM(vm, builder.try_append(TRY_OR_THROW_OOM(vm, JS::number_to_string(m44())))); TRY_OR_THROW_OOM(vm, builder.try_append(JS::number_to_string(m44())));
// 25. Append ")" to string. // 25. Append ")" to string.
TRY_OR_THROW_OOM(vm, builder.try_append(")"sv)); TRY_OR_THROW_OOM(vm, builder.try_append(")"sv));