diff --git a/Libraries/LibWeb/HTML/ImageData.cpp b/Libraries/LibWeb/HTML/ImageData.cpp
index 346275b4259..8524b03380a 100644
--- a/Libraries/LibWeb/HTML/ImageData.cpp
+++ b/Libraries/LibWeb/HTML/ImageData.cpp
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -133,4 +134,50 @@ const JS::Uint8ClampedArray* ImageData::data() const
return m_data;
}
+// https://html.spec.whatwg.org/multipage/canvas.html#pixel-manipulation:serialization-steps
+WebIDL::ExceptionOr ImageData::serialization_steps(HTML::SerializationRecord& serialized, bool for_storage, HTML::SerializationMemory& memory)
+{
+ auto& vm = this->vm();
+
+ // FIXME: These have to be performed out of order, since these primitive types will get the wrong value when deserializing
+ // if they're placed after the Uint8ClampedArray.
+ // 2. Set serialized.[[Width]] to the value of value's width attribute.
+ HTML::serialize_primitive_type(serialized, width());
+
+ // 3. Set serialized.[[Height]] to the value of value's height attribute.
+ HTML::serialize_primitive_type(serialized, height());
+
+ // 1. Set serialized.[[Data]] to the sub-serialization of the value of value's data attribute.
+ serialized.extend(TRY(HTML::structured_serialize_internal(vm, m_data, for_storage, memory)));
+
+ // FIXME: 4. Set serialized.[[ColorSpace]] to the value of value's colorSpace attribute.
+
+ return {};
+}
+
+// https://html.spec.whatwg.org/multipage/canvas.html#pixel-manipulation:deserialization-steps
+WebIDL::ExceptionOr ImageData::deserialization_steps(ReadonlySpan const& serialized, size_t& position, HTML::DeserializationMemory& memory)
+{
+ auto& vm = this->vm();
+ auto& realm = this->realm();
+
+ // FIXME: These have to be performed out of order, since these primitive types will get the wrong value if they're
+ // placed after the Uint8ClampedArray.
+ // 2. Initialize value's width attribute to serialized.[[Width]].
+ // 3. Initialize value's height attribute to serialized.[[Height]].
+ auto width = HTML::deserialize_primitive_type(serialized, position);
+ auto height = HTML::deserialize_primitive_type(serialized, position);
+
+ // 1. Initialize value's data attribute to the sub-deserialization of serialized.[[Data]].
+ auto deserialized_record = TRY(HTML::structured_deserialize_internal(vm, serialized, realm, memory, position));
+ if (deserialized_record.value.has_value() && is(deserialized_record.value.value().as_object()))
+ m_data = dynamic_cast(deserialized_record.value.release_value().as_object());
+
+ m_bitmap = TRY_OR_THROW_OOM(vm, Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::RGBA8888, Gfx::AlphaType::Unpremultiplied, Gfx::IntSize(width, height), width * sizeof(u32), m_data->data().data()));
+
+ // FIXME: 4. Initialize value's colorSpace attribute to serialized.[[ColorSpace]].
+
+ return {};
+}
+
}
diff --git a/Libraries/LibWeb/HTML/ImageData.h b/Libraries/LibWeb/HTML/ImageData.h
index 652060f8939..21abf63294f 100644
--- a/Libraries/LibWeb/HTML/ImageData.h
+++ b/Libraries/LibWeb/HTML/ImageData.h
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
namespace Web::HTML {
@@ -17,7 +18,9 @@ struct ImageDataSettings {
Bindings::PredefinedColorSpace color_space;
};
-class ImageData final : public Bindings::PlatformObject {
+class ImageData final
+ : public Bindings::PlatformObject
+ , public Bindings::Serializable {
WEB_PLATFORM_OBJECT(ImageData, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(ImageData);
@@ -39,6 +42,10 @@ public:
JS::Uint8ClampedArray* data();
const JS::Uint8ClampedArray* data() const;
+ virtual StringView interface_name() const override { return "ImageData"sv; }
+ virtual WebIDL::ExceptionOr serialization_steps(HTML::SerializationRecord& serialized, bool for_storage, HTML::SerializationMemory&) override;
+ virtual WebIDL::ExceptionOr deserialization_steps(ReadonlySpan const& serialized, size_t& position, HTML::DeserializationMemory&) override;
+
private:
ImageData(JS::Realm&, NonnullRefPtr, GC::Ref);
diff --git a/Libraries/LibWeb/HTML/StructuredSerialize.cpp b/Libraries/LibWeb/HTML/StructuredSerialize.cpp
index e0c6d6f634d..67d257167bf 100644
--- a/Libraries/LibWeb/HTML/StructuredSerialize.cpp
+++ b/Libraries/LibWeb/HTML/StructuredSerialize.cpp
@@ -46,6 +46,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -1069,6 +1070,8 @@ private:
return Crypto::CryptoKey::create(realm);
if (interface_name == "DOMQuad"sv)
return Geometry::DOMQuad::create(realm);
+ if (interface_name == "ImageData"sv) // FIXME: Unfortunately we have to create this with a dummy array and bitmap, as they're non-nullable.
+ return MUST(HTML::ImageData::create(realm, 1, 1));
VERIFY_NOT_REACHED();
}
diff --git a/Tests/LibWeb/Text/expected/HTML/ImageData-is-serializable.txt b/Tests/LibWeb/Text/expected/HTML/ImageData-is-serializable.txt
new file mode 100644
index 00000000000..9c5ecba9e60
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/HTML/ImageData-is-serializable.txt
@@ -0,0 +1,13 @@
+=== before clone start ===
+width: 123
+height: 321
+data byteLength: 157932
+data filled with 0x41? true
+=== before clone end ===
+=== after clone start ===
+width: 123
+height: 321
+data byteLength: 157932
+data filled with 0x41? true
+not the same data array? true
+=== after clone end ===
diff --git a/Tests/LibWeb/Text/input/HTML/ImageData-is-serializable.html b/Tests/LibWeb/Text/input/HTML/ImageData-is-serializable.html
new file mode 100644
index 00000000000..a3f2d9c317f
--- /dev/null
+++ b/Tests/LibWeb/Text/input/HTML/ImageData-is-serializable.html
@@ -0,0 +1,27 @@
+
+
+