1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:47:36 +00:00

LibJS+Everywhere: Make PrimitiveString and Utf16String fallible

This makes construction of Utf16String fallible in OOM conditions. The
immediate impact is that PrimitiveString must then be fallible as well,
as it may either transcode UTF-8 to UTF-16, or create a UTF-16 string
from ropes.

There are a couple of places where it is very non-trivial to propagate
the error further. A FIXME has been added to those locations.
This commit is contained in:
Timothy Flynn 2023-01-07 12:24:05 -05:00 committed by Linus Groh
parent d793262beb
commit 115baa7e32
57 changed files with 306 additions and 295 deletions

View file

@ -351,7 +351,7 @@ DeprecatedString Value::to_string_without_side_effects() const
case INT32_TAG:
return DeprecatedString::number(as_i32());
case STRING_TAG:
return as_string().deprecated_string();
return MUST(as_string().deprecated_string());
case SYMBOL_TAG:
return as_symbol().to_deprecated_string();
case BIGINT_TAG:
@ -382,7 +382,7 @@ ThrowCompletionOr<DeprecatedString> Value::to_string(VM& vm) const
switch (m_value.tag) {
// 1. If argument is a String, return argument.
case STRING_TAG:
return as_string().deprecated_string();
return TRY(as_string().deprecated_string());
// 2. If argument is a Symbol, throw a TypeError exception.
case SYMBOL_TAG:
return vm.throw_completion<TypeError>(ErrorType::Convert, "symbol", "string");
@ -421,10 +421,10 @@ ThrowCompletionOr<DeprecatedString> Value::to_string(VM& vm) const
ThrowCompletionOr<Utf16String> Value::to_utf16_string(VM& vm) const
{
if (is_string())
return as_string().utf16_string();
return TRY(as_string().utf16_string());
auto utf8_string = TRY(to_string(vm));
return Utf16String(utf8_string);
return Utf16String::create(vm, utf8_string);
}
// 7.1.2 ToBoolean ( argument ), https://tc39.es/ecma262/#sec-toboolean
@ -684,7 +684,7 @@ ThrowCompletionOr<Value> Value::to_number(VM& vm) const
return Value(as_bool() ? 1 : 0);
// 6. If argument is a String, return StringToNumber(argument).
case STRING_TAG:
return string_to_number(as_string().deprecated_string().view());
return string_to_number(TRY(as_string().deprecated_string()));
// 7. Assert: argument is an Object.
case OBJECT_TAG: {
// 8. Let primValue be ? ToPrimitive(argument, number).
@ -738,7 +738,7 @@ ThrowCompletionOr<BigInt*> Value::to_bigint(VM& vm) const
return &primitive.as_bigint();
case STRING_TAG: {
// 1. Let n be ! StringToBigInt(prim).
auto bigint = string_to_bigint(vm, primitive.as_string().deprecated_string());
auto bigint = string_to_bigint(vm, TRY(primitive.as_string().deprecated_string()));
// 2. If n is undefined, throw a SyntaxError exception.
if (!bigint.has_value())
@ -2150,7 +2150,8 @@ bool same_value_non_number(Value lhs, Value rhs)
// 5. If x is a String, then
if (lhs.is_string()) {
// a. If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false.
return lhs.as_string().deprecated_string() == rhs.as_string().deprecated_string();
// FIXME: Propagate this error.
return MUST(lhs.as_string().deprecated_string()) == MUST(rhs.as_string().deprecated_string());
}
// 3. If x is undefined, return true.
@ -2231,7 +2232,7 @@ ThrowCompletionOr<bool> is_loosely_equal(VM& vm, Value lhs, Value rhs)
// 7. If Type(x) is BigInt and Type(y) is String, then
if (lhs.is_bigint() && rhs.is_string()) {
// a. Let n be StringToBigInt(y).
auto bigint = string_to_bigint(vm, rhs.as_string().deprecated_string());
auto bigint = string_to_bigint(vm, TRY(rhs.as_string().deprecated_string()));
// b. If n is undefined, return false.
if (!bigint.has_value())
@ -2312,8 +2313,8 @@ ThrowCompletionOr<TriState> is_less_than(VM& vm, Value lhs, Value rhs, bool left
// 3. If px is a String and py is a String, then
if (x_primitive.is_string() && y_primitive.is_string()) {
auto x_string = x_primitive.as_string().deprecated_string();
auto y_string = y_primitive.as_string().deprecated_string();
auto x_string = TRY(x_primitive.as_string().deprecated_string());
auto y_string = TRY(y_primitive.as_string().deprecated_string());
Utf8View x_code_points { x_string };
Utf8View y_code_points { y_string };
@ -2348,7 +2349,7 @@ ThrowCompletionOr<TriState> is_less_than(VM& vm, Value lhs, Value rhs, bool left
// a. If px is a BigInt and py is a String, then
if (x_primitive.is_bigint() && y_primitive.is_string()) {
// i. Let ny be StringToBigInt(py).
auto y_bigint = string_to_bigint(vm, y_primitive.as_string().deprecated_string());
auto y_bigint = string_to_bigint(vm, TRY(y_primitive.as_string().deprecated_string()));
// ii. If ny is undefined, return undefined.
if (!y_bigint.has_value())
@ -2363,7 +2364,7 @@ ThrowCompletionOr<TriState> is_less_than(VM& vm, Value lhs, Value rhs, bool left
// b. If px is a String and py is a BigInt, then
if (x_primitive.is_string() && y_primitive.is_bigint()) {
// i. Let nx be StringToBigInt(px).
auto x_bigint = string_to_bigint(vm, x_primitive.as_string().deprecated_string());
auto x_bigint = string_to_bigint(vm, TRY(x_primitive.as_string().deprecated_string()));
// ii. If nx is undefined, return undefined.
if (!x_bigint.has_value())