This commit is contained in:
Luke Wilde 2025-01-02 11:40:21 +00:00 committed by GitHub
commit 949f41e820
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 98 additions and 1 deletions

View file

@ -10,6 +10,7 @@
#include <LibWeb/Bindings/ImageDataPrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/HTML/ImageData.h>
#include <LibWeb/HTML/StructuredSerialize.h>
#include <LibWeb/WebIDL/Buffers.h>
#include <LibWeb/WebIDL/DOMException.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
@ -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<void> 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<void> ImageData::deserialization_steps(ReadonlySpan<u32> 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<unsigned>(serialized, position);
auto height = HTML::deserialize_primitive_type<unsigned>(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<JS::Uint8ClampedArray>(deserialized_record.value.value().as_object()))
m_data = dynamic_cast<JS::Uint8ClampedArray&>(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 {};
}
}

View file

@ -10,6 +10,7 @@
#include <LibGfx/Forward.h>
#include <LibWeb/Bindings/ImageDataPrototype.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/Bindings/Serializable.h>
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<void> serialization_steps(HTML::SerializationRecord& serialized, bool for_storage, HTML::SerializationMemory&) override;
virtual WebIDL::ExceptionOr<void> deserialization_steps(ReadonlySpan<u32> const& serialized, size_t& position, HTML::DeserializationMemory&) override;
private:
ImageData(JS::Realm&, NonnullRefPtr<Gfx::Bitmap>, GC::Ref<JS::Uint8ClampedArray>);

View file

@ -46,6 +46,7 @@
#include <LibWeb/Geometry/DOMQuad.h>
#include <LibWeb/Geometry/DOMRect.h>
#include <LibWeb/Geometry/DOMRectReadOnly.h>
#include <LibWeb/HTML/ImageData.h>
#include <LibWeb/HTML/MessagePort.h>
#include <LibWeb/HTML/StructuredSerialize.h>
#include <LibWeb/WebIDL/DOMException.h>
@ -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();
}

View file

@ -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 ===

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<script>
test(() => {
const arr = new Uint8ClampedArray(4 * 123 * 321);
arr.fill(0x41);
const imageData = new ImageData(arr, 123, 321);
println("=== before clone start ===");
println(`width: ${imageData.width}`);
println(`height: ${imageData.height}`);
println(`data byteLength: ${imageData.data.byteLength}`);
println(`data filled with 0x41? ${imageData.data.every((val) => val === 0x41)}`);
println("=== before clone end ===");
const clonedImageData = structuredClone(imageData);
println("=== after clone start ===");
println(`width: ${clonedImageData.width}`);
println(`height: ${clonedImageData.height}`);
println(`data byteLength: ${clonedImageData.data.byteLength}`);
println(`data filled with 0x41? ${clonedImageData.data.every((val) => val === 0x41)}`);
println(`not the same data array? ${imageData.data !== clonedImageData.data}`);
println("=== after clone end ===");
});
</script>