diff --git a/Tests/LibWeb/Text/expected/HTML/StructuredClone-object-primitives.txt b/Tests/LibWeb/Text/expected/HTML/StructuredClone-object-primitives.txt
index 01f1f25aa5..bcc689ffd6 100644
--- a/Tests/LibWeb/Text/expected/HTML/StructuredClone-object-primitives.txt
+++ b/Tests/LibWeb/Text/expected/HTML/StructuredClone-object-primitives.txt
@@ -6,5 +6,7 @@ This is a String object
9007199254740991
1692748800000
/abc/gimsuy
+Error
+URIError: hello
[object ArrayBuffer]
ERROR: DataCloneError: Cannot serialize Symbol
\ No newline at end of file
diff --git a/Tests/LibWeb/Text/input/HTML/StructuredClone-object-primitives.html b/Tests/LibWeb/Text/input/HTML/StructuredClone-object-primitives.html
index ae3dd770d8..b692902669 100644
--- a/Tests/LibWeb/Text/input/HTML/StructuredClone-object-primitives.html
+++ b/Tests/LibWeb/Text/input/HTML/StructuredClone-object-primitives.html
@@ -9,6 +9,8 @@
println(structuredClone(BigInt("0x1fffffffffffff")));
println(structuredClone(Date.UTC(2023, 7, 23)));
println(structuredClone(/abc/gimsuy));
+ println(structuredClone(new Error()));
+ println(structuredClone(new URIError("hello")));
{
let arrayBuffer = new ArrayBuffer(6);
diff --git a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp
index 829a1d7ecd..a2f17bc108 100644
--- a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp
+++ b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp
@@ -85,12 +85,32 @@ enum ValueTag {
ArrayBufferView,
+ ErrorObject,
+
// TODO: Define many more types
// This tag or higher are understood to be errors
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:
// 1. Fill up the memory with all the values, but without translating references
// 2. Translate all the references into the appropriate form
@@ -215,7 +235,36 @@ public:
TRY(serialize_viewed_array_buffer(m_serialized, static_cast(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(value.as_object()) && !is(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 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 {
return throw_completion(WebIDL::DataCloneError::create(*m_vm.current_realm(), "Unsupported type"_fly_string));
}
@@ -501,6 +550,38 @@ public:
}
break;
}
+ case ValueTag::ErrorObject: {
+ auto& realm = *m_vm.current_realm();
+ auto type = static_cast(m_vector[position++]);
+ auto has_message = static_cast(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:
m_error = "Unsupported type"_fly_string;
break;