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 8ee29134f9f..a9b42aeb5c9 100644 --- a/Libraries/LibWeb/HTML/StructuredSerialize.cpp +++ b/Libraries/LibWeb/HTML/StructuredSerialize.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -1008,6 +1009,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 @@ + + +