mirror of
https://github.com/RGBCube/serenity
synced 2025-05-25 22:15:06 +00:00
LibWeb: Support [de]serialization for Error objects
This commit is contained in:
parent
71d4ab367a
commit
1d24e08934
3 changed files with 86 additions and 1 deletions
|
@ -6,5 +6,7 @@ This is a String object
|
||||||
9007199254740991
|
9007199254740991
|
||||||
1692748800000
|
1692748800000
|
||||||
/abc/gimsuy
|
/abc/gimsuy
|
||||||
|
Error
|
||||||
|
URIError: hello
|
||||||
[object ArrayBuffer]
|
[object ArrayBuffer]
|
||||||
ERROR: DataCloneError: Cannot serialize Symbol
|
ERROR: DataCloneError: Cannot serialize Symbol
|
|
@ -9,6 +9,8 @@
|
||||||
println(structuredClone(BigInt("0x1fffffffffffff")));
|
println(structuredClone(BigInt("0x1fffffffffffff")));
|
||||||
println(structuredClone(Date.UTC(2023, 7, 23)));
|
println(structuredClone(Date.UTC(2023, 7, 23)));
|
||||||
println(structuredClone(/abc/gimsuy));
|
println(structuredClone(/abc/gimsuy));
|
||||||
|
println(structuredClone(new Error()));
|
||||||
|
println(structuredClone(new URIError("hello")));
|
||||||
|
|
||||||
{
|
{
|
||||||
let arrayBuffer = new ArrayBuffer(6);
|
let arrayBuffer = new ArrayBuffer(6);
|
||||||
|
|
|
@ -85,12 +85,32 @@ enum ValueTag {
|
||||||
|
|
||||||
ArrayBufferView,
|
ArrayBufferView,
|
||||||
|
|
||||||
|
ErrorObject,
|
||||||
|
|
||||||
// TODO: Define many more types
|
// TODO: Define many more types
|
||||||
|
|
||||||
// This tag or higher are understood to be errors
|
// This tag or higher are understood to be errors
|
||||||
ValueTagMax,
|
ValueTagMax,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ErrorType {
|
||||||
|
Error,
|
||||||
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||||
|
ClassName,
|
||||||
|
JS_ENUMERATE_NATIVE_ERRORS
|
||||||
|
#undef __JS_ENUMERATE
|
||||||
|
};
|
||||||
|
|
||||||
|
static ErrorType error_name_to_type(String const& name)
|
||||||
|
{
|
||||||
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||||
|
if (name == #ClassName##sv) \
|
||||||
|
return ErrorType::ClassName;
|
||||||
|
JS_ENUMERATE_NATIVE_ERRORS
|
||||||
|
#undef __JS_ENUMERATE
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
// Serializing and deserializing are each two passes:
|
// Serializing and deserializing are each two passes:
|
||||||
// 1. Fill up the memory with all the values, but without translating references
|
// 1. Fill up the memory with all the values, but without translating references
|
||||||
// 2. Translate all the references into the appropriate form
|
// 2. Translate all the references into the appropriate form
|
||||||
|
@ -215,7 +235,36 @@ public:
|
||||||
TRY(serialize_viewed_array_buffer(m_serialized, static_cast<JS::DataView&>(value.as_object())));
|
TRY(serialize_viewed_array_buffer(m_serialized, static_cast<JS::DataView&>(value.as_object())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 15 - 24: FIXME: Serialize other data types
|
// 17. Otherwise, if value has an [[ErrorData]] internal slot and value is not a platform object, then:
|
||||||
|
else if (value.is_object() && is<JS::Error>(value.as_object()) && !is<Bindings::PlatformObject>(value.as_object())) {
|
||||||
|
// 1. Let name be ? Get(value, "name").
|
||||||
|
auto name_property = TRY(value.as_object().get(m_vm.names.name));
|
||||||
|
|
||||||
|
// FIXME: Spec bug - https://github.com/whatwg/html/issues/9923
|
||||||
|
// MISSING STEP: Set name to ? ToString(name).
|
||||||
|
auto name = TRY(name_property.to_string(m_vm));
|
||||||
|
|
||||||
|
// 2. If name is not one of "Error", "EvalError", "RangeError", "ReferenceError", "SyntaxError", "TypeError", or "URIError", then set name to "Error".
|
||||||
|
auto type = error_name_to_type(name);
|
||||||
|
|
||||||
|
// 3. Let valueMessageDesc be ? value.[[GetOwnProperty]]("message").
|
||||||
|
auto value_message_descriptor = TRY(value.as_object().internal_get_own_property(m_vm.names.message));
|
||||||
|
|
||||||
|
// 4. Let message be undefined if IsDataDescriptor(valueMessageDesc) is false, and ? ToString(valueMessageDesc.[[Value]]) otherwise.
|
||||||
|
Optional<String> message;
|
||||||
|
if (value_message_descriptor.has_value() && value_message_descriptor->is_data_descriptor())
|
||||||
|
message = TRY(value_message_descriptor->value->to_string(m_vm));
|
||||||
|
|
||||||
|
// 5. Set serialized to { [[Type]]: "Error", [[Name]]: name, [[Message]]: message }.
|
||||||
|
// FIXME: 6. User agents should attach a serialized representation of any interesting accompanying data which are not yet specified, notably the stack property, to serialized.
|
||||||
|
m_serialized.append(ValueTag::ErrorObject);
|
||||||
|
m_serialized.append(type);
|
||||||
|
m_serialized.append(message.has_value());
|
||||||
|
if (message.has_value())
|
||||||
|
TRY(serialize_string(m_serialized, *message));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 15, 16, 18 - 24: FIXME: Serialize other data types
|
||||||
else {
|
else {
|
||||||
return throw_completion(WebIDL::DataCloneError::create(*m_vm.current_realm(), "Unsupported type"_fly_string));
|
return throw_completion(WebIDL::DataCloneError::create(*m_vm.current_realm(), "Unsupported type"_fly_string));
|
||||||
}
|
}
|
||||||
|
@ -501,6 +550,38 @@ public:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ValueTag::ErrorObject: {
|
||||||
|
auto& realm = *m_vm.current_realm();
|
||||||
|
auto type = static_cast<ErrorType>(m_vector[position++]);
|
||||||
|
auto has_message = static_cast<bool>(m_vector[position++]);
|
||||||
|
if (has_message) {
|
||||||
|
auto message = TRY(deserialize_string(m_vm, m_vector, position));
|
||||||
|
switch (type) {
|
||||||
|
case ErrorType::Error:
|
||||||
|
m_memory.append(JS::Error::create(realm, message));
|
||||||
|
break;
|
||||||
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||||
|
case ErrorType::ClassName: \
|
||||||
|
m_memory.append(JS::ClassName::create(realm, message)); \
|
||||||
|
break;
|
||||||
|
JS_ENUMERATE_NATIVE_ERRORS
|
||||||
|
#undef __JS_ENUMERATE
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (type) {
|
||||||
|
case ErrorType::Error:
|
||||||
|
m_memory.append(JS::Error::create(realm));
|
||||||
|
break;
|
||||||
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||||
|
case ErrorType::ClassName: \
|
||||||
|
m_memory.append(JS::ClassName::create(realm)); \
|
||||||
|
break;
|
||||||
|
JS_ENUMERATE_NATIVE_ERRORS
|
||||||
|
#undef __JS_ENUMERATE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
m_error = "Unsupported type"_fly_string;
|
m_error = "Unsupported type"_fly_string;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue