diff --git a/Tests/LibWeb/Text/expected/HTML/StructuredClone-serializable-objects.txt b/Tests/LibWeb/Text/expected/HTML/StructuredClone-serializable-objects.txt index ef45185e3da..58fd081e04f 100644 --- a/Tests/LibWeb/Text/expected/HTML/StructuredClone-serializable-objects.txt +++ b/Tests/LibWeb/Text/expected/HTML/StructuredClone-serializable-objects.txt @@ -5,4 +5,7 @@ instanceOf File: true File.name: hello.txt File.type: text/plain File.text(): Hello, File! -File.size: 12 \ No newline at end of file +File.size: 12 +instanceOf DOMMatrixReadOnly: true +DOMMatrixReadOnly: {"a":1.7976931348623157e+308,"b":2.2250738585072014e-308,"c":2.220446049250313e-16,"d":40,"e":50,"f":60,"m11":1.7976931348623157e+308,"m12":2.2250738585072014e-308,"m13":0,"m14":0,"m21":2.220446049250313e-16,"m22":40,"m23":0,"m24":0,"m31":0,"m32":0,"m33":1,"m34":0,"m41":50,"m42":60,"m43":0,"m44":1,"is2D":true,"isIdentity":false} +DOMMatrixReadOnly: {"a":10,"b":20,"c":50,"d":60,"e":130,"f":140,"m11":10,"m12":20,"m13":30,"m14":40,"m21":50,"m22":60,"m23":70,"m24":80,"m31":90,"m32":100,"m33":110,"m34":120,"m41":130,"m42":140,"m43":150,"m44":160,"is2D":false,"isIdentity":false} diff --git a/Tests/LibWeb/Text/input/HTML/StructuredClone-serializable-objects.html b/Tests/LibWeb/Text/input/HTML/StructuredClone-serializable-objects.html index d0a34772628..1a6934d78e3 100644 --- a/Tests/LibWeb/Text/input/HTML/StructuredClone-serializable-objects.html +++ b/Tests/LibWeb/Text/input/HTML/StructuredClone-serializable-objects.html @@ -15,6 +15,12 @@ println(`File.text(): ${text}`); println(`File.size: ${file.size}`); + let domMatrixReadOnly = structuredClone(new DOMMatrixReadOnly([1.7976931348623157e+308, 2.2250738585072014e-308, 2.2204460492503131e-016, 40, 50, 60])); + println(`instanceOf DOMMatrixReadOnly: ${domMatrixReadOnly instanceof DOMMatrixReadOnly}`); + println(`DOMMatrixReadOnly: ${JSON.stringify(domMatrixReadOnly)}`); + domMatrixReadOnly = structuredClone(new DOMMatrixReadOnly([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160])); + println(`DOMMatrixReadOnly: ${JSON.stringify(domMatrixReadOnly)}`); + done(); }); diff --git a/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.cpp b/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.cpp index 90aee5e7147..90816192116 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.cpp +++ b/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2023, Luke Wilde * Copyright (c) 2023, Bastiaan van der Plaat + * Copyright (c) 2024, Kenneth Myhra * * SPDX-License-Identifier: BSD-2-Clause */ @@ -12,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -115,6 +117,11 @@ WebIDL::ExceptionOr> DOMMatrixReadOnly::crea init.m41.value(), init.m42.value(), init.m43, init.m44); } +JS::NonnullGCPtr DOMMatrixReadOnly::create(JS::Realm& realm) +{ + return realm.heap().allocate(realm, realm); +} + DOMMatrixReadOnly::DOMMatrixReadOnly(JS::Realm& realm, double m11, double m12, double m21, double m22, double m41, double m42) : Bindings::PlatformObject(realm) { @@ -134,6 +141,11 @@ DOMMatrixReadOnly::DOMMatrixReadOnly(JS::Realm& realm, DOMMatrixReadOnly const& { } +DOMMatrixReadOnly::DOMMatrixReadOnly(JS::Realm& realm) + : Bindings::PlatformObject(realm) +{ +} + DOMMatrixReadOnly::~DOMMatrixReadOnly() = default; void DOMMatrixReadOnly::initialize(JS::Realm& realm) @@ -685,6 +697,140 @@ WebIDL::ExceptionOr DOMMatrixReadOnly::to_string() const return TRY_OR_THROW_OOM(vm, builder.to_string()); } +// https://drafts.fxtf.org/geometry/#structured-serialization +WebIDL::ExceptionOr DOMMatrixReadOnly::serialization_steps(HTML::SerializationRecord& serialized, bool) +{ + HTML::serialize_primitive_type(serialized, m_is_2d); + // 1. If value’s is 2D is true: + if (m_is_2d) { + // 1. Set serialized.[[M11]] to value’s m11 element. + HTML::serialize_primitive_type(serialized, this->m11()); + // 2. Set serialized.[[M12]] to value’s m12 element. + HTML::serialize_primitive_type(serialized, this->m12()); + // 3. Set serialized.[[M21]] to value’s m21 element. + HTML::serialize_primitive_type(serialized, this->m21()); + // 4. Set serialized.[[M22]] to value’s m22 element. + HTML::serialize_primitive_type(serialized, this->m22()); + // 5. Set serialized.[[M41]] to value’s m41 element. + HTML::serialize_primitive_type(serialized, this->m41()); + // 6. Set serialized.[[M42]] to value’s m42 element. + HTML::serialize_primitive_type(serialized, this->m42()); + // 7. Set serialized.[[Is2D]] to true. + // NOTE: This is set in the beginning of the function. + } + // 2. Otherwise: + else { + // 1. Set serialized.[[M11]] to value’s m11 element. + HTML::serialize_primitive_type(serialized, this->m11()); + // 2. Set serialized.[[M12]] to value’s m12 element. + HTML::serialize_primitive_type(serialized, this->m12()); + // 3. Set serialized.[[M13]] to value’s m13 element. + HTML::serialize_primitive_type(serialized, this->m13()); + // 4. Set serialized.[[M14]] to value’s m14 element. + HTML::serialize_primitive_type(serialized, this->m14()); + // 5. Set serialized.[[M21]] to value’s m21 element. + HTML::serialize_primitive_type(serialized, this->m21()); + // 6. Set serialized.[[M22]] to value’s m22 element. + HTML::serialize_primitive_type(serialized, this->m22()); + // 7. Set serialized.[[M23]] to value’s m23 element. + HTML::serialize_primitive_type(serialized, this->m23()); + // 8. Set serialized.[[M24]] to value’s m24 element. + HTML::serialize_primitive_type(serialized, this->m24()); + // 9. Set serialized.[[M31]] to value’s m31 element. + HTML::serialize_primitive_type(serialized, this->m31()); + // 10. Set serialized.[[M32]] to value’s m32 element. + HTML::serialize_primitive_type(serialized, this->m32()); + // 11. Set serialized.[[M33]] to value’s m33 element. + HTML::serialize_primitive_type(serialized, this->m33()); + // 12. Set serialized.[[M34]] to value’s m34 element. + HTML::serialize_primitive_type(serialized, this->m34()); + // 13. Set serialized.[[M41]] to value’s m41 element. + HTML::serialize_primitive_type(serialized, this->m41()); + // 14. Set serialized.[[M42]] to value’s m42 element. + HTML::serialize_primitive_type(serialized, this->m42()); + // 15. Set serialized.[[M43]] to value’s m43 element. + HTML::serialize_primitive_type(serialized, this->m43()); + // 16. Set serialized.[[M44]] to value’s m44 element. + HTML::serialize_primitive_type(serialized, this->m44()); + // 17. Set serialized.[[Is2D]] to false. + // NOTE: This is set in the beginning of the function. + } + return {}; +} + +// https://drafts.fxtf.org/geometry/#structured-serialization +WebIDL::ExceptionOr DOMMatrixReadOnly::deserialization_steps(ReadonlySpan const& record, size_t& position) +{ + bool is_2d = HTML::deserialize_primitive_type(record, position); + // 1. If serialized.[[Is2D]] is true: + if (is_2d) { + // 1. Set value’s m11 element to serialized.[[M11]]. + double m11 = HTML::deserialize_primitive_type(record, position); + // 2. Set value’s m12 element to serialized.[[M12]]. + double m12 = HTML::deserialize_primitive_type(record, position); + // 3. Set value’s m13 element to 0. + // 4. Set value’s m14 element to 0. + // 5. Set value’s m21 element to serialized.[[M21]]. + double m21 = HTML::deserialize_primitive_type(record, position); + // 6. Set value’s m22 element to serialized.[[M22]]. + double m22 = HTML::deserialize_primitive_type(record, position); + // 7. Set value’s m23 element to 0. + // 8. Set value’s m24 element to 0. + // 9. Set value’s m31 element to 0. + // 10. Set value’s m32 element to 0. + // 11. Set value’s m33 element to 1. + // 12. Set value’s m34 element to 0. + // 13. Set value’s m41 element to serialized.[[M41]]. + double m41 = HTML::deserialize_primitive_type(record, position); + // 14 Set value’s m42 element to serialized.[[M42]]. + double m42 = HTML::deserialize_primitive_type(record, position); + // 15. Set value’s m43 element to 0. + // 16. Set value’s m44 element to 1. + // 17. Set value’s is 2D to true. + + initialize_from_create_2d_matrix(m11, m12, m21, m22, m41, m42); + } + // 2. Otherwise: + else { + // 1. Set value’s m11 element to serialized.[[M11]]. + double m11 = HTML::deserialize_primitive_type(record, position); + // 2. Set value’s m12 element to serialized.[[M12]]. + double m12 = HTML::deserialize_primitive_type(record, position); + // 3. Set value’s m13 element to serialized.[[M13]]. + double m13 = HTML::deserialize_primitive_type(record, position); + // 4. Set value’s m14 element to serialized.[[M14]]. + double m14 = HTML::deserialize_primitive_type(record, position); + // 5. Set value’s m21 element to serialized.[[M21]]. + double m21 = HTML::deserialize_primitive_type(record, position); + // 6. Set value’s m22 element to serialized.[[M22]]. + double m22 = HTML::deserialize_primitive_type(record, position); + // 7. Set value’s m23 element to serialized.[[M23]]. + double m23 = HTML::deserialize_primitive_type(record, position); + // 8. Set value’s m24 element to serialized.[[M24]]. + double m24 = HTML::deserialize_primitive_type(record, position); + // 9. Set value’s m31 element to serialized.[[M31]]. + double m31 = HTML::deserialize_primitive_type(record, position); + // 10. Set value’s m32 element to serialized.[[M32]]. + double m32 = HTML::deserialize_primitive_type(record, position); + // 11. Set value’s m33 element to serialized.[[M33]]. + double m33 = HTML::deserialize_primitive_type(record, position); + // 12. Set value’s m34 element to serialized.[[M34]]. + double m34 = HTML::deserialize_primitive_type(record, position); + // 13. Set value’s m41 element to serialized.[[M41]]. + double m41 = HTML::deserialize_primitive_type(record, position); + // 14. Set value’s m42 element to serialized.[[M42]]. + double m42 = HTML::deserialize_primitive_type(record, position); + // 15. Set value’s m43 element to serialized.[[M43]]. + double m43 = HTML::deserialize_primitive_type(record, position); + // 16. Set value’s m44 element to serialized.[[M44]]. + double m44 = HTML::deserialize_primitive_type(record, position); + // 17. Set value’s is 2D to false. + + initialize_from_create_3d_matrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44); + } + return {}; +} + // https://drafts.fxtf.org/geometry/#matrix-validate-and-fixup-2d WebIDL::ExceptionOr validate_and_fixup_dom_matrix_2d_init(DOMMatrix2DInit& init) { diff --git a/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.h b/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.h index ad5d6092a97..7a6882dd23c 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.h +++ b/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2023, Luke Wilde * Copyright (c) 2023, Bastiaan van der Plaat + * Copyright (c) 2024, Kenneth Myhra * * SPDX-License-Identifier: BSD-2-Clause */ @@ -9,6 +10,7 @@ #include #include +#include #include #include @@ -46,13 +48,16 @@ struct DOMMatrixInit : public DOMMatrix2DInit { }; // https://drafts.fxtf.org/geometry/#dommatrixreadonly -class DOMMatrixReadOnly : public Bindings::PlatformObject { +class DOMMatrixReadOnly + : public Bindings::PlatformObject + , public Bindings::Serializable { WEB_PLATFORM_OBJECT(DOMMatrixReadOnly, Bindings::PlatformObject); public: static WebIDL::ExceptionOr> construct_impl(JS::Realm&, Optional>> const& init); static WebIDL::ExceptionOr> create_from_dom_matrix_2d_init(JS::Realm&, DOMMatrix2DInit& init); static WebIDL::ExceptionOr> create_from_dom_matrix_init(JS::Realm&, DOMMatrixInit& init); + static JS::NonnullGCPtr create(JS::Realm&); virtual ~DOMMatrixReadOnly() override; @@ -109,10 +114,15 @@ public: WebIDL::ExceptionOr to_string() const; + virtual StringView interface_name() const override { return "DOMMatrixReadOnly"sv; } + virtual WebIDL::ExceptionOr serialization_steps(HTML::SerializationRecord&, bool for_storage) override; + virtual WebIDL::ExceptionOr deserialization_steps(ReadonlySpan const& record, size_t& position) override; + protected: DOMMatrixReadOnly(JS::Realm&, double m11, double m12, double m21, double m22, double m41, double m42); DOMMatrixReadOnly(JS::Realm&, double m11, double m12, double m13, double m14, double m21, double m22, double m23, double m24, double m31, double m32, double m33, double m34, double m41, double m42, double m43, double m44); DOMMatrixReadOnly(JS::Realm&, DOMMatrixReadOnly const& other); + explicit DOMMatrixReadOnly(JS::Realm&); // NOTE: The matrix used in the spec is column-major (https://drafts.fxtf.org/geometry/#4x4-abstract-matrix) but Gfx::Matrix4x4 is row-major so we need to transpose the values. Gfx::DoubleMatrix4x4 m_matrix { Gfx::DoubleMatrix4x4::identity() }; diff --git a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp index 4f61d46d233..f5e9af31189 100644 --- a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp +++ b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -963,6 +964,8 @@ private: return FileAPI::Blob::create(realm); if (interface_name == "File"sv) return FileAPI::File::create(realm); + if (interface_name == "DOMMatrixReadOnly"sv) + return Geometry::DOMMatrixReadOnly::create(realm); VERIFY_NOT_REACHED(); }