diff --git a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp
index 5eb084058e..022d98f441 100644
--- a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp
+++ b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp
@@ -31,7 +31,9 @@
#include
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -105,6 +107,8 @@ enum ValueTag {
ObjectReference,
+ SerializableObject,
+
// TODO: Define many more types
// This tag or higher are understood to be errors
@@ -310,6 +314,14 @@ public:
}
// FIXME: 19. Otherwise, if value is a platform object that is a serializable object:
+ else if (value.is_object() && is(value.as_object())) {
+ auto& serializable = dynamic_cast(value.as_object());
+
+ m_serialized.append(ValueTag::SerializableObject);
+
+ // 1. Perform the serialization steps for value's primary interface, given value, serialized, and forStorage.
+ TRY(serializable.serialization_steps(m_serialized, m_for_storage));
+ }
// 20. Otherwise, if value is a platform object, then throw a "DataCloneError" DOMException.
else if (value.is_object() && is(value.as_object())) {
@@ -812,7 +824,20 @@ public:
}
// 22. Otherwise:
default:
- return WebIDL::DataCloneError::create(*m_vm.current_realm(), "Unsupported type"_fly_string);
+ VERIFY(tag == ValueTag::SerializableObject);
+
+ auto& realm = *m_vm.current_realm();
+ // 1. Let interfaceName be serialized.[[Type]].
+ auto interface_name = TRY(deserialize_string(m_vm, m_serialized, m_position));
+ // 2. If the interface identified by interfaceName is not exposed in targetRealm, then throw a "DataCloneError" DOMException.
+ if (!is_interface_exposed_on_target_realm(interface_name, realm))
+ return WebIDL::DataCloneError::create(realm, "Unsupported type"_fly_string);
+
+ // 3. Set value to a new instance of the interface identified by interfaceName, created in targetRealm.
+ value = TRY(create_serialized_type(interface_name, realm));
+
+ // 4. Set deep to true.
+ deep = true;
}
// 23. Set memory[serialized] to value.
@@ -874,8 +899,9 @@ public:
// 4. Otherwise:
else {
- // FIXME: 1. Perform the appropriate deserialization steps for the interface identified by serialized.[[Type]], given serialized, value, and targetRealm.
- VERIFY_NOT_REACHED();
+ // 1. Perform the appropriate deserialization steps for the interface identified by serialized.[[Type]], given serialized, value, and targetRealm.
+ auto& serializable = dynamic_cast(value.as_object());
+ TRY(serializable.deserialization_steps(m_serialized, m_position));
}
}
@@ -896,6 +922,22 @@ private:
m_position += 2;
return value;
}
+
+ static WebIDL::ExceptionOr> create_serialized_type(StringView interface_name, JS::Realm& realm)
+ {
+ if (interface_name == "Blob"sv)
+ return FileAPI::Blob::create(realm);
+
+ VERIFY_NOT_REACHED();
+ }
+
+ // FIXME: Consolidate this function with the similar is_interface_exposed_on_target_realm() used when transferring objects.
+ // Also, the name parameter would be better off being the interface name (as a string) so that we don't need a switch statement.
+ static bool is_interface_exposed_on_target_realm(StringView interface_name, JS::Realm& realm)
+ {
+ auto const& intrinsics = Bindings::host_defined_intrinsics(realm);
+ return intrinsics.is_exposed(interface_name);
+ }
};
WebIDL::ExceptionOr deserialize_bytes(JS::VM& vm, ReadonlySpan vector, size_t& position)