diff --git a/Cargo.lock b/Cargo.lock index d887785b19a48f..162b5bafbf9628 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,6 +94,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "getrandom 0.2.14", "once_cell", "version_check", "zerocopy", @@ -193,6 +194,15 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "arbitrary" version = "1.4.1" @@ -1114,12 +1124,41 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-str" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21077772762a1002bb421c3af42ac1725fa56066bfc53d9a55bb79905df2aaf3" +dependencies = [ + "const-str-proc-macro", +] + +[[package]] +name = "const-str-proc-macro" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1e0fdd2e5d3041e530e1b21158aeeef8b5d0e306bc5c1e3d6cf0930d10e25a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "convert_case" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "cooked-waker" version = "5.0.0" @@ -1437,6 +1476,19 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25670139e591f1c2869eb8d0d977028f8d05e859132b4c874ecd02a00d3c9174" +[[package]] +name = "cssparser" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be934d936a0fbed5bcdc01042b770de1398bf79d0e192f49fa7faea0e99281e" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + [[package]] name = "cssparser" version = "0.35.0" @@ -1450,6 +1502,15 @@ dependencies = [ "smallvec", ] +[[package]] +name = "cssparser-color" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556c099a61d85989d7af52b692e35a8d68a57e7df8c6d07563dc0778b3960c9f" +dependencies = [ + "cssparser 0.33.0", +] + [[package]] name = "cssparser-macros" version = "0.6.1" @@ -2185,6 +2246,17 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "deno_geometry" +version = "0.1.0" +dependencies = [ + "deno_core", + "deno_error", + "lightningcss", + "nalgebra", + "thiserror 2.0.12", +] + [[package]] name = "deno_graph" version = "0.101.0" @@ -2871,6 +2943,7 @@ dependencies = [ "deno_fetch", "deno_ffi", "deno_fs", + "deno_geometry", "deno_http", "deno_io", "deno_kv", @@ -3437,7 +3510,7 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case", + "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version 0.4.0", @@ -4511,6 +4584,102 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "glam" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da" + +[[package]] +name = "glam" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3abb554f8ee44336b72d522e0a7fe86a29e09f839a36022fa869a7dfe941a54b" + +[[package]] +name = "glam" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4126c0479ccf7e8664c36a2d719f5f2c140fbb4f9090008098d2c291fa5b3f16" + +[[package]] +name = "glam" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01732b97afd8508eee3333a541b9f7610f454bb818669e66e90f5f57c93a776" + +[[package]] +name = "glam" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525a3e490ba77b8e326fb67d4b44b4bd2f920f44d4cc73ccec50adc68e3bee34" + +[[package]] +name = "glam" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b8509e6791516e81c1a630d0bd7fbac36d2fa8712a9da8662e716b52d5051ca" + +[[package]] +name = "glam" +version = "0.20.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f" + +[[package]] +name = "glam" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815" + +[[package]] +name = "glam" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774" + +[[package]] +name = "glam" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c" + +[[package]] +name = "glam" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" + +[[package]] +name = "glam" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3" + +[[package]] +name = "glam" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9" + +[[package]] +name = "glam" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94" + +[[package]] +name = "glam" +version = "0.29.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee" + +[[package]] +name = "glam" +version = "0.30.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d1aab06663bdce00d6ca5e5ed586ec8d18033a771906c993a1e3755b368d85" + [[package]] name = "glob" version = "0.3.1" @@ -5522,6 +5691,15 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -5887,6 +6065,41 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "lightningcss" +version = "1.0.0-alpha.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "798fba4e1205eed356b8ed7754cc3f7f04914e27855ca641409f4a532e992149" +dependencies = [ + "ahash", + "bitflags 2.9.3", + "const-str", + "cssparser 0.33.0", + "cssparser-color", + "data-encoding", + "getrandom 0.2.14", + "indexmap 2.9.0", + "itertools 0.10.5", + "lazy_static", + "lightningcss-derive", + "parcel_selectors", + "paste", + "pathdiff", + "smallvec", +] + +[[package]] +name = "lightningcss-derive" +version = "1.0.0-alpha.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12744d1279367caed41739ef094c325d53fb0ffcd4f9b84a368796f870252" +dependencies = [ + "convert_case 0.6.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -5938,7 +6151,7 @@ checksum = "b63d49c99bfbf3400dd6450e516515b7014fcb49b5cb533f4b725a00c1462a36" dependencies = [ "bitflags 2.9.3", "cfg-if", - "cssparser", + "cssparser 0.35.0", "encoding_rs", "hashbrown 0.15.5", "memchr", @@ -6036,6 +6249,16 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "matrixmultiply" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2" +dependencies = [ + "autocfg", + "rawpointer", +] + [[package]] name = "md-5" version = "0.10.6" @@ -6209,6 +6432,37 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "nalgebra" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd59afb6639828b33677758314a4a1a745c15c02bc597095b851c8fd915cf49" +dependencies = [ + "approx", + "glam 0.14.0", + "glam 0.15.2", + "glam 0.16.0", + "glam 0.17.3", + "glam 0.18.0", + "glam 0.19.0", + "glam 0.20.5", + "glam 0.21.3", + "glam 0.22.0", + "glam 0.23.0", + "glam 0.24.2", + "glam 0.25.0", + "glam 0.27.0", + "glam 0.28.0", + "glam 0.29.3", + "glam 0.30.5", + "matrixmultiply", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum", +] + [[package]] name = "napi-build" version = "1.2.1" @@ -6796,6 +7050,22 @@ dependencies = [ "once_cell", ] +[[package]] +name = "parcel_selectors" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54fd03f1ad26cb6b3ec1b7414fa78a3bd639e7dbb421b1a60513c96ce886a196" +dependencies = [ + "bitflags 2.9.3", + "cssparser 0.33.0", + "log", + "phf", + "phf_codegen", + "precomputed-hash", + "rustc-hash 2.1.1", + "smallvec", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -7525,6 +7795,12 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cc3bcbdb1ddfc11e700e62968e6b4cc9c75bb466464ad28fb61c5b2c964418b" +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rayon" version = "1.10.0" @@ -8153,7 +8429,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3df44ba8a7ca7a4d28c589e04f526266ed76b6cc556e33fe69fa25de31939a65" dependencies = [ "bitflags 2.9.3", - "cssparser", + "cssparser 0.35.0", "derive_more 2.0.1", "fxhash", "log", @@ -8419,6 +8695,19 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simba" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + [[package]] name = "simd-adler32" version = "0.3.7" diff --git a/Cargo.toml b/Cargo.toml index 9b7abf74df423d..69338c3b175eb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = [ "ext/fetch", "ext/ffi", "ext/fs", + "ext/geometry", "ext/http", "ext/io", "ext/kv", @@ -97,6 +98,7 @@ deno_crypto = { version = "0.231.0", path = "./ext/crypto" } deno_fetch = { version = "0.241.0", path = "./ext/fetch" } deno_ffi = { version = "0.204.0", path = "./ext/ffi" } deno_fs = { version = "0.127.0", path = "./ext/fs" } +deno_geometry = { version = "0.1.0", path = "./ext/geometry" } deno_http = { version = "0.215.0", path = "./ext/http" } deno_io = { version = "0.127.0", path = "./ext/io" } deno_kv = { version = "0.125.0", path = "./ext/kv" } @@ -382,6 +384,10 @@ libuv-sys-lite = "=1.48.2" napi-build = "1" napi-sys = { version = "=2.2.2", default-features = false } +# geometry +lightningcss = { version = "1.0.0-alpha.67", default-features = false } +nalgebra = { version = "0.34.0", default-features = false, features = ["std"] } + # webgpu raw-window-handle = "0.6.0" wgpu-core = "24.0.0" @@ -451,6 +457,8 @@ opt-level = 3 opt-level = 3 [profile.release.package.deno_ffi] opt-level = 3 +[profile.release.package.deno_geometry] +opt-level = 3 [profile.release.package.deno_http] opt-level = 3 [profile.release.package.deno_napi] diff --git a/cli/build.rs b/cli/build.rs index 0ef22879779e29..16463d01b025c9 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -20,6 +20,7 @@ fn compress_decls(out_dir: &Path) { "lib.deno_url.d.ts", "lib.deno_web.d.ts", "lib.deno_fetch.d.ts", + "lib.deno_geometry.d.ts", "lib.deno_websocket.d.ts", "lib.deno_webstorage.d.ts", "lib.deno_canvas.d.ts", diff --git a/cli/tsc/dts/lib.deno.shared_globals.d.ts b/cli/tsc/dts/lib.deno.shared_globals.d.ts index 50f7e82e20bb5d..21b43e89c4c9f9 100644 --- a/cli/tsc/dts/lib.deno.shared_globals.d.ts +++ b/cli/tsc/dts/lib.deno.shared_globals.d.ts @@ -11,6 +11,7 @@ /// /// /// +/// /// /// /// diff --git a/cli/tsc/dts/lib.deno_geometry.d.ts b/cli/tsc/dts/lib.deno_geometry.d.ts new file mode 100644 index 00000000000000..e2a6063d91bf4f --- /dev/null +++ b/cli/tsc/dts/lib.deno_geometry.d.ts @@ -0,0 +1,792 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +// deno-lint-ignore-file no-var + +/// +/// + +/** + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMMatrix2DInit { + a?: number; + b?: number; + c?: number; + d?: number; + e?: number; + f?: number; + m11?: number; + m12?: number; + m21?: number; + m22?: number; + m41?: number; + m42?: number; +} + +/** + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMMatrixInit extends DOMMatrix2DInit { + is2D?: boolean; + m13?: number; + m14?: number; + m23?: number; + m24?: number; + m31?: number; + m32?: number; + m33?: number; + m34?: number; + m43?: number; + m44?: number; +} + +/** + * The **`DOMMatrix`** interface represents 4×4 matrices, suitable for 2D and 3D operations including rotation and translation. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMMatrix) + * + * ``` + * | m11 m21 m31 m41 | + * | m12 m22 m32 m42 | + * | m13 m23 m33 m43 | + * | m14 m24 m34 m44 | + * ``` + * + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMMatrix extends DOMMatrixReadOnly { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + a: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + b: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + c: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + d: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + e: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + f: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m11: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m12: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m13: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m14: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m21: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m22: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m23: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m24: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m31: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m32: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m33: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m34: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m41: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m42: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m43: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix#instance_properties) */ + m44: number; + /** + * The **`invertSelf()`** method of the DOMMatrix interface inverts the original matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/invertSelf) + */ + invertSelf(): DOMMatrix; + /** + * The **`multiplySelf()`** method of the DOMMatrix interface multiplies a matrix by the `otherMatrix` parameter, computing the dot product of the original matrix and the specified matrix: `A⋅B`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/multiplySelf) + */ + multiplySelf(other?: DOMMatrixInit): DOMMatrix; + /** + * The **`preMultiplySelf()`** method of the DOMMatrix interface modifies the matrix by pre-multiplying it with the specified `DOMMatrix`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/preMultiplySelf) + */ + preMultiplySelf(other?: DOMMatrixInit): DOMMatrix; + /** + * The `rotateAxisAngleSelf()` method of the DOMMatrix interface is a transformation method that rotates the source matrix by the given vector and angle, returning the altered matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/rotateAxisAngleSelf) + */ + rotateAxisAngleSelf( + x?: number, + y?: number, + z?: number, + angle?: number, + ): DOMMatrix; + /** + * The `rotateFromVectorSelf()` method of the DOMMatrix interface is a mutable transformation method that modifies a matrix by rotating the matrix by the angle between the specified vector and `(1, 0)`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/rotateFromVectorSelf) + */ + rotateFromVectorSelf(x?: number, y?: number): DOMMatrix; + /** + * The `rotateSelf()` method of the DOMMatrix interface is a mutable transformation method that modifies a matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/rotateSelf) + */ + rotateSelf(rotX?: number, rotY?: number, rotZ?: number): DOMMatrix; + /** + * The **`scale3dSelf()`** method of the DOMMatrix interface is a mutable transformation method that modifies a matrix by applying a specified scaling factor to all three axes, centered on the given origin, with a default origin of `(0, 0, 0)`, returning the 3D-scaled matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/scale3dSelf) + */ + scale3dSelf( + scale?: number, + originX?: number, + originY?: number, + originZ?: number, + ): DOMMatrix; + /** + * The **`scaleSelf()`** method of the DOMMatrix interface is a mutable transformation method that modifies a matrix by applying a specified scaling factor, centered on the given origin, with a default origin of `(0, 0)`, returning the scaled matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/scaleSelf) + */ + scaleSelf( + scaleX?: number, + scaleY?: number, + scaleZ?: number, + originX?: number, + originY?: number, + originZ?: number, + ): DOMMatrix; + /** + * The **`setMatrixValue()`** method of the DOMMatrix interface replaces the contents of the matrix with the matrix described by the specified transform or transforms, returning itself. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/setMatrixValue) + */ + setMatrixValue(transformList: string): DOMMatrix; + /** + * The `skewXSelf()` method of the DOMMatrix interface is a mutable transformation method that modifies a matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/skewXSelf) + */ + skewXSelf(sx?: number): DOMMatrix; + /** + * The `skewYSelf()` method of the DOMMatrix interface is a mutable transformation method that modifies a matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/skewYSelf) + */ + skewYSelf(sy?: number): DOMMatrix; + /** + * The `translateSelf()` method of the DOMMatrix interface is a mutable transformation method that modifies a matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrix/translateSelf) + */ + translateSelf(tx?: number, ty?: number, tz?: number): DOMMatrix; +} + +/** + * A 4×4 matrix (column-major order), suitable for 2D and 3D operations including rotation and translation. + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMMatrix) + * + * ``` + * | m11 m21 m31 m41 | + * | m12 m22 m32 m42 | + * | m13 m23 m33 m43 | + * | m14 m24 m34 m44 | + * ``` + * + * @category Geometry Interfaces Module API + * @experimental + */ +declare var DOMMatrix: { + prototype: DOMMatrix; + new (init?: string | number[]): DOMMatrix; + fromFloat32Array(array32: Float32Array): DOMMatrix; + fromFloat64Array(array64: Float64Array): DOMMatrix; + fromMatrix(other?: DOMMatrixInit): DOMMatrix; +}; + +/** + * The **`DOMMatrixReadOnly`** interface represents a read-only 4×4 matrix, suitable for 2D and 3D operations. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly) + * + * ``` + * | m11 m21 m31 m41 | + * | m12 m22 m32 m42 | + * | m13 m23 m33 m43 | + * | m14 m24 m34 m44 | + * ``` + * + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMMatrixReadOnly { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly a: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly b: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly c: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly d: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly e: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly f: number; + /** + * The readonly **`is2D`** property of the DOMMatrixReadOnly interface is a Boolean flag that is `true` when the matrix is 2D. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/is2D) + */ + readonly is2D: boolean; + /** + * The readonly **`isIdentity`** property of the DOMMatrixReadOnly interface is a Boolean whose value is `true` if the matrix is the identity matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/isIdentity) + */ + readonly isIdentity: boolean; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m11: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m12: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m13: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m14: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m21: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m22: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m23: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m24: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m31: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m32: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m33: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m34: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m41: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m42: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m43: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly#instance_properties) */ + readonly m44: number; + /** + * The **`flipX()`** method of the DOMMatrixReadOnly interface creates a new matrix being the result of the original matrix flipped about the x-axis. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/flipX) + */ + flipX(): DOMMatrix; + /** + * The **`flipY()`** method of the DOMMatrixReadOnly interface creates a new matrix being the result of the original matrix flipped about the y-axis. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/flipY) + */ + flipY(): DOMMatrix; + /** + * The **`inverse()`** method of the DOMMatrixReadOnly interface creates a new matrix which is the inverse of the original matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/inverse) + */ + inverse(): DOMMatrix; + /** + * The **`multiply()`** method of the DOMMatrixReadOnly interface creates and returns a new matrix which is the dot product of the matrix and the `otherMatrix` parameter. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/multiply) + */ + multiply(other?: DOMMatrixInit): DOMMatrix; + /** + * The `rotate()` method of the DOMMatrixReadOnly interface returns a new DOMMatrix created by rotating the source matrix around each of its axes by the specified number of degrees. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/rotate) + */ + rotate(rotX?: number, rotY?: number, rotZ?: number): DOMMatrix; + /** + * The `rotateAxisAngle()` method of the DOMMatrixReadOnly interface returns a new DOMMatrix created by rotating the source matrix by the given vector and angle. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/rotateAxisAngle) + */ + rotateAxisAngle( + x?: number, + y?: number, + z?: number, + angle?: number, + ): DOMMatrix; + /** + * The `rotateFromVector()` method of the DOMMatrixReadOnly interface is returns a new DOMMatrix created by rotating the source matrix by the angle between the specified vector and `(1, 0)`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/rotateFromVector) + */ + rotateFromVector(x?: number, y?: number): DOMMatrix; + /** + * The **`scale()`** method of the original matrix with a scale transform applied. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/scale) + */ + scale( + scaleX?: number, + scaleY?: number, + scaleZ?: number, + originX?: number, + originY?: number, + originZ?: number, + ): DOMMatrix; + /** + * The **`scale3d()`** method of the DOMMatrixReadOnly interface creates a new matrix which is the result of a 3D scale transform being applied to the matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/scale3d) + */ + scale3d( + scale?: number, + originX?: number, + originY?: number, + originZ?: number, + ): DOMMatrix; + /** @deprecated */ + scaleNonUniform(scaleX?: number, scaleY?: number): DOMMatrix; + /** + * The `skewX()` method of the DOMMatrixReadOnly interface returns a new DOMMatrix created by applying the specified skew transformation to the source matrix along its x-axis. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/skewX) + */ + skewX(sx?: number): DOMMatrix; + /** + * The `skewY()` method of the DOMMatrixReadOnly interface returns a new DOMMatrix created by applying the specified skew transformation to the source matrix along its y-axis. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/skewY) + */ + skewY(sy?: number): DOMMatrix; + /** + * The **`toFloat32Array()`** method of the DOMMatrixReadOnly interface returns a new Float32Array containing all 16 elements (`m11`, `m12`, `m13`, `m14`, `m21`, `m22`, `m23`, `m24`, `m31`, `m32`, `m33`, `m34`, `m41`, `m42`, `m43`, `m44`) which comprise the matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/toFloat32Array) + */ + toFloat32Array(): Float32Array; + /** + * The **`toFloat64Array()`** method of the DOMMatrixReadOnly interface returns a new Float64Array containing all 16 elements (`m11`, `m12`, `m13`, `m14`, `m21`, `m22`, `m23`, `m24`, `m31`, `m32`, `m33`, `m34`, `m41`, `m42`, `m43`, `m44`) which comprise the matrix. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/toFloat64Array) + */ + toFloat64Array(): Float64Array; + /** + * The **`toJSON()`** method of the DOMMatrixReadOnly interface creates and returns a JSON object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/toJSON) + */ + toJSON(): any; + /** + * The **`transformPoint`** method of the You can also create a new `DOMPoint` by applying a matrix to a point with the DOMPointReadOnly.matrixTransform() method. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/transformPoint) + */ + transformPoint(point?: DOMPointInit): DOMPoint; + /** + * The `translate()` method of the DOMMatrixReadOnly interface creates a new matrix being the result of the original matrix with a translation applied. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly/translate) + */ + translate(tx?: number, ty?: number, tz?: number): DOMMatrix; + toString(): string; +} + +/** + * The **`DOMMatrixReadOnly`** interface represents a read-only 4×4 matrix, suitable for 2D and 3D operations. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMMatrixReadOnly) + * + * ``` + * | m11 m21 m31 m41 | + * | m12 m22 m32 m42 | + * | m13 m23 m33 m43 | + * | m14 m24 m34 m44 | + * ``` + * + * @category Geometry Interfaces Module API + * @experimental + */ +declare var DOMMatrixReadOnly: { + prototype: DOMMatrixReadOnly; + new (init?: string | number[]): DOMMatrixReadOnly; + fromFloat32Array(array32: Float32Array): DOMMatrixReadOnly; + fromFloat64Array(array64: Float64Array): DOMMatrixReadOnly; + fromMatrix(other?: DOMMatrixInit): DOMMatrixReadOnly; +}; + +/** + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMPointInit { + w?: number; + x?: number; + y?: number; + z?: number; +} + +/** + * A **`DOMPoint`** object represents a 2D or 3D point in a coordinate system; it includes values for the coordinates in up to three dimensions, as well as an optional perspective value. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMPoint) + * + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMPoint extends DOMPointReadOnly { + /** + * The **`DOMPoint`** interface's **`w`** property holds the point's perspective value, w, for a point in space. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPoint/w) + */ + w: number; + /** + * The **`DOMPoint`** interface's **`x`** property holds the horizontal coordinate, x, for a point in space. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPoint/x) + */ + x: number; + /** + * The **`DOMPoint`** interface's **`y`** property holds the vertical coordinate, _y_, for a point in space. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPoint/y) + */ + y: number; + /** + * The **`DOMPoint`** interface's **`z`** property specifies the depth coordinate of a point in space. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPoint/z) + */ + z: number; +} + +/** + * A **`DOMPoint`** object represents a 2D or 3D point in a coordinate system; it includes values for the coordinates in up to three dimensions, as well as an optional perspective value. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMPoint) + * + * @category Geometry Interfaces Module API + * @experimental + */ +declare var DOMPoint: { + prototype: DOMPoint; + new (x?: number, y?: number, z?: number, w?: number): DOMPoint; + /** + * The **`fromPoint()`** static method of the DOMPoint interface creates and returns a new mutable `DOMPoint` object given a source point. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPoint/fromPoint_static) + */ + fromPoint(other?: DOMPointInit): DOMPoint; +}; + +/** + * The **`DOMPointReadOnly`** interface specifies the coordinate and perspective fields used by DOMPoint to define a 2D or 3D point in a coordinate system. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly) + * + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMPointReadOnly { + /** + * The **`DOMPointReadOnly`** interface's **`w`** property holds the point's perspective value, `w`, for a read-only point in space. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/w) + */ + readonly w: number; + /** + * The **`DOMPointReadOnly`** interface's **`x`** property holds the horizontal coordinate, x, for a read-only point in space. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/x) + */ + readonly x: number; + /** + * The **`DOMPointReadOnly`** interface's **`y`** property holds the vertical coordinate, y, for a read-only point in space. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/y) + */ + readonly y: number; + /** + * The **`DOMPointReadOnly`** interface's **`z`** property holds the depth coordinate, z, for a read-only point in space. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/z) + */ + readonly z: number; + /** + * The **`matrixTransform()`** method of the DOMPointReadOnly interface applies a matrix transform specified as an object to the DOMPointReadOnly object, creating and returning a new `DOMPointReadOnly` object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/matrixTransform) + */ + matrixTransform(matrix?: DOMMatrixInit): DOMPoint; + /** + * The DOMPointReadOnly method `toJSON()` returns an object giving the ```js-nolint toJSON() ``` None. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/toJSON) + */ + toJSON(): any; +} + +/** + * The **`DOMPointReadOnly`** interface specifies the coordinate and perspective fields used by DOMPoint to define a 2D or 3D point in a coordinate system. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly) + * + * @category Geometry Interfaces Module API + * @experimental + */ +declare var DOMPointReadOnly: { + prototype: DOMPointReadOnly; + new (x?: number, y?: number, z?: number, w?: number): DOMPointReadOnly; + /** + * The static **DOMPointReadOnly** method `fromPoint()` creates and returns a new `DOMPointReadOnly` object given a source point. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMPointReadOnly/fromPoint_static) + */ + fromPoint(other?: DOMPointInit): DOMPointReadOnly; +}; + +/** + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMQuadInit { + p1?: DOMPointInit; + p2?: DOMPointInit; + p3?: DOMPointInit; + p4?: DOMPointInit; +} + +/** + * A `DOMQuad` is a collection of four `DOMPoint`s defining the corners of an arbitrary quadrilateral. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMQuad) + * + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMQuad { + /** + * The **`DOMQuad`** interface's **`p1`** property holds the DOMPoint object that represents one of the four corners of the `DOMQuad`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p1) + */ + readonly p1: DOMPoint; + /** + * The **`DOMQuad`** interface's **`p2`** property holds the DOMPoint object that represents one of the four corners of the `DOMQuad`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p2) + */ + readonly p2: DOMPoint; + /** + * The **`DOMQuad`** interface's **`p3`** property holds the DOMPoint object that represents one of the four corners of the `DOMQuad`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p3) + */ + readonly p3: DOMPoint; + /** + * The **`DOMQuad`** interface's **`p4`** property holds the DOMPoint object that represents one of the four corners of the `DOMQuad`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/p4) + */ + readonly p4: DOMPoint; + /** + * The DOMQuad method `getBounds()` returns a DOMRect object representing the smallest rectangle that fully contains the `DOMQuad` object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/getBounds) + */ + getBounds(): DOMRect; + /** + * The DOMQuad method `toJSON()` returns a ```js-nolint toJSON() ``` None. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMQuad/toJSON) + */ + toJSON(): any; +} + +/** + * A `DOMQuad` is a collection of four `DOMPoint`s defining the corners of an arbitrary quadrilateral. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMQuad) + * + * @category Geometry Interfaces Module API + * @experimental + */ +declare var DOMQuad: { + prototype: DOMQuad; + new ( + p1?: DOMPointInit, + p2?: DOMPointInit, + p3?: DOMPointInit, + p4?: DOMPointInit, + ): DOMQuad; + fromQuad(other?: DOMQuadInit): DOMQuad; + fromRect(other?: DOMRectInit): DOMQuad; +}; + +/** + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMRectInit { + height?: number; + width?: number; + x?: number; + y?: number; +} + +/** + * A **`DOMRect`** describes the size and position of a rectangle. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMRect) + * + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMRect extends DOMRectReadOnly { + /** + * The **`height`** property of the DOMRect interface represents the height of the rectangle. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRect/height) + */ + height: number; + /** + * The **`width`** property of the DOMRect interface represents the width of the rectangle. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRect/width) + */ + width: number; + /** + * The **`x`** property of the DOMRect interface represents the x-coordinate of the rectangle, which is the horizontal distance between the viewport's left edge and the rectangle's origin. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRect/x) + */ + x: number; + /** + * The **`y`** property of the DOMRect interface represents the y-coordinate of the rectangle, which is the vertical distance between the viewport's top edge and the rectangle's origin. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRect/y) + */ + y: number; +} + +/** + * A **`DOMRect`** describes the size and position of a rectangle. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMRect) + * + * @category Geometry Interfaces Module API + * @experimental + */ +declare var DOMRect: { + prototype: DOMRect; + new (x?: number, y?: number, width?: number, height?: number): DOMRect; + /** + * The **`fromRect()`** static method of the object with a given location and dimensions. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRect/fromRect_static) + */ + fromRect(other?: DOMRectInit): DOMRect; +}; + +/** + * The **`DOMRectReadOnly`** interface specifies the standard properties (also used by DOMRect) to define a rectangle whose properties are immutable. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly) + * + * @category Geometry Interfaces Module API + * @experimental + */ +interface DOMRectReadOnly { + /** + * The **`bottom`** read-only property of the **`DOMRectReadOnly`** interface returns the bottom coordinate value of the `DOMRect`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly/bottom) + */ + readonly bottom: number; + /** + * The **`height`** read-only property of the **`DOMRectReadOnly`** interface represents the height of the `DOMRect`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly/height) + */ + readonly height: number; + /** + * The **`left`** read-only property of the **`DOMRectReadOnly`** interface returns the left coordinate value of the `DOMRect`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly/left) + */ + readonly left: number; + /** + * The **`right`** read-only property of the **`DOMRectReadOnly`** interface returns the right coordinate value of the `DOMRect`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly/right) + */ + readonly right: number; + /** + * The **`top`** read-only property of the **`DOMRectReadOnly`** interface returns the top coordinate value of the `DOMRect`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly/top) + */ + readonly top: number; + /** + * The **`width`** read-only property of the **`DOMRectReadOnly`** interface represents the width of the `DOMRect`. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly/width) + */ + readonly width: number; + /** + * The **`x`** read-only property of the **`DOMRectReadOnly`** interface represents the x coordinate of the `DOMRect`'s origin. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly/x) + */ + readonly x: number; + /** + * The **`y`** read-only property of the **`DOMRectReadOnly`** interface represents the y coordinate of the `DOMRect`'s origin. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly/y) + */ + readonly y: number; + /** + * The DOMRectReadOnly method `toJSON()` returns a JSON representation of the `DOMRectReadOnly` object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly/toJSON) + */ + toJSON(): any; +} + +/** + * The **`DOMRectReadOnly`** interface specifies the standard properties (also used by DOMRect) to define a rectangle whose properties are immutable. + * + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly) + * + * @category Geometry Interfaces Module API + * @experimental + */ +declare var DOMRectReadOnly: { + prototype: DOMRectReadOnly; + new ( + x?: number, + y?: number, + width?: number, + height?: number, + ): DOMRectReadOnly; + /** + * The **`fromRect()`** static method of the object with a given location and dimensions. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly/fromRect_static) + */ + fromRect(other?: DOMRectInit): DOMRectReadOnly; +}; diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs index b3b23dfa770b0f..df03ed85db48b2 100644 --- a/cli/tsc/mod.rs +++ b/cli/tsc/mod.rs @@ -73,6 +73,7 @@ pub fn get_types_declaration_file_text() -> String { "deno.webstorage", "deno.canvas", "deno.crypto", + "deno.geometry", "deno.broadcast_channel", "deno.net", "deno.shared_globals", @@ -190,6 +191,7 @@ pub static LAZILY_LOADED_STATIC_ASSETS: Lazy< ), maybe_compressed_lib!("lib.deno.canvas.d.ts", "lib.deno_canvas.d.ts"), maybe_compressed_lib!("lib.deno.crypto.d.ts", "lib.deno_crypto.d.ts"), + maybe_compressed_lib!("lib.deno.geometry.d.ts", "lib.deno_geometry.d.ts"), maybe_compressed_lib!( "lib.deno.broadcast_channel.d.ts", "lib.deno_broadcast_channel.d.ts" diff --git a/ext/geometry/00_init.js b/ext/geometry/00_init.js new file mode 100644 index 00000000000000..ac3ea4e173c2df --- /dev/null +++ b/ext/geometry/00_init.js @@ -0,0 +1,7 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +import { core } from "ext:core/mod.js"; + +const loadGeometry = core.createLazyLoader("ext:deno_geometry/01_geometry.js"); + +export { loadGeometry }; diff --git a/ext/geometry/01_geometry.js b/ext/geometry/01_geometry.js new file mode 100644 index 00000000000000..3973cab045736f --- /dev/null +++ b/ext/geometry/01_geometry.js @@ -0,0 +1,218 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +import { primordials } from "ext:core/mod.js"; +import { + DOMMatrix, + DOMMatrixReadOnly, + DOMPoint, + DOMPointReadOnly, + DOMQuad, + DOMRect, + DOMRectReadOnly, + op_geometry_get_enable_window_features, + op_geometry_matrix_set_matrix_value, + op_geometry_matrix_to_buffer, + op_geometry_matrix_to_string, +} from "ext:core/ops"; +const { + Float32Array, + Float64Array, + ObjectDefineProperties, + ObjectDefineProperty, + ObjectPrototypeIsPrototypeOf, + SymbolFor, +} = primordials; + +import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; +import * as webidl from "ext:deno_webidl/00_webidl.js"; + +const DOMPointPrototype = DOMPoint.prototype; +const DOMPointReadOnlyPrototype = DOMPointReadOnly.prototype; +ObjectDefineProperty( + DOMPointReadOnlyPrototype, + SymbolFor("Deno.privateCustomInspect"), + { + __proto__: null, + value: function customInspect(inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf( + DOMPointReadOnlyPrototype, + this, + ), + keys: ["x", "y", "z", "w"], + }), + inspectOptions, + ); + }, + enumerable: false, + writable: true, + configurable: true, + }, +); +webidl.configureInterface(DOMPoint); +webidl.configureInterface(DOMPointReadOnly); + +const DOMRectPrototype = DOMRect.prototype; +const DOMRectReadOnlyPrototype = DOMRectReadOnly.prototype; +ObjectDefineProperty( + DOMRectReadOnlyPrototype, + SymbolFor("Deno.privateCustomInspect"), + { + __proto__: null, + value: function customInspect(inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf( + DOMRectReadOnlyPrototype, + this, + ), + keys: ["x", "y", "width", "height", "top", "right", "bottom", "left"], + }), + inspectOptions, + ); + }, + enumerable: false, + writable: true, + configurable: true, + }, +); +webidl.configureInterface(DOMRect); +webidl.configureInterface(DOMRectReadOnly); + +const DOMQuadPrototype = DOMQuad.prototype; +ObjectDefineProperty(DOMQuadPrototype, SymbolFor("Deno.privateCustomInspect"), { + __proto__: null, + value: function customInspect(inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf(DOMQuadPrototype, this), + keys: ["p1", "p2", "p3", "p4"], + }), + inspectOptions, + ); + }, + enumerable: false, + writable: true, + configurable: true, +}); +webidl.configureInterface(DOMQuad); + +const DOMMatrixPrototype = DOMMatrix.prototype; +const DOMMatrixReadOnlyPrototype = DOMMatrixReadOnly.prototype; +ObjectDefineProperties(DOMMatrixReadOnlyPrototype, { + toFloat32Array: { + __proto__: null, + value: function toFloat32Array() { + return new Float32Array( + new Float64Array(op_geometry_matrix_to_buffer(this)), + ); + }, + enumerable: false, + writable: true, + configurable: true, + }, + toFloat64Array: { + __proto__: null, + value: function toFloat64Array() { + return new Float64Array(op_geometry_matrix_to_buffer(this)); + }, + enumerable: false, + writable: true, + configurable: true, + }, + [SymbolFor("Deno.privateCustomInspect")]: { + __proto__: null, + value: function customInspect(inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf( + DOMMatrixReadOnlyPrototype, + this, + ), + keys: [ + "a", + "b", + "c", + "d", + "e", + "f", + "m11", + "m12", + "m13", + "m14", + "m21", + "m22", + "m23", + "m24", + "m31", + "m32", + "m33", + "m34", + "m41", + "m42", + "m43", + "m44", + "is2D", + "isIdentity", + ], + }), + inspectOptions, + ); + }, + enumerable: false, + writable: true, + configurable: true, + }, +}); + +if (op_geometry_get_enable_window_features()) { + // https://drafts.fxtf.org/geometry/#dommatrixreadonly-stringification-behavior + ObjectDefineProperty(DOMMatrixReadOnlyPrototype, "toString", { + __proto__: null, + value: function toString() { + return op_geometry_matrix_to_string(this); + }, + writable: true, + enumerable: true, + configurable: true, + }); + + // https://drafts.fxtf.org/geometry/#dom-dommatrix-setmatrixvalue + ObjectDefineProperty(DOMMatrixPrototype, "setMatrixValue", { + __proto__: null, + value: function setMatrixValue(transformList) { + const prefix = "Failed to execute 'setMatrixValue' on 'DOMMatrix'"; + webidl.requiredArguments(arguments.length, 1, prefix); + op_geometry_matrix_set_matrix_value(this, transformList); + return this; + }, + writable: true, + enumerable: true, + configurable: true, + }); +} + +webidl.configureInterface(DOMMatrix); +webidl.configureInterface(DOMMatrixReadOnly); + +export { + DOMMatrix, + DOMMatrixPrototype, + DOMMatrixReadOnly, + DOMMatrixReadOnlyPrototype, + DOMPoint, + DOMPointPrototype, + DOMPointReadOnly, + DOMPointReadOnlyPrototype, + DOMQuad, + DOMQuadPrototype, + DOMRect, + DOMRectPrototype, + DOMRectReadOnly, + DOMRectReadOnlyPrototype, +}; diff --git a/ext/geometry/Cargo.toml b/ext/geometry/Cargo.toml new file mode 100644 index 00000000000000..7f53629c460fe8 --- /dev/null +++ b/ext/geometry/Cargo.toml @@ -0,0 +1,21 @@ +# Copyright 2018-2025 the Deno authors. MIT license. + +[package] +name = "deno_geometry" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +readme = "README.md" +repository.workspace = true +description = "Geometry Interfaces Module API implementation for Deno" + +[lib] +path = "lib.rs" + +[dependencies] +deno_core.workspace = true +deno_error.workspace = true +lightningcss.workspace = true +nalgebra.workspace = true +thiserror.workspace = true diff --git a/ext/geometry/README.md b/ext/geometry/README.md new file mode 100644 index 00000000000000..1ef3341c9b42cb --- /dev/null +++ b/ext/geometry/README.md @@ -0,0 +1,76 @@ +# deno_geometry + +This crate implements the Geometry Interfaces Module API. + +Spec: https://drafts.fxtf.org/geometry/ + +## Usage Example + +From javascript, include the extension's source: + +```javascript +import { core } from "ext:core/mod.js"; +import { loadGeometry } from "ext:deno_geometry/00_init.js"; +``` + +Then define to globalThis: + +```javascript +Object.defineProperties(globalThis, { + DOMMatrix: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMMatrix, + loadGeometry, + ), + DOMMatrixReadOnly: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMMatrixReadOnly, + loadGeometry, + ), + DOMPoint: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMPoint, + loadGeometry, + ), + DOMPointReadOnly: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMPointReadOnly, + loadGeometry, + ), + DOMQuad: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMQuad, + loadGeometry, + ), + DOMRect: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMRect, + loadGeometry, + ), + DOMRectReadOnly: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMRectReadOnly, + loadGeometry, + ), +}); +``` + +Then from rust, provide: `deno_geometry::deno_geometry::init(bool)` in the +`extensions` field of your `RuntimeOptions` + +Where `bool` indicates whether window features are enabled at initialization. + +## Dependencies + +- **deno_webidl**: Provided by the `deno_webidl` crate +- **deno_web**: Provided by the `deno_web` crate +- **deno_console**: Provided by the `deno_console` crate + +## Provided ops + +Following ops are provided, which can be accessed through `Deno.ops`: + +- DOMPointReadOnly +- DOMPoint +- DOMRectReadOnly +- DOMRect +- DOMQuad +- DOMMatrixReadOnly +- DOMMatrix +- op_geometry_get_enable_window_features +- op_geometry_matrix_set_matrix_value +- op_geometry_matrix_to_buffer +- op_geometry_matrix_to_string diff --git a/ext/geometry/lib.rs b/ext/geometry/lib.rs new file mode 100644 index 00000000000000..7f34f6c67a40c9 --- /dev/null +++ b/ext/geometry/lib.rs @@ -0,0 +1,3046 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +#![allow(clippy::too_many_arguments)] + +use std::borrow::Cow; +use std::cell::Cell; +use std::cell::RefCell; +use std::mem; +use std::ptr; +use std::slice; + +use deno_core::GarbageCollected; +use deno_core::OpState; +use deno_core::WebIDL; +use deno_core::cppgc; +use deno_core::op2; +use deno_core::v8; +use deno_core::webidl; +use deno_core::webidl::ContextFn; +use deno_core::webidl::WebIdlConverter; +use deno_core::webidl::WebIdlError; +use lightningcss::properties::transform::Matrix as CSSMatrix; +use lightningcss::properties::transform::Matrix3d as CSSMatrix3d; +use lightningcss::properties::transform::Transform; +use lightningcss::properties::transform::TransformList; +use lightningcss::traits::Parse; +use lightningcss::values::length::LengthPercentage; +use lightningcss::values::number::CSSNumber; +use nalgebra::Matrix3; +use nalgebra::Matrix4; +use nalgebra::Matrix4x2; +use nalgebra::Matrix4x3; +use nalgebra::Rotation3; +use nalgebra::UnitVector3; +use nalgebra::Vector3; +use nalgebra::Vector4; + +deno_core::extension!( + deno_geometry, + deps = [deno_webidl, deno_web, deno_console], + ops = [ + op_geometry_get_enable_window_features, + op_geometry_matrix_set_matrix_value, + op_geometry_matrix_to_buffer, + op_geometry_matrix_to_string, + ], + objects = [ + DOMPointReadOnly, + DOMPoint, + DOMRectReadOnly, + DOMRect, + DOMQuad, + DOMMatrixReadOnly, + DOMMatrix, + ], + esm = ["00_init.js"], + lazy_loaded_esm = ["01_geometry.js"], + options = { + enable_window_features: bool, + }, + state = |state, options| { + state.put(State::new(options.enable_window_features)); + }, +); + +struct State { + enable_window_features: bool, +} + +impl State { + fn new(enable_window_features: bool) -> Self { + Self { + enable_window_features, + } + } +} + +#[op2(fast)] +fn op_geometry_get_enable_window_features(state: &mut OpState) -> bool { + let state = state.borrow_mut::(); + state.enable_window_features +} + +#[derive(Debug, thiserror::Error, deno_error::JsError)] +pub enum GeometryError { + #[class(type)] + #[error("Illegal invocation")] + IllegalInvocation, + #[class(inherit)] + #[error(transparent)] + WebIDL(#[from] WebIdlError), + #[class(type)] + #[error("Inconsistent 2d matrix value")] + Inconsistent2DMatrix, + #[class(type)] + #[error( + "The sequence must contain 6 elements for a 2D matrix or 16 elements for a 3D matrix" + )] + InvalidSequenceSize, + #[class(type)] + #[error("Mismatched types")] + TypeMismatch, + #[class("DOMExceptionInvalidStateError")] + #[error("Cannot be serialized with NaN or Infinity values")] + InvalidState, + #[class(type)] + #[error("Cannot parse a CSS value on Workers")] + DisallowWindowFeatures, + #[class("DOMExceptionSyntaxError")] + #[error("Failed to parse the string as CSS value")] + FailedToParse, + #[class("DOMExceptionSyntaxError")] + #[error("The CSS value contains relative values")] + ContainsRelativeValue, +} + +#[derive(WebIDL, Debug)] +#[webidl(dictionary)] +pub struct DOMPointInit { + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + x: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + y: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + z: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(1.0))] + w: webidl::UnrestrictedDouble, +} + +#[derive(Debug)] +pub struct DOMPointReadOnly { + inner: RefCell>, +} + +// SAFETY: we're sure `DOMPointReadOnly` can be GCed +unsafe impl GarbageCollected for DOMPointReadOnly { + fn trace(&self, _visitor: &mut deno_core::v8::cppgc::Visitor) {} + + fn get_name(&self) -> &'static std::ffi::CStr { + c"DOMPointReadOnly" + } +} + +impl DOMPointReadOnly { + #[inline] + fn from_point_inner(init: DOMPointInit) -> DOMPointReadOnly { + DOMPointReadOnly { + inner: RefCell::new(Vector4::new(*init.x, *init.y, *init.z, *init.w)), + } + } +} + +#[op2(base)] +impl DOMPointReadOnly { + #[constructor] + #[required(0)] + #[cppgc] + fn constructor( + #[webidl] x: Option, + #[webidl] y: Option, + #[webidl] z: Option, + #[webidl] w: Option, + ) -> DOMPointReadOnly { + DOMPointReadOnly { + inner: RefCell::new(Vector4::new( + *x.unwrap_or(webidl::UnrestrictedDouble(0.0)), + *y.unwrap_or(webidl::UnrestrictedDouble(0.0)), + *z.unwrap_or(webidl::UnrestrictedDouble(0.0)), + *w.unwrap_or(webidl::UnrestrictedDouble(1.0)), + )), + } + } + + #[reentrant] + #[required(0)] + #[static_method] + #[cppgc] + fn from_point(#[webidl] init: DOMPointInit) -> DOMPointReadOnly { + DOMPointReadOnly::from_point_inner(init) + } + + #[fast] + #[getter] + fn x(&self) -> f64 { + self.inner.borrow().x + } + + #[fast] + #[getter] + fn y(&self) -> f64 { + self.inner.borrow().y + } + + #[fast] + #[getter] + fn z(&self) -> f64 { + self.inner.borrow().z + } + + #[fast] + #[getter] + fn w(&self) -> f64 { + self.inner.borrow().w + } + + #[rename("toJSON")] + #[required(0)] + fn to_json<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + let mut obj = v8::Object::new(scope); + set_f64(scope, &mut obj, "x", self.inner.borrow().x); + set_f64(scope, &mut obj, "y", self.inner.borrow().y); + set_f64(scope, &mut obj, "z", self.inner.borrow().z); + set_f64(scope, &mut obj, "w", self.inner.borrow().w); + obj + } + + #[reentrant] + #[required(0)] + fn matrix_transform<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + #[webidl] value: DOMMatrixInit, + ) -> Result, GeometryError> { + let matrix = DOMMatrixReadOnly::from_matrix_inner(&value)?; + let ro = DOMPointReadOnly { + inner: RefCell::new(Vector4::zeros()), + }; + matrix_transform_point(&matrix, self, &ro); + let obj = cppgc::make_cppgc_empty_object::(scope); + Ok(cppgc::wrap_object2(scope, obj, (ro, DOMPoint {}))) + } +} + +pub struct DOMPoint {} + +// SAFETY: we're sure `DOMPoint` can be GCed +unsafe impl GarbageCollected for DOMPoint { + fn trace(&self, _visitor: &mut deno_core::v8::cppgc::Visitor) {} + + fn get_name(&self) -> &'static std::ffi::CStr { + c"DOMPoint" + } +} + +#[op2(inherit = DOMPointReadOnly)] +impl DOMPoint { + #[constructor] + #[required(0)] + #[cppgc] + fn constructor( + #[webidl] x: Option, + #[webidl] y: Option, + #[webidl] z: Option, + #[webidl] w: Option, + ) -> (DOMPointReadOnly, DOMPoint) { + let ro = DOMPointReadOnly { + inner: RefCell::new(Vector4::new( + *x.unwrap_or(webidl::UnrestrictedDouble(0.0)), + *y.unwrap_or(webidl::UnrestrictedDouble(0.0)), + *z.unwrap_or(webidl::UnrestrictedDouble(0.0)), + *w.unwrap_or(webidl::UnrestrictedDouble(1.0)), + )), + }; + (ro, DOMPoint {}) + } + + #[reentrant] + #[required(0)] + #[static_method] + fn from_point<'a>( + scope: &mut v8::PinScope<'a, '_>, + #[webidl] init: DOMPointInit, + ) -> v8::Local<'a, v8::Object> { + let ro = DOMPointReadOnly::from_point_inner(init); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (ro, DOMPoint {})) + } + + #[fast] + #[getter] + fn x(&self, #[proto] ro: &DOMPointReadOnly) -> f64 { + ro.inner.borrow().x + } + + #[setter] + fn x( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMPointReadOnly, + ) { + ro.inner.borrow_mut().x = *value + } + + #[fast] + #[getter] + fn y(&self, #[proto] ro: &DOMPointReadOnly) -> f64 { + ro.inner.borrow().y + } + + #[setter] + fn y( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMPointReadOnly, + ) { + ro.inner.borrow_mut().y = *value + } + + #[fast] + #[getter] + fn z(&self, #[proto] ro: &DOMPointReadOnly) -> f64 { + ro.inner.borrow().z + } + + #[setter] + fn z( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMPointReadOnly, + ) { + ro.inner.borrow_mut().z = *value + } + + #[fast] + #[getter] + fn w(&self, #[proto] ro: &DOMPointReadOnly) -> f64 { + ro.inner.borrow().w + } + + #[setter] + fn w( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMPointReadOnly, + ) { + ro.inner.borrow_mut().w = *value + } +} + +#[derive(WebIDL, Debug)] +#[webidl(dictionary)] +pub struct DOMRectInit { + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + x: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + y: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + width: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + height: webidl::UnrestrictedDouble, +} + +#[derive(Debug)] +pub struct DOMRectReadOnly { + x: Cell, + y: Cell, + width: Cell, + height: Cell, +} + +// SAFETY: we're sure `DOMRectReadOnly` can be GCed +unsafe impl GarbageCollected for DOMRectReadOnly { + fn trace(&self, _visitor: &mut deno_core::v8::cppgc::Visitor) {} + + fn get_name(&self) -> &'static std::ffi::CStr { + c"DOMRectReadOnly" + } +} + +impl DOMRectReadOnly { + #[inline] + fn from_rect_inner(init: DOMRectInit) -> DOMRectReadOnly { + DOMRectReadOnly { + x: Cell::new(*init.x), + y: Cell::new(*init.y), + width: Cell::new(*init.width), + height: Cell::new(*init.height), + } + } + + #[inline] + fn get_top(&self) -> f64 { + let y = self.y.get(); + let height = self.height.get(); + minimum(y, y + height) + } + + #[inline] + fn get_right(&self) -> f64 { + let x = self.x.get(); + let width = self.width.get(); + maximum(x, x + width) + } + + #[inline] + fn get_bottom(&self) -> f64 { + let y = self.y.get(); + let height = self.height.get(); + maximum(y, y + height) + } + + #[inline] + fn get_left(&self) -> f64 { + let x = self.x.get(); + let width = self.width.get(); + minimum(x, x + width) + } +} + +#[op2(base)] +impl DOMRectReadOnly { + #[constructor] + #[required(0)] + #[cppgc] + fn constructor( + #[webidl] x: Option, + #[webidl] y: Option, + #[webidl] width: Option, + #[webidl] height: Option, + ) -> DOMRectReadOnly { + DOMRectReadOnly { + x: Cell::new(*x.unwrap_or(webidl::UnrestrictedDouble(0.0))), + y: Cell::new(*y.unwrap_or(webidl::UnrestrictedDouble(0.0))), + width: Cell::new(*width.unwrap_or(webidl::UnrestrictedDouble(0.0))), + height: Cell::new(*height.unwrap_or(webidl::UnrestrictedDouble(0.0))), + } + } + + #[reentrant] + #[required(0)] + #[static_method] + #[cppgc] + fn from_rect(#[webidl] init: DOMRectInit) -> DOMRectReadOnly { + DOMRectReadOnly::from_rect_inner(init) + } + + #[fast] + #[getter] + fn x(&self) -> f64 { + self.x.get() + } + + #[fast] + #[getter] + fn y(&self) -> f64 { + self.y.get() + } + + #[fast] + #[getter] + fn width(&self) -> f64 { + self.width.get() + } + + #[fast] + #[getter] + fn height(&self) -> f64 { + self.height.get() + } + + #[fast] + #[getter] + fn top(&self) -> f64 { + self.get_top() + } + + #[fast] + #[getter] + fn right(&self) -> f64 { + self.get_right() + } + + #[fast] + #[getter] + fn bottom(&self) -> f64 { + self.get_bottom() + } + + #[fast] + #[getter] + fn left(&self) -> f64 { + self.get_left() + } + + #[rename("toJSON")] + #[required(0)] + fn to_json<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + let mut obj = v8::Object::new(scope); + set_f64(scope, &mut obj, "x", self.x.get()); + set_f64(scope, &mut obj, "y", self.y.get()); + set_f64(scope, &mut obj, "width", self.width.get()); + set_f64(scope, &mut obj, "height", self.height.get()); + set_f64(scope, &mut obj, "top", self.get_top()); + set_f64(scope, &mut obj, "right", self.get_right()); + set_f64(scope, &mut obj, "bottom", self.get_bottom()); + set_f64(scope, &mut obj, "left", self.get_left()); + obj + } +} + +pub struct DOMRect {} + +// SAFETY: we're sure `DOMRect` can be GCed +unsafe impl GarbageCollected for DOMRect { + fn trace(&self, _visitor: &mut deno_core::v8::cppgc::Visitor) {} + + fn get_name(&self) -> &'static std::ffi::CStr { + c"DOMRect" + } +} + +#[op2(inherit = DOMRectReadOnly)] +impl DOMRect { + #[constructor] + #[required(0)] + #[cppgc] + fn constructor( + #[webidl] x: Option, + #[webidl] y: Option, + #[webidl] width: Option, + #[webidl] height: Option, + ) -> (DOMRectReadOnly, DOMRect) { + let ro = DOMRectReadOnly { + x: Cell::new(*x.unwrap_or(webidl::UnrestrictedDouble(0.0))), + y: Cell::new(*y.unwrap_or(webidl::UnrestrictedDouble(0.0))), + width: Cell::new(*width.unwrap_or(webidl::UnrestrictedDouble(0.0))), + height: Cell::new(*height.unwrap_or(webidl::UnrestrictedDouble(0.0))), + }; + (ro, DOMRect {}) + } + + #[reentrant] + #[required(0)] + #[static_method] + fn from_rect<'a>( + scope: &mut v8::PinScope<'a, '_>, + #[webidl] init: DOMRectInit, + ) -> v8::Local<'a, v8::Object> { + let ro = DOMRectReadOnly::from_rect_inner(init); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (ro, DOMRect {})) + } + + #[fast] + #[getter] + fn x(&self, #[proto] ro: &DOMRectReadOnly) -> f64 { + ro.x.get() + } + + #[setter] + fn x( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMRectReadOnly, + ) { + ro.x.set(*value) + } + + #[fast] + #[getter] + fn y(&self, #[proto] ro: &DOMRectReadOnly) -> f64 { + ro.y.get() + } + + #[setter] + fn y( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMRectReadOnly, + ) { + ro.y.set(*value) + } + + #[fast] + #[getter] + fn width(&self, #[proto] ro: &DOMRectReadOnly) -> f64 { + ro.width.get() + } + + #[setter] + fn width( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMRectReadOnly, + ) { + ro.width.set(*value) + } + + #[fast] + #[getter] + fn height(&self, #[proto] ro: &DOMRectReadOnly) -> f64 { + ro.height.get() + } + + #[setter] + fn height( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMRectReadOnly, + ) { + ro.height.set(*value) + } +} + +#[derive(WebIDL, Debug)] +#[webidl(dictionary)] +pub struct DOMQuadInit { + p1: DOMPointInit, + p2: DOMPointInit, + p3: DOMPointInit, + p4: DOMPointInit, +} + +pub struct DOMQuad { + p1: v8::TracedReference, + p2: v8::TracedReference, + p3: v8::TracedReference, + p4: v8::TracedReference, +} + +// SAFETY: we're sure `DOMQuad` can be GCed +unsafe impl GarbageCollected for DOMQuad { + fn trace(&self, visitor: &mut deno_core::v8::cppgc::Visitor) { + visitor.trace(&self.p1); + visitor.trace(&self.p2); + visitor.trace(&self.p3); + visitor.trace(&self.p4); + } + + fn get_name(&self) -> &'static std::ffi::CStr { + c"DOMQuad" + } +} + +#[op2] +impl DOMQuad { + #[constructor] + #[reentrant] + #[required(0)] + #[cppgc] + fn constructor( + scope: &mut v8::PinScope<'_, '_>, + #[webidl] p1: DOMPointInit, + #[webidl] p2: DOMPointInit, + #[webidl] p3: DOMPointInit, + #[webidl] p4: DOMPointInit, + ) -> DOMQuad { + #[inline] + fn from_point( + scope: &mut v8::PinScope<'_, '_>, + point: DOMPointInit, + ) -> v8::TracedReference { + let ro = DOMPointReadOnly { + inner: RefCell::new(Vector4::new( + *point.x, *point.y, *point.z, *point.w, + )), + }; + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (ro, DOMPoint {})); + v8::TracedReference::new(scope, obj) + } + + DOMQuad { + p1: from_point(scope, p1), + p2: from_point(scope, p2), + p3: from_point(scope, p3), + p4: from_point(scope, p4), + } + } + + #[reentrant] + #[required(0)] + #[static_method] + #[cppgc] + fn from_rect( + scope: &mut v8::PinScope<'_, '_>, + #[webidl] rect: DOMRectInit, + ) -> DOMQuad { + #[inline] + fn create_point( + scope: &mut v8::PinScope<'_, '_>, + x: f64, + y: f64, + z: f64, + w: f64, + ) -> v8::TracedReference { + let ro = DOMPointReadOnly { + inner: RefCell::new(Vector4::new(x, y, z, w)), + }; + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (ro, DOMPoint {})); + v8::TracedReference::new(scope, obj) + } + + let DOMRectInit { + x, + y, + width, + height, + } = rect; + DOMQuad { + p1: create_point(scope, *x, *y, 0.0, 1.0), + p2: create_point(scope, *x + *width, *y, 0.0, 1.0), + p3: create_point(scope, *x + *width, *y + *height, 0.0, 1.0), + p4: create_point(scope, *x, *y + *height, 0.0, 1.0), + } + } + + #[reentrant] + #[required(0)] + #[static_method] + #[cppgc] + fn from_quad( + scope: &mut v8::PinScope<'_, '_>, + #[webidl] quad: DOMQuadInit, + ) -> DOMQuad { + #[inline] + fn from_point( + scope: &mut v8::PinScope<'_, '_>, + point: DOMPointInit, + ) -> v8::TracedReference { + let ro = DOMPointReadOnly { + inner: RefCell::new(Vector4::new( + *point.x, *point.y, *point.z, *point.w, + )), + }; + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (ro, DOMPoint {})); + v8::TracedReference::new(scope, obj) + } + + DOMQuad { + p1: from_point(scope, quad.p1), + p2: from_point(scope, quad.p2), + p3: from_point(scope, quad.p3), + p4: from_point(scope, quad.p4), + } + } + + #[getter] + fn p1<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + self.p1.get(scope).unwrap() + } + + #[getter] + fn p2<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + self.p2.get(scope).unwrap() + } + + #[getter] + fn p3<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + self.p3.get(scope).unwrap() + } + + #[getter] + fn p4<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + self.p4.get(scope).unwrap() + } + + #[required(0)] + fn get_bounds<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + #[inline] + fn get_ptr( + scope: &mut v8::PinScope<'_, '_>, + value: &v8::TracedReference, + ) -> cppgc::UnsafePtr { + let value = value.get(scope).unwrap(); + cppgc::try_unwrap_cppgc_proto_object::( + scope, + value.into(), + ) + .unwrap() + } + + let p1 = get_ptr(scope, &self.p1); + let p2 = get_ptr(scope, &self.p2); + let p3 = get_ptr(scope, &self.p3); + let p4 = get_ptr(scope, &self.p4); + let p1 = *p1.inner.borrow(); + let p2 = *p2.inner.borrow(); + let p3 = *p3.inner.borrow(); + let p4 = *p4.inner.borrow(); + let left = minimum(minimum(p1.x, p2.x), minimum(p3.x, p4.x)); + let top = minimum(minimum(p1.y, p2.y), minimum(p3.y, p4.y)); + let right = maximum(maximum(p1.x, p2.x), maximum(p3.x, p4.x)); + let bottom = maximum(maximum(p1.y, p2.y), maximum(p3.y, p4.y)); + let ro = DOMRectReadOnly { + x: Cell::new(left), + y: Cell::new(top), + width: Cell::new(right - left), + height: Cell::new(bottom - top), + }; + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (ro, DOMRect {})) + } + + #[rename("toJSON")] + #[required(0)] + fn to_json<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + #[inline] + fn set_object( + scope: &mut v8::PinScope<'_, '_>, + object: &mut v8::Local, + key: &str, + value: &v8::TracedReference, + ) { + let key = v8::String::new(scope, key).unwrap(); + let value = value.get(scope).unwrap(); + object.create_data_property(scope, key.into(), value.into()); + } + + let mut obj = v8::Object::new(scope); + set_object(scope, &mut obj, "p1", &self.p1); + set_object(scope, &mut obj, "p2", &self.p2); + set_object(scope, &mut obj, "p3", &self.p3); + set_object(scope, &mut obj, "p4", &self.p4); + obj + } +} + +#[derive(WebIDL, Debug)] +#[webidl(dictionary)] +pub struct DOMMatrixInit { + // Need to place the inherited DOMMatrixInit2D first + #[webidl(default = None)] + a: Option, + #[webidl(default = None)] + b: Option, + #[webidl(default = None)] + c: Option, + #[webidl(default = None)] + d: Option, + #[webidl(default = None)] + e: Option, + #[webidl(default = None)] + f: Option, + #[webidl(default = None)] + m11: Option, + #[webidl(default = None)] + m12: Option, + #[webidl(default = None)] + m21: Option, + #[webidl(default = None)] + m22: Option, + #[webidl(default = None)] + m41: Option, + #[webidl(default = None)] + m42: Option, + + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + m13: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + m14: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + m23: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + m24: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + m31: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + m32: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(1.0))] + m33: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + m34: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(0.0))] + m43: webidl::UnrestrictedDouble, + #[webidl(default = webidl::UnrestrictedDouble(1.0))] + m44: webidl::UnrestrictedDouble, + #[webidl(default = None)] + is_2d: Option, +} + +#[derive(Debug, Clone)] +pub struct DOMMatrixReadOnly { + inner: RefCell>, + is_2d: Cell, +} + +// SAFETY: we're sure `DOMMatrixReadOnly` can be GCed +unsafe impl GarbageCollected for DOMMatrixReadOnly { + fn trace(&self, _visitor: &mut deno_core::v8::cppgc::Visitor) {} + + fn get_name(&self) -> &'static std::ffi::CStr { + c"DOMMatrixReadOnly" + } +} + +/* + * NOTE: column-major order + * + * For a 2D 3x2 matrix, the index of properties in + * | a c 0 e | | 0 4 _ 12 | + * | b d 0 f | | 1 5 _ 13 | + * | 0 0 1 0 | is | _ _ _ _ | + * | 0 0 0 1 | | _ _ _ _ | + */ +const INDEX_A: usize = 0; +const INDEX_B: usize = 1; +const INDEX_C: usize = 4; +const INDEX_D: usize = 5; +const INDEX_E: usize = 12; +const INDEX_F: usize = 13; + +/* + * NOTE: column-major order + * + * The index of properties in + * | m11 m21 m31 m41 | | 0 4 8 12 | + * | m12 m22 m32 m42 | | 1 5 9 13 | + * | m13 m23 m33 m43 | is | 2 6 10 14 | + * | m14 m24 m34 m44 | | 3 7 11 15 | + */ +const INDEX_M11: usize = 0; +const INDEX_M12: usize = 1; +const INDEX_M13: usize = 2; +const INDEX_M14: usize = 3; +const INDEX_M21: usize = 4; +const INDEX_M22: usize = 5; +const INDEX_M23: usize = 6; +const INDEX_M24: usize = 7; +const INDEX_M31: usize = 8; +const INDEX_M32: usize = 9; +const INDEX_M33: usize = 10; +const INDEX_M34: usize = 11; +const INDEX_M41: usize = 12; +const INDEX_M42: usize = 13; +const INDEX_M43: usize = 14; +const INDEX_M44: usize = 15; + +impl DOMMatrixReadOnly { + fn new<'a>( + state: &mut OpState, + scope: &mut v8::PinScope<'a, '_>, + value: v8::Local<'a, v8::Value>, + prefix: Cow<'static, str>, + context: ContextFn<'_>, + ) -> Result { + // omitted (undefined) + if value.is_undefined() { + return Ok(DOMMatrixReadOnly::identity()); + } + + // sequence + if value.is_object() + && let Ok(seq) = Vec::::convert( + scope, + value, + prefix, + context, + &Default::default(), + ) + { + let seq = seq.into_iter().map(|f| *f).collect::>(); + return DOMMatrixReadOnly::from_sequence_inner(&seq); + } + + // DOMString + if let Some(value) = value.to_string(scope) { + let state = state.borrow_mut::(); + if !state.enable_window_features { + return Err(GeometryError::DisallowWindowFeatures); + } + + let matrix = DOMMatrixReadOnly::identity(); + let string = value.to_rust_string_lossy(scope); + if !string.is_empty() { + let Ok(transform_list) = TransformList::parse_string(&string) else { + return Err(GeometryError::FailedToParse); + }; + matrix.set_matrix_value_inner(&transform_list)?; + } + return Ok(matrix); + } + + Ok(DOMMatrixReadOnly::identity()) + } + + fn from_matrix_inner( + init: &DOMMatrixInit, + ) -> Result { + macro_rules! fixup { + ($value3d:expr, $value2d:expr, $default:expr) => {{ + if let Some(value3d) = $value3d { + if let Some(value2d) = $value2d { + if !(*value3d == *value2d || value3d.is_nan() && value2d.is_nan()) { + return Err(GeometryError::Inconsistent2DMatrix); + } + } + value3d + } else if let Some(value2d) = $value2d { + value2d + } else { + webidl::UnrestrictedDouble($default) + } + }}; + } + + let m11 = fixup!(init.m11, init.a, 1.0); + let m12 = fixup!(init.m12, init.b, 0.0); + let m21 = fixup!(init.m21, init.c, 0.0); + let m22 = fixup!(init.m22, init.d, 1.0); + let m41 = fixup!(init.m41, init.e, 0.0); + let m42 = fixup!(init.m42, init.f, 0.0); + let is_2d = { + let is_2d_can_be_true = *init.m13 == 0.0 + && *init.m14 == 0.0 + && *init.m23 == 0.0 + && *init.m24 == 0.0 + && *init.m31 == 0.0 + && *init.m32 == 0.0 + && *init.m33 == 1.0 + && *init.m34 == 0.0 + && *init.m43 == 0.0 + && *init.m44 == 1.0; + if let Some(is_2d) = init.is_2d { + if is_2d && !is_2d_can_be_true { + return Err(GeometryError::Inconsistent2DMatrix); + } else { + is_2d + } + } else { + is_2d_can_be_true + } + }; + + if is_2d { + Ok(DOMMatrixReadOnly { + #[rustfmt::skip] + inner: RefCell::new(Matrix4::new( + *m11, *m21, 0.0, *m41, + *m12, *m22, 0.0, *m42, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + )), + is_2d: Cell::new(true), + }) + } else { + let DOMMatrixInit { + m13, + m14, + m23, + m24, + m31, + m32, + m33, + m34, + m43, + m44, + .. + } = init; + Ok(DOMMatrixReadOnly { + #[rustfmt::skip] + inner: RefCell::new(Matrix4::new( + *m11, *m21, **m31, *m41, + *m12, *m22, **m32, *m42, + **m13, **m23, **m33, **m43, + **m14, **m24, **m34, **m44, + )), + is_2d: Cell::new(false), + }) + } + } + + fn from_sequence_inner( + seq: &[f64], + ) -> Result { + if let [a, b, c, d, e, f] = seq { + Ok(DOMMatrixReadOnly { + #[rustfmt::skip] + inner: RefCell::new(Matrix4::new( + *a, *c, 0.0, *e, + *b, *d, 0.0, *f, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + )), + is_2d: Cell::new(true), + }) + } else if seq.len() == 16 { + Ok(DOMMatrixReadOnly { + inner: RefCell::new(Matrix4::from_column_slice(seq)), + is_2d: Cell::new(false), + }) + } else { + Err(GeometryError::InvalidSequenceSize) + } + } + + #[inline] + fn identity() -> DOMMatrixReadOnly { + DOMMatrixReadOnly { + inner: RefCell::new(Matrix4::identity()), + is_2d: Cell::new(true), + } + } + + #[inline] + fn translate_self_inner(&self, tx: f64, ty: f64, tz: f64) { + let mut inner = self.inner.borrow_mut(); + let is_2d = self.is_2d.get(); + let shift = Vector3::new(tx, ty, tz); + inner.prepend_translation_mut(&shift); + self.is_2d.set(is_2d && tz == 0.0); + } + + #[inline] + fn scale_without_origin_self_inner(&self, sx: f64, sy: f64, sz: f64) { + let mut inner = self.inner.borrow_mut(); + let is_2d = self.is_2d.get(); + let scaling = Vector3::new(sx, sy, sz); + inner.prepend_nonuniform_scaling_mut(&scaling); + self.is_2d.set(is_2d && sz == 1.0); + } + + #[inline] + fn scale_with_origin_self_inner( + &self, + sx: f64, + sy: f64, + sz: f64, + origin_x: f64, + origin_y: f64, + origin_z: f64, + ) { + let mut inner = self.inner.borrow_mut(); + let is_2d = self.is_2d.get(); + let scaling = Vector3::new(sx, sy, sz); + let mut shift = Vector3::new(origin_x, origin_y, origin_z); + inner.prepend_translation_mut(&shift); + inner.prepend_nonuniform_scaling_mut(&scaling); + shift.neg_mut(); + inner.prepend_translation_mut(&shift); + self.is_2d.set(is_2d && sz == 1.0 && origin_z == 0.0); + } + + #[inline] + fn rotate_self_inner(&self, roll: f64, pitch: f64, yaw: f64) { + let mut inner = self.inner.borrow_mut(); + let is_2d = self.is_2d.get(); + let rotation = + Rotation3::from_euler_angles(roll, pitch, yaw).to_homogeneous(); + let mut result = Matrix4x3::zeros(); + inner.mul_to(&rotation.fixed_view::<4, 3>(0, 0), &mut result); + inner.set_column(0, &result.column(0)); + inner.set_column(1, &result.column(1)); + inner.set_column(2, &result.column(2)); + self.is_2d.set(is_2d && roll == 0.0 && pitch == 0.0); + } + + #[inline] + fn rotate_from_vector_self_inner(&self, x: f64, y: f64) { + if x == 0.0 && y == 0.0 { + return; + } + let mut inner = self.inner.borrow_mut(); + let rotation = Rotation3::from_axis_angle(&Vector3::z_axis(), y.atan2(x)) + .to_homogeneous(); + let mut result = Matrix4x3::zeros(); + inner.mul_to(&rotation.fixed_view::<4, 3>(0, 0), &mut result); + inner.set_column(0, &result.column(0)); + inner.set_column(1, &result.column(1)); + inner.set_column(2, &result.column(2)); + } + + #[inline] + fn rotate_axis_angle_self_inner(&self, x: f64, y: f64, z: f64, angle: f64) { + if x == 0.0 && y == 0.0 && z == 0.0 { + return; + } + let mut inner = self.inner.borrow_mut(); + let is_2d = self.is_2d.get(); + let rotation = Rotation3::from_axis_angle( + &UnitVector3::new_normalize(Vector3::new(x, y, z)), + angle, + ) + .to_homogeneous(); + let mut result = Matrix4x3::zeros(); + inner.mul_to(&rotation.fixed_view::<4, 3>(0, 0), &mut result); + inner.set_column(0, &result.column(0)); + inner.set_column(1, &result.column(1)); + inner.set_column(2, &result.column(2)); + self.is_2d.set(is_2d && x == 0.0 && y == 0.0); + } + + #[inline] + fn skew_self_inner(&self, x: f64, y: f64) { + let mut inner = self.inner.borrow_mut(); + let skew = Matrix4x2::new(1.0, x.tan(), y.tan(), 1.0, 0.0, 0.0, 0.0, 0.0); + let mut result = Matrix4x2::zeros(); + inner.mul_to(&skew, &mut result); + inner.set_column(0, &result.column(0)); + inner.set_column(1, &result.column(1)); + } + + #[inline] + fn perspective_self_inner(&self, d: f64) { + if d == 0.0 { + return; + } + let mut inner = self.inner.borrow_mut(); + let perspective = + Matrix4x2::new(0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0 / d, 1.0); + let mut result = Matrix4x2::zeros(); + inner.mul_to(&perspective, &mut result); + inner.set_column(2, &result.column(0)); + inner.set_column(3, &result.column(1)); + self.is_2d.set(false); + } + + #[inline] + fn multiply_self_inner( + &self, + lhs: &DOMMatrixReadOnly, + rhs: &DOMMatrixReadOnly, + ) { + let lhs_inner = lhs.inner.borrow(); + let lhs_is_2d = lhs.is_2d.get(); + let rhs_inner = rhs.inner.borrow(); + let rhs_is_2d = rhs.is_2d.get(); + let mut out_inner = self.inner.borrow_mut(); + lhs_inner.mul_to(&rhs_inner, &mut out_inner); + self.is_2d.set(lhs_is_2d && rhs_is_2d); + } + + #[inline] + fn flip_x_inner(&self) { + let mut inner = self.inner.borrow_mut(); + inner.column_mut(0).neg_mut(); + } + + #[inline] + fn flip_y_inner(&self) { + let mut inner = self.inner.borrow_mut(); + inner.column_mut(1).neg_mut(); + } + + #[inline] + fn invert_self_inner(&self) { + let mut inner = self.inner.borrow_mut(); + let is_2d = self.is_2d.get(); + if inner.iter().any(|&x| x.is_infinite()) { + inner.fill(f64::NAN); + self.is_2d.set(false); + return; + } + if is_2d { + let mut matrix3 = Matrix3::new( + inner[INDEX_A], + inner[INDEX_C], + inner[INDEX_E], + inner[INDEX_B], + inner[INDEX_D], + inner[INDEX_F], + 0.0, + 0.0, + 1.0, + ); + if !matrix3.try_inverse_mut() { + inner.fill(f64::NAN); + self.is_2d.set(false); + return; + } + inner[INDEX_A] = matrix3[0]; + inner[INDEX_B] = matrix3[1]; + inner[INDEX_C] = matrix3[3]; + inner[INDEX_D] = matrix3[4]; + inner[INDEX_E] = matrix3[6]; + inner[INDEX_F] = matrix3[7]; + } else if !inner.try_inverse_mut() { + inner.fill(f64::NAN); + } + } + + #[inline] + fn a_inner(&self) -> f64 { + self.inner.borrow()[INDEX_A] + } + + #[inline] + fn b_inner(&self) -> f64 { + self.inner.borrow()[INDEX_B] + } + + #[inline] + fn c_inner(&self) -> f64 { + self.inner.borrow()[INDEX_C] + } + + #[inline] + fn d_inner(&self) -> f64 { + self.inner.borrow()[INDEX_D] + } + + #[inline] + fn e_inner(&self) -> f64 { + self.inner.borrow()[INDEX_E] + } + + #[inline] + fn f_inner(&self) -> f64 { + self.inner.borrow()[INDEX_F] + } + + #[inline] + fn m11_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M11] + } + + #[inline] + fn m12_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M12] + } + + #[inline] + fn m13_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M13] + } + + #[inline] + fn m14_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M14] + } + + #[inline] + fn m21_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M21] + } + + #[inline] + fn m22_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M22] + } + + #[inline] + fn m23_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M23] + } + + #[inline] + fn m24_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M24] + } + + #[inline] + fn m31_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M31] + } + + #[inline] + fn m32_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M32] + } + + #[inline] + fn m33_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M33] + } + + #[inline] + fn m34_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M34] + } + + #[inline] + fn m41_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M41] + } + + #[inline] + fn m42_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M42] + } + + #[inline] + fn m43_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M43] + } + + #[inline] + fn m44_inner(&self) -> f64 { + self.inner.borrow()[INDEX_M44] + } + + #[inline] + fn is_identity_inner(&self) -> bool { + let inner = self.inner.borrow(); + inner[INDEX_M11] == 1.0 + && inner[INDEX_M12] == 0.0 + && inner[INDEX_M13] == 0.0 + && inner[INDEX_M14] == 0.0 + && inner[INDEX_M21] == 0.0 + && inner[INDEX_M22] == 1.0 + && inner[INDEX_M23] == 0.0 + && inner[INDEX_M24] == 0.0 + && inner[INDEX_M31] == 0.0 + && inner[INDEX_M32] == 0.0 + && inner[INDEX_M33] == 1.0 + && inner[INDEX_M34] == 0.0 + && inner[INDEX_M41] == 0.0 + && inner[INDEX_M42] == 0.0 + && inner[INDEX_M43] == 0.0 + && inner[INDEX_M44] == 1.0 + } + + #[inline] + fn is_finite_inner(&self) -> bool { + self + .inner + .borrow() + .into_iter() + .all(|&item| item.is_finite()) + } + + fn set_matrix_value_inner( + &self, + transform_list: &TransformList, + ) -> Result<(), GeometryError> { + for transform in transform_list.0.iter() { + match transform { + Transform::Translate( + LengthPercentage::Dimension(x), + LengthPercentage::Dimension(y), + ) => { + if let (Some(x), Some(y)) = (x.to_px(), y.to_px()) { + self.translate_self_inner(x.into(), y.into(), 0.0); + } else { + return Err(GeometryError::ContainsRelativeValue); + } + } + Transform::TranslateX(LengthPercentage::Dimension(x)) => { + if let Some(x) = x.to_px() { + self.translate_self_inner(x.into(), 0.0, 0.0); + } else { + return Err(GeometryError::ContainsRelativeValue); + } + } + Transform::TranslateY(LengthPercentage::Dimension(y)) => { + if let Some(y) = y.to_px() { + self.translate_self_inner(0.0, y.into(), 0.0); + } else { + return Err(GeometryError::ContainsRelativeValue); + } + } + Transform::TranslateZ(z) => { + if let Some(z) = z.to_px() { + self.translate_self_inner(0.0, 0.0, z.into()); + self.is_2d.set(false); + } else { + return Err(GeometryError::ContainsRelativeValue); + } + } + Transform::Translate3d( + LengthPercentage::Dimension(x), + LengthPercentage::Dimension(y), + z, + ) => { + if let (Some(x), Some(y), Some(z)) = (x.to_px(), y.to_px(), z.to_px()) + { + self.translate_self_inner(x.into(), y.into(), z.into()); + self.is_2d.set(false); + } else { + return Err(GeometryError::ContainsRelativeValue); + } + } + Transform::Scale(x, y) => { + let x: CSSNumber = x.into(); + let y: CSSNumber = y.into(); + self.scale_without_origin_self_inner(x.into(), y.into(), 1.0); + } + Transform::ScaleX(x) => { + let x: CSSNumber = x.into(); + self.scale_without_origin_self_inner(x.into(), 1.0, 1.0); + } + Transform::ScaleY(y) => { + let y: CSSNumber = y.into(); + self.scale_without_origin_self_inner(1.0, y.into(), 1.0); + } + Transform::ScaleZ(z) => { + let z: CSSNumber = z.into(); + self.scale_without_origin_self_inner(1.0, 1.0, z.into()); + self.is_2d.set(false); + } + Transform::Scale3d(x, y, z) => { + let x: CSSNumber = x.into(); + let y: CSSNumber = y.into(); + let z: CSSNumber = z.into(); + self.scale_without_origin_self_inner(x.into(), y.into(), z.into()); + self.is_2d.set(false); + } + Transform::Rotate(angle) => { + self.rotate_axis_angle_self_inner( + 0.0, + 0.0, + 1.0, + angle.to_radians().into(), + ); + } + Transform::RotateX(angle) => { + self.rotate_axis_angle_self_inner( + 1.0, + 0.0, + 0.0, + angle.to_radians().into(), + ); + self.is_2d.set(false); + } + Transform::RotateY(angle) => { + self.rotate_axis_angle_self_inner( + 0.0, + 1.0, + 0.0, + angle.to_radians().into(), + ); + self.is_2d.set(false); + } + Transform::RotateZ(angle) => { + self.rotate_axis_angle_self_inner( + 0.0, + 0.0, + 1.0, + angle.to_radians().into(), + ); + self.is_2d.set(false); + } + Transform::Rotate3d(x, y, z, angle) => { + self.rotate_axis_angle_self_inner( + (*x).into(), + (*y).into(), + (*z).into(), + angle.to_radians().into(), + ); + self.is_2d.set(false); + } + Transform::Skew(x, y) => { + self.skew_self_inner(x.to_radians().into(), y.to_radians().into()); + } + Transform::SkewX(angle) => { + self.skew_self_inner(angle.to_radians().into(), 0.0); + } + Transform::SkewY(angle) => { + self.skew_self_inner(0.0, angle.to_radians().into()); + } + Transform::Perspective(length) => { + if let Some(length) = length.to_px() { + self.perspective_self_inner(length.into()); + self.is_2d.set(false); + } else { + return Err(GeometryError::ContainsRelativeValue); + } + } + Transform::Matrix(CSSMatrix { a, b, c, d, e, f }) => { + let lhs = self.clone(); + let rhs = DOMMatrixReadOnly { + #[rustfmt::skip] + inner: RefCell::new(Matrix4::new( + (*a).into(), (*c).into(), 0.0, (*e).into(), + (*b).into(), (*d).into(), 0.0, (*f).into(), + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + )), + is_2d: Cell::new(true), + }; + self.multiply_self_inner(&lhs, &rhs); + } + Transform::Matrix3d(CSSMatrix3d { + m11, + m12, + m13, + m14, + m21, + m22, + m23, + m24, + m31, + m32, + m33, + m34, + m41, + m42, + m43, + m44, + }) => { + let lhs = self.clone(); + let rhs = DOMMatrixReadOnly { + #[rustfmt::skip] + inner: RefCell::new(Matrix4::new( + (*m11).into(), (*m21).into(), (*m31).into(), (*m41).into(), + (*m12).into(), (*m22).into(), (*m32).into(), (*m42).into(), + (*m13).into(), (*m23).into(), (*m33).into(), (*m43).into(), + (*m14).into(), (*m24).into(), (*m34).into(), (*m44).into(), + )), + is_2d: Cell::new(false), + }; + self.multiply_self_inner(&lhs, &rhs); + } + _ => { + return Err(GeometryError::ContainsRelativeValue); + } + } + } + Ok(()) + } +} + +#[op2(base)] +impl DOMMatrixReadOnly { + #[constructor] + #[reentrant] + #[required(0)] + #[cppgc] + fn constructor<'a>( + state: &mut OpState, + scope: &mut v8::PinScope<'a, '_>, + value: v8::Local<'a, v8::Value>, + ) -> Result { + DOMMatrixReadOnly::new( + state, + scope, + value, + "Failed to construct 'DOMMatrixReadOnly'".into(), + ContextFn::new_borrowed(&|| Cow::Borrowed("Argument 1")), + ) + } + + #[reentrant] + #[required(0)] + #[static_method] + #[cppgc] + fn from_matrix( + #[webidl] init: DOMMatrixInit, + ) -> Result { + DOMMatrixReadOnly::from_matrix_inner(&init) + } + + #[rename("fromFloat32Array")] + #[required(1)] + #[static_method] + #[cppgc] + fn from_float32_array<'a>( + scope: &mut v8::PinScope<'a, '_>, + value: v8::Local<'a, v8::Value>, + ) -> Result { + if !value.is_float32_array() { + return Err(GeometryError::TypeMismatch); + } + let seq = Vec::::convert( + scope, + value, + "Failed to execute 'DOMMatrixReadOnly.fromFloat32Array'".into(), + (|| Cow::Borrowed("Argument 1")).into(), + &Default::default(), + )?; + let seq = seq.into_iter().map(|f| *f).collect::>(); + DOMMatrixReadOnly::from_sequence_inner(&seq) + } + + #[rename("fromFloat64Array")] + #[required(1)] + #[static_method] + #[cppgc] + fn from_float64_array<'a>( + scope: &mut v8::PinScope<'a, '_>, + value: v8::Local<'a, v8::Value>, + ) -> Result { + if !value.is_float64_array() { + return Err(GeometryError::TypeMismatch); + } + let seq = Vec::::convert( + scope, + value, + "Failed to execute 'DOMMatrixReadOnly.fromFloat64Array'".into(), + (|| Cow::Borrowed("Argument 1")).into(), + &Default::default(), + )?; + let seq = seq.into_iter().map(|f| *f).collect::>(); + DOMMatrixReadOnly::from_sequence_inner(&seq) + } + + #[fast] + #[getter] + fn a(&self) -> f64 { + self.a_inner() + } + + #[fast] + #[getter] + fn b(&self) -> f64 { + self.b_inner() + } + + #[fast] + #[getter] + fn c(&self) -> f64 { + self.c_inner() + } + + #[fast] + #[getter] + fn d(&self) -> f64 { + self.d_inner() + } + + #[fast] + #[getter] + fn e(&self) -> f64 { + self.e_inner() + } + + #[fast] + #[getter] + fn f(&self) -> f64 { + self.f_inner() + } + + #[fast] + #[getter] + fn m11(&self) -> f64 { + self.m11_inner() + } + + #[fast] + #[getter] + fn m12(&self) -> f64 { + self.m12_inner() + } + + #[fast] + #[getter] + fn m13(&self) -> f64 { + self.m13_inner() + } + + #[fast] + #[getter] + fn m14(&self) -> f64 { + self.m14_inner() + } + + #[fast] + #[getter] + fn m21(&self) -> f64 { + self.m21_inner() + } + + #[fast] + #[getter] + fn m22(&self) -> f64 { + self.m22_inner() + } + + #[fast] + #[getter] + fn m23(&self) -> f64 { + self.m23_inner() + } + + #[fast] + #[getter] + fn m24(&self) -> f64 { + self.m24_inner() + } + + #[fast] + #[getter] + fn m31(&self) -> f64 { + self.m31_inner() + } + + #[fast] + #[getter] + fn m32(&self) -> f64 { + self.m32_inner() + } + + #[fast] + #[getter] + fn m33(&self) -> f64 { + self.m33_inner() + } + + #[fast] + #[getter] + fn m34(&self) -> f64 { + self.m34_inner() + } + + #[fast] + #[getter] + fn m41(&self) -> f64 { + self.m41_inner() + } + + #[fast] + #[getter] + fn m42(&self) -> f64 { + self.m42_inner() + } + + #[fast] + #[getter] + fn m43(&self) -> f64 { + self.m43_inner() + } + + #[fast] + #[getter] + fn m44(&self) -> f64 { + self.m44_inner() + } + + #[fast] + #[getter] + fn is_2d(&self) -> bool { + self.is_2d.get() + } + + #[fast] + #[getter] + fn is_identity(&self) -> bool { + self.is_identity_inner() + } + + #[required(0)] + fn translate<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + #[webidl] tx: Option, + #[webidl] ty: Option, + #[webidl] tz: Option, + ) -> v8::Local<'a, v8::Object> { + let tx = *tx.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let ty = *ty.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let tz = *tz.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let out = self.clone(); + out.translate_self_inner(tx, ty, tz); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[required(0)] + fn scale<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + #[webidl] sx: Option, + #[webidl] sy: Option, + #[webidl] sz: Option, + #[webidl] origin_x: Option, + #[webidl] origin_y: Option, + #[webidl] origin_z: Option, + ) -> v8::Local<'a, v8::Object> { + let sx = *sx.unwrap_or(webidl::UnrestrictedDouble(1.0)); + let sy = *sy.unwrap_or(webidl::UnrestrictedDouble(sx)); + let sz = *sz.unwrap_or(webidl::UnrestrictedDouble(1.0)); + let origin_x = *origin_x.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let origin_y = *origin_y.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let origin_z = *origin_z.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let out = self.clone(); + if origin_x == 0.0 && origin_y == 0.0 && origin_z == 0.0 { + out.scale_without_origin_self_inner(sx, sy, sz); + } else { + out + .scale_with_origin_self_inner(sx, sy, sz, origin_x, origin_y, origin_z); + } + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[required(0)] + fn scale_non_uniform<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + #[webidl] sx: Option, + #[webidl] sy: Option, + ) -> v8::Local<'a, v8::Object> { + let sx = *sx.unwrap_or(webidl::UnrestrictedDouble(1.0)); + let sy = *sy.unwrap_or(webidl::UnrestrictedDouble(1.0)); + let out = self.clone(); + out.scale_without_origin_self_inner(sx, sy, 1.0); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[rename("scale3d")] + #[required(0)] + fn scale3d<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + #[webidl] scale: Option, + #[webidl] origin_x: Option, + #[webidl] origin_y: Option, + #[webidl] origin_z: Option, + ) -> v8::Local<'a, v8::Object> { + let scale = *scale.unwrap_or(webidl::UnrestrictedDouble(1.0)); + let origin_x = *origin_x.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let origin_y = *origin_y.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let origin_z = *origin_z.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let out = self.clone(); + if origin_x == 0.0 && origin_y == 0.0 && origin_z == 0.0 { + out.scale_without_origin_self_inner(scale, scale, scale); + } else { + out.scale_with_origin_self_inner( + scale, scale, scale, origin_x, origin_y, origin_z, + ); + } + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[required(0)] + fn rotate<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + #[webidl] rotate_x: Option, + #[webidl] rotate_y: Option, + #[webidl] rotate_z: Option, + ) -> v8::Local<'a, v8::Object> { + let rotate_x = *rotate_x.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let (roll_deg, pitch_deg, yaw_deg) = + if rotate_y.is_none() && rotate_z.is_none() { + (0.0, 0.0, rotate_x) + } else { + ( + rotate_x, + *rotate_y.unwrap_or(webidl::UnrestrictedDouble(0.0)), + *rotate_z.unwrap_or(webidl::UnrestrictedDouble(0.0)), + ) + }; + let out = self.clone(); + out.rotate_self_inner( + roll_deg.to_radians(), + pitch_deg.to_radians(), + yaw_deg.to_radians(), + ); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[required(0)] + fn rotate_from_vector<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + #[webidl] x: Option, + #[webidl] y: Option, + ) -> v8::Local<'a, v8::Object> { + let x = *x.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let y = *y.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let out = self.clone(); + out.rotate_from_vector_self_inner(x, y); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[required(0)] + fn rotate_axis_angle<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + #[webidl] x: Option, + #[webidl] y: Option, + #[webidl] z: Option, + #[webidl] angle_deg: Option, + ) -> v8::Local<'a, v8::Object> { + let x = *x.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let y = *y.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let z = *z.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let angle_deg = *angle_deg.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let out = self.clone(); + out.rotate_axis_angle_self_inner(x, y, z, angle_deg.to_radians()); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[required(0)] + fn skew_x<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + #[webidl] x_deg: Option, + ) -> v8::Local<'a, v8::Object> { + let x_deg = *x_deg.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let out = self.clone(); + out.skew_self_inner(x_deg.to_radians(), 0.0); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[required(0)] + fn skew_y<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + #[webidl] y_deg: Option, + ) -> v8::Local<'a, v8::Object> { + let y_deg = *y_deg.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let out = self.clone(); + out.skew_self_inner(0.0, y_deg.to_radians()); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[required(0)] + fn multiply<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + other: v8::Local<'a, v8::Value>, + ) -> Result, GeometryError> { + let out = self.clone(); + if let Some(other) = + cppgc::try_unwrap_cppgc_proto_object::(scope, other) + { + out.multiply_self_inner(self, &other); + } else { + let other = DOMMatrixInit::convert( + scope, + other, + "Failed to execute 'multiply' on 'DOMMatrixReadOnly'".into(), + (|| Cow::Borrowed("Argument 1")).into(), + &Default::default(), + )?; + let other = DOMMatrixReadOnly::from_matrix_inner(&other)?; + out.multiply_self_inner(self, &other); + } + let obj = cppgc::make_cppgc_empty_object::(scope); + Ok(cppgc::wrap_object2(scope, obj, (out, DOMMatrix {}))) + } + + #[required(0)] + fn flip_x<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + let out = self.clone(); + out.flip_x_inner(); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[required(0)] + fn flip_y<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + let out = self.clone(); + out.flip_y_inner(); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[required(0)] + fn inverse<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + let out = self.clone(); + out.invert_self_inner(); + let obj = cppgc::make_cppgc_empty_object::(scope); + cppgc::wrap_object2(scope, obj, (out, DOMMatrix {})) + } + + #[reentrant] + #[required(0)] + fn transform_point<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + point: v8::Local<'a, v8::Value>, + ) -> Result, GeometryError> { + let out = DOMPointReadOnly { + inner: RefCell::new(Vector4::zeros()), + }; + if let Some(point) = + cppgc::try_unwrap_cppgc_proto_object::(scope, point) + { + matrix_transform_point(self, &point, &out); + } else { + let point = DOMPointInit::convert( + scope, + point, + "Failed to execute 'transformPoint' on 'DOMMatrixReadOnly'".into(), + (|| Cow::Borrowed("Argument 1")).into(), + &Default::default(), + )?; + let point = DOMPointReadOnly::from_point_inner(point); + matrix_transform_point(self, &point, &out); + } + let obj = cppgc::make_cppgc_empty_object::(scope); + Ok(cppgc::wrap_object2(scope, obj, (out, DOMPoint {}))) + } + + #[rename("toJSON")] + #[required(0)] + fn to_json<'a>( + &self, + scope: &mut v8::PinScope<'a, '_>, + ) -> v8::Local<'a, v8::Object> { + let mut obj = v8::Object::new(scope); + set_f64(scope, &mut obj, "a", self.a_inner()); + set_f64(scope, &mut obj, "b", self.b_inner()); + set_f64(scope, &mut obj, "c", self.c_inner()); + set_f64(scope, &mut obj, "d", self.d_inner()); + set_f64(scope, &mut obj, "e", self.e_inner()); + set_f64(scope, &mut obj, "f", self.f_inner()); + set_f64(scope, &mut obj, "m11", self.m11_inner()); + set_f64(scope, &mut obj, "m12", self.m12_inner()); + set_f64(scope, &mut obj, "m13", self.m13_inner()); + set_f64(scope, &mut obj, "m14", self.m14_inner()); + set_f64(scope, &mut obj, "m21", self.m21_inner()); + set_f64(scope, &mut obj, "m22", self.m22_inner()); + set_f64(scope, &mut obj, "m23", self.m23_inner()); + set_f64(scope, &mut obj, "m24", self.m24_inner()); + set_f64(scope, &mut obj, "m31", self.m31_inner()); + set_f64(scope, &mut obj, "m32", self.m32_inner()); + set_f64(scope, &mut obj, "m33", self.m33_inner()); + set_f64(scope, &mut obj, "m34", self.m34_inner()); + set_f64(scope, &mut obj, "m41", self.m41_inner()); + set_f64(scope, &mut obj, "m42", self.m42_inner()); + set_f64(scope, &mut obj, "m43", self.m43_inner()); + set_f64(scope, &mut obj, "m44", self.m44_inner()); + set_boolean(scope, &mut obj, "is2D", self.is_2d.get()); + set_boolean(scope, &mut obj, "isIdentity", self.is_identity_inner()); + obj + } +} + +pub struct DOMMatrix {} + +// SAFETY: we're sure `DOMMatrix` can be GCed +unsafe impl GarbageCollected for DOMMatrix { + fn trace(&self, _visitor: &mut deno_core::v8::cppgc::Visitor) {} + + fn get_name(&self) -> &'static std::ffi::CStr { + c"DOMMatrix" + } +} + +#[op2(inherit = DOMMatrixReadOnly)] +impl DOMMatrix { + #[constructor] + #[reentrant] + #[required(0)] + #[cppgc] + fn constructor<'a>( + state: &mut OpState, + scope: &mut v8::PinScope<'a, '_>, + value: v8::Local<'a, v8::Value>, + // TODO(petamoriken): Error when deleting next line. proc-macro bug? + #[webidl] _: bool, + ) -> Result<(DOMMatrixReadOnly, DOMMatrix), GeometryError> { + let ro = DOMMatrixReadOnly::new( + state, + scope, + value, + "Failed to construct 'DOMMatrixReadOnly'".into(), + ContextFn::new_borrowed(&|| Cow::Borrowed("Argument 1")), + )?; + Ok((ro, DOMMatrix {})) + } + + #[reentrant] + #[required(0)] + #[static_method] + fn from_matrix<'a>( + scope: &mut v8::PinScope<'a, '_>, + #[webidl] init: DOMMatrixInit, + ) -> Result, GeometryError> { + let ro = DOMMatrixReadOnly::from_matrix_inner(&init)?; + let obj = cppgc::make_cppgc_empty_object::(scope); + Ok(cppgc::wrap_object2(scope, obj, (ro, DOMMatrix {}))) + } + + #[rename("fromFloat32Array")] + #[required(1)] + #[static_method] + fn from_float32_array<'a>( + scope: &mut v8::PinScope<'a, '_>, + value: v8::Local<'a, v8::Value>, + ) -> Result, GeometryError> { + if !value.is_float32_array() { + return Err(GeometryError::TypeMismatch); + } + let float64 = Vec::::convert( + scope, + value, + "Failed to execute 'DOMMatrixReadOnly.fromFloat32Array'".into(), + (|| Cow::Borrowed("Argument 1")).into(), + &Default::default(), + )?; + let float64 = float64.into_iter().map(|f| *f).collect::>(); + + let ro = if let [a, b, c, d, e, f] = float64.as_slice() { + DOMMatrixReadOnly { + #[rustfmt::skip] + inner: RefCell::new(Matrix4::new( + *a, *c, 0.0, *e, + *b, *d, 0.0, *f, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + )), + is_2d: Cell::new(true), + } + } else if float64.len() == 16 { + DOMMatrixReadOnly { + inner: RefCell::new(Matrix4::from_column_slice(float64.as_slice())), + is_2d: Cell::new(false), + } + } else { + return Err(GeometryError::InvalidSequenceSize); + }; + + let obj = cppgc::make_cppgc_empty_object::(scope); + Ok(cppgc::wrap_object2(scope, obj, (ro, DOMMatrix {}))) + } + + #[rename("fromFloat64Array")] + #[required(1)] + #[static_method] + fn from_float64_array<'a>( + scope: &mut v8::PinScope<'a, '_>, + value: v8::Local<'a, v8::Value>, + ) -> Result, GeometryError> { + if !value.is_float64_array() { + return Err(GeometryError::TypeMismatch); + } + let float64 = Vec::::convert( + scope, + value, + "Failed to execute 'DOMMatrixReadOnly.fromFloat64Array'".into(), + (|| Cow::Borrowed("Argument 1")).into(), + &Default::default(), + )?; + let float64 = float64.into_iter().map(|f| *f).collect::>(); + + let ro = if let [a, b, c, d, e, f] = float64.as_slice() { + DOMMatrixReadOnly { + #[rustfmt::skip] + inner: RefCell::new(Matrix4::new( + *a, *c, 0.0, *e, + *b, *d, 0.0, *f, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + )), + is_2d: Cell::new(true), + } + } else if float64.len() == 16 { + DOMMatrixReadOnly { + inner: RefCell::new(Matrix4::from_column_slice(float64.as_slice())), + is_2d: Cell::new(false), + } + } else { + return Err(GeometryError::InvalidSequenceSize); + }; + + let obj = cppgc::make_cppgc_empty_object::(scope); + Ok(cppgc::wrap_object2(scope, obj, (ro, DOMMatrix {}))) + } + + #[fast] + #[getter] + fn a(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.a_inner() + } + + #[setter] + fn a( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_A] = *value; + } + + #[fast] + #[getter] + fn b(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.b_inner() + } + + #[setter] + fn b( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_B] = *value; + } + + #[fast] + #[getter] + fn c(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.c_inner() + } + + #[setter] + fn c( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_C] = *value; + } + + #[fast] + #[getter] + fn d(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.d_inner() + } + + #[setter] + fn d( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_D] = *value; + } + + #[fast] + #[getter] + fn e(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.e_inner() + } + + #[setter] + fn e( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_E] = *value; + } + + #[fast] + #[getter] + fn f(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.f_inner() + } + + #[setter] + fn f( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_F] = *value; + } + + #[fast] + #[getter] + fn m11(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m11_inner() + } + + #[setter] + fn m11( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M11] = *value; + } + + #[fast] + #[getter] + fn m12(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m12_inner() + } + + #[setter] + fn m12( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M12] = *value; + } + + #[fast] + #[getter] + fn m13(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m13_inner() + } + + #[setter] + fn m13( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M13] = *value; + if *value != 0.0 { + ro.is_2d.set(false); + } + } + + #[fast] + #[getter] + fn m14(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m14_inner() + } + + #[setter] + fn m14( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M14] = *value; + if *value != 0.0 { + ro.is_2d.set(false); + } + } + + #[fast] + #[getter] + fn m21(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m21_inner() + } + + #[setter] + fn m21( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M21] = *value; + } + + #[fast] + #[getter] + fn m22(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m22_inner() + } + + #[setter] + fn m22( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M22] = *value; + } + + #[fast] + #[getter] + fn m23(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m23_inner() + } + + #[setter] + fn m23( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M23] = *value; + if *value != 0.0 { + ro.is_2d.set(false); + } + } + + #[fast] + #[getter] + fn m24(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m24_inner() + } + + #[setter] + fn m24( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M24] = *value; + if *value != 0.0 { + ro.is_2d.set(false); + } + } + + #[fast] + #[getter] + fn m31(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m31_inner() + } + + #[setter] + fn m31( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M31] = *value; + if *value != 0.0 { + ro.is_2d.set(false); + } + } + + #[fast] + #[getter] + fn m32(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m32_inner() + } + + #[setter] + fn m32( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M32] = *value; + if *value != 0.0 { + ro.is_2d.set(false); + } + } + + #[fast] + #[getter] + fn m33(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m33_inner() + } + + #[setter] + fn m33( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M33] = *value; + if *value != 1.0 { + ro.is_2d.set(false); + } + } + + #[fast] + #[getter] + fn m34(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m34_inner() + } + + #[setter] + fn m34( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M34] = *value; + if *value != 0.0 { + ro.is_2d.set(false); + } + } + + #[fast] + #[getter] + fn m41(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m41_inner() + } + + #[setter] + fn m41( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M41] = *value; + } + + #[fast] + #[getter] + fn m42(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m42_inner() + } + + #[setter] + fn m42( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M42] = *value; + } + + #[fast] + #[getter] + fn m43(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m43_inner() + } + + #[setter] + fn m43( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M43] = *value; + if *value != 0.0 { + ro.is_2d.set(false); + } + } + + #[fast] + #[getter] + fn m44(&self, #[proto] ro: &DOMMatrixReadOnly) -> f64 { + ro.m44_inner() + } + + #[setter] + fn m44( + &self, + #[webidl] value: webidl::UnrestrictedDouble, + #[proto] ro: &DOMMatrixReadOnly, + ) { + ro.inner.borrow_mut()[INDEX_M44] = *value; + if *value != 1.0 { + ro.is_2d.set(false); + } + } + + #[required(0)] + #[global] + fn translate_self( + &self, + #[this] this: v8::Global, + #[webidl] tx: Option, + #[webidl] ty: Option, + #[webidl] tz: Option, + #[proto] ro: &DOMMatrixReadOnly, + ) -> v8::Global { + let tx = *tx.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let ty = *ty.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let tz = *tz.unwrap_or(webidl::UnrestrictedDouble(0.0)); + ro.translate_self_inner(tx, ty, tz); + this + } + + #[required(0)] + #[global] + fn scale_self( + &self, + #[this] this: v8::Global, + #[webidl] sx: Option, + #[webidl] sy: Option, + #[webidl] sz: Option, + #[webidl] origin_x: Option, + #[webidl] origin_y: Option, + #[webidl] origin_z: Option, + #[proto] ro: &DOMMatrixReadOnly, + ) -> v8::Global { + let sx = *sx.unwrap_or(webidl::UnrestrictedDouble(1.0)); + let sy = *sy.unwrap_or(webidl::UnrestrictedDouble(sx)); + let sz = *sz.unwrap_or(webidl::UnrestrictedDouble(1.0)); + let origin_x = *origin_x.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let origin_y = *origin_y.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let origin_z = *origin_z.unwrap_or(webidl::UnrestrictedDouble(0.0)); + if origin_x == 0.0 && origin_y == 0.0 && origin_z == 0.0 { + ro.scale_without_origin_self_inner(sx, sy, sz); + } else { + ro.scale_with_origin_self_inner(sx, sy, sz, origin_x, origin_y, origin_z); + } + this + } + + #[rename("scale3dSelf")] + #[required(0)] + #[global] + fn scale3d_self( + &self, + #[this] this: v8::Global, + #[webidl] scale: Option, + #[webidl] origin_x: Option, + #[webidl] origin_y: Option, + #[webidl] origin_z: Option, + #[proto] ro: &DOMMatrixReadOnly, + ) -> v8::Global { + let scale = *scale.unwrap_or(webidl::UnrestrictedDouble(1.0)); + let origin_x = *origin_x.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let origin_y = *origin_y.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let origin_z = *origin_z.unwrap_or(webidl::UnrestrictedDouble(0.0)); + if origin_x == 0.0 && origin_y == 0.0 && origin_z == 0.0 { + ro.scale_without_origin_self_inner(scale, scale, scale); + } else { + ro.scale_with_origin_self_inner( + scale, scale, scale, origin_x, origin_y, origin_z, + ); + } + this + } + + #[required(0)] + #[global] + fn rotate_self( + &self, + #[this] this: v8::Global, + #[webidl] rotate_x: Option, + #[webidl] rotate_y: Option, + #[webidl] rotate_z: Option, + #[proto] ro: &DOMMatrixReadOnly, + ) -> v8::Global { + let rotate_x = *rotate_x.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let (roll_deg, pitch_deg, yaw_deg) = + if rotate_y.is_none() && rotate_z.is_none() { + (0.0, 0.0, rotate_x) + } else { + ( + rotate_x, + *rotate_y.unwrap_or(webidl::UnrestrictedDouble(0.0)), + *rotate_z.unwrap_or(webidl::UnrestrictedDouble(0.0)), + ) + }; + ro.rotate_self_inner( + roll_deg.to_radians(), + pitch_deg.to_radians(), + yaw_deg.to_radians(), + ); + this + } + + #[required(0)] + #[global] + fn rotate_from_vector_self( + &self, + #[this] this: v8::Global, + #[webidl] x: Option, + #[webidl] y: Option, + #[proto] ro: &DOMMatrixReadOnly, + ) -> v8::Global { + let x = *x.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let y = *y.unwrap_or(webidl::UnrestrictedDouble(0.0)); + ro.rotate_from_vector_self_inner(x, y); + this + } + + #[required(0)] + #[global] + fn rotate_axis_angle_self( + &self, + #[this] this: v8::Global, + #[webidl] x: Option, + #[webidl] y: Option, + #[webidl] z: Option, + #[webidl] angle_deg: Option, + #[proto] ro: &DOMMatrixReadOnly, + ) -> v8::Global { + let x = *x.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let y = *y.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let z = *z.unwrap_or(webidl::UnrestrictedDouble(0.0)); + let angle_deg = *angle_deg.unwrap_or(webidl::UnrestrictedDouble(0.0)); + ro.rotate_axis_angle_self_inner(x, y, z, angle_deg.to_radians()); + this + } + + #[required(0)] + #[global] + fn skew_x_self( + &self, + #[this] this: v8::Global, + #[webidl] x_deg: Option, + #[proto] ro: &DOMMatrixReadOnly, + ) -> v8::Global { + let x_deg = *x_deg.unwrap_or(webidl::UnrestrictedDouble(0.0)); + ro.skew_self_inner(x_deg.to_radians(), 0.0); + this + } + + #[required(0)] + #[global] + fn skew_y_self( + &self, + #[this] this: v8::Global, + #[webidl] y_deg: Option, + #[proto] ro: &DOMMatrixReadOnly, + ) -> v8::Global { + let y_deg = *y_deg.unwrap_or(webidl::UnrestrictedDouble(0.0)); + ro.skew_self_inner(0.0, y_deg.to_radians()); + this + } + + #[required(0)] + #[global] + fn multiply_self<'a>( + &self, + #[this] this: v8::Global, + scope: &mut v8::PinScope<'a, '_>, + other: v8::Local<'a, v8::Value>, + #[proto] ro: &DOMMatrixReadOnly, + ) -> Result, GeometryError> { + let lhs = ro.clone(); + if let Some(other) = + cppgc::try_unwrap_cppgc_proto_object::(scope, other) + { + if ptr::eq(ro, &*other) { + ro.multiply_self_inner(&lhs, &other.clone()); + } else { + ro.multiply_self_inner(&lhs, &other); + }; + } else { + let other = DOMMatrixInit::convert( + scope, + other, + "Failed to execute 'multiply' on 'DOMMatrixReadOnly'".into(), + (|| Cow::Borrowed("Argument 1")).into(), + &Default::default(), + )?; + let other = DOMMatrixReadOnly::from_matrix_inner(&other)?; + ro.multiply_self_inner(&lhs, &other); + } + Ok(this) + } + + #[required(0)] + #[global] + fn pre_multiply_self<'a>( + &self, + #[this] this: v8::Global, + scope: &mut v8::PinScope<'a, '_>, + other: v8::Local<'a, v8::Value>, + #[proto] ro: &DOMMatrixReadOnly, + ) -> Result, GeometryError> { + let rhs = ro.clone(); + if let Some(other) = + cppgc::try_unwrap_cppgc_proto_object::(scope, other) + { + if ptr::eq(ro, &*other) { + ro.multiply_self_inner(&other.clone(), &rhs); + } else { + ro.multiply_self_inner(&other, &rhs); + } + } else { + let other = DOMMatrixInit::convert( + scope, + other, + "Failed to execute 'multiply' on 'DOMMatrixReadOnly'".into(), + (|| Cow::Borrowed("Argument 1")).into(), + &Default::default(), + )?; + let other = DOMMatrixReadOnly::from_matrix_inner(&other)?; + ro.multiply_self_inner(&other, &rhs); + } + Ok(this) + } + + #[required(0)] + #[global] + fn invert_self( + &self, + #[this] this: v8::Global, + #[proto] ro: &DOMMatrixReadOnly, + ) -> v8::Global { + ro.invert_self_inner(); + this + } +} + +#[inline] +fn set_f64( + scope: &mut v8::PinScope<'_, '_>, + object: &mut v8::Local, + key: &str, + value: f64, +) { + let key = v8::String::new(scope, key).unwrap(); + let value = v8::Number::new(scope, value); + object.create_data_property(scope, key.into(), value.into()); +} + +#[inline] +fn set_boolean( + scope: &mut v8::PinScope<'_, '_>, + object: &mut v8::Local, + key: &str, + value: bool, +) { + let key = v8::String::new(scope, key).unwrap(); + let value = v8::Boolean::new(scope, value); + object.create_data_property(scope, key.into(), value.into()); +} + +// TODO(petamoriken) Use f64::maximum instead https://github.com/rust-lang/rust/issues/91079 +#[inline] +fn maximum(a: f64, b: f64) -> f64 { + if a > b { + a + } else if b > a { + b + } else if a == b { + if a.is_sign_positive() && b.is_sign_negative() { + a + } else { + b + } + } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. + a + b + } +} + +// TODO(petamoriken) Use f64::minimum instead https://github.com/rust-lang/rust/issues/91079 +#[inline] +fn minimum(a: f64, b: f64) -> f64 { + if a < b { + a + } else if b < a { + b + } else if a == b { + if a.is_sign_negative() && b.is_sign_positive() { + a + } else { + b + } + } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. + a + b + } +} + +#[inline] +fn matrix_transform_point( + matrix: &DOMMatrixReadOnly, + point: &DOMPointReadOnly, + out: &DOMPointReadOnly, +) { + let inner = matrix.inner.borrow(); + let point = point.inner.borrow(); + let mut result = out.inner.borrow_mut(); + inner.mul_to(&point, &mut result); +} + +#[op2] +#[arraybuffer] +pub fn op_geometry_matrix_to_buffer<'a>( + scope: &mut v8::PinScope<'a, '_>, + matrix: v8::Local<'a, v8::Value>, +) -> Result, GeometryError> { + let Some(matrix) = + cppgc::try_unwrap_cppgc_proto_object::(scope, matrix) + else { + return Err(GeometryError::IllegalInvocation); + }; + let inner = matrix.inner.borrow(); + Ok( + // SAFETY: in-range access + unsafe { + slice::from_raw_parts( + inner.as_slice().as_ptr() as *mut u8, + mem::size_of::() * 16, + ) + } + .to_vec(), + ) +} + +#[op2] +#[string] +pub fn op_geometry_matrix_to_string<'a>( + scope: &mut v8::PinScope<'a, '_>, + matrix: v8::Local<'a, v8::Value>, +) -> Result { + #[inline] + fn to_string(scope: &mut v8::PinScope<'_, '_>, value: f64) -> String { + let number = v8::Number::new(scope, value); + number.to_string(scope).unwrap().to_rust_string_lossy(scope) + } + + let Some(matrix) = + cppgc::try_unwrap_cppgc_proto_object::(scope, matrix) + else { + return Err(GeometryError::IllegalInvocation); + }; + if !matrix.is_finite_inner() { + return Err(GeometryError::InvalidState); + } + if matrix.is_2d.get() { + Ok(format!( + "matrix({}, {}, {}, {}, {}, {})", + to_string(scope, matrix.a_inner()), + to_string(scope, matrix.b_inner()), + to_string(scope, matrix.c_inner()), + to_string(scope, matrix.d_inner()), + to_string(scope, matrix.e_inner()), + to_string(scope, matrix.f_inner()), + )) + } else { + Ok(format!( + "matrix3d({})", + matrix + .inner + .borrow() + .iter() + .map(|item| to_string(scope, *item)) + .collect::>() + .join(", ") + )) + } +} + +#[op2(fast)] +pub fn op_geometry_matrix_set_matrix_value<'a>( + scope: &mut v8::PinScope<'a, '_>, + input: v8::Local<'a, v8::Value>, + transform_list: v8::Local<'a, v8::Value>, +) -> Result<(), GeometryError> { + if cppgc::try_unwrap_cppgc_proto_object::(scope, input).is_none() { + return Err(GeometryError::IllegalInvocation); + } + let matrix = + cppgc::try_unwrap_cppgc_proto_object::(scope, input) + .unwrap(); + let transform_list = String::convert( + scope, + transform_list, + "Failed to execute 'setMatrixValue' on 'DOMMatrix'".into(), + (|| Cow::Borrowed("Argument 1")).into(), + &Default::default(), + )?; + if transform_list.is_empty() { + // Make it an identity matrix + let mut inner = matrix.inner.borrow_mut(); + inner.fill(0.0); + inner.fill_diagonal(1.0); + matrix.is_2d.set(true); + return Ok(()); + } + let Ok(transform_list) = TransformList::parse_string(&transform_list) else { + return Err(GeometryError::FailedToParse); + }; + matrix.set_matrix_value_inner(&transform_list)?; + Ok(()) +} diff --git a/ext/webidl/00_webidl.js b/ext/webidl/00_webidl.js index 56f6c931d278da..8c20c960db88b3 100644 --- a/ext/webidl/00_webidl.js +++ b/ext/webidl/00_webidl.js @@ -690,6 +690,9 @@ converters["UVString?"] = createNullableConverter( converters["sequence"] = createSequenceConverter( converters.double, ); +converters["sequence"] = createSequenceConverter( + converters["unrestricted double"], +); converters["sequence"] = createSequenceConverter( converters.object, ); diff --git a/ext/webidl/internal.d.ts b/ext/webidl/internal.d.ts index a884d982aabb2f..adfb6713563c80 100644 --- a/ext/webidl/internal.d.ts +++ b/ext/webidl/internal.d.ts @@ -348,6 +348,12 @@ declare module "ext:deno_webidl/00_webidl.js" { context?: string, opts?: any, ): number[]; + ["sequence"]( + v: any, + prefix?: string, + context?: string, + opts?: any, + ): number[]; [type: string]: ( v: any, diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index f216569f4aa3ca..665c8170acbb48 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -52,6 +52,7 @@ deno_features.workspace = true deno_fetch.workspace = true deno_ffi.workspace = true deno_fs = { workspace = true, features = ["sync_fs"] } +deno_geometry.workspace = true deno_http.workspace = true deno_io.workspace = true deno_kv.workspace = true diff --git a/runtime/js/98_global_scope_shared.js b/runtime/js/98_global_scope_shared.js index 97a8a37efc3636..dcdb2e730c02c5 100644 --- a/runtime/js/98_global_scope_shared.js +++ b/runtime/js/98_global_scope_shared.js @@ -42,6 +42,7 @@ import { setTimeout as nodeSetTimeout, } from "node:timers"; import { loadWebGPU } from "ext:deno_webgpu/00_init.js"; +import { loadGeometry } from "ext:deno_geometry/00_init.js"; import * as webgpuSurface from "ext:deno_webgpu/02_surface.js"; import { unstableIds } from "ext:runtime/90_deno_ns.js"; @@ -65,6 +66,34 @@ const windowOrWorkerGlobalScope = { CustomEvent: core.propNonEnumerable(event.CustomEvent), DecompressionStream: core.propNonEnumerable(compression.DecompressionStream), DOMException: core.propNonEnumerable(DOMException), + DOMMatrix: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMMatrix, + loadGeometry, + ), + DOMMatrixReadOnly: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMMatrixReadOnly, + loadGeometry, + ), + DOMPoint: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMPoint, + loadGeometry, + ), + DOMPointReadOnly: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMPointReadOnly, + loadGeometry, + ), + DOMQuad: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMQuad, + loadGeometry, + ), + DOMRect: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMRect, + loadGeometry, + ), + DOMRectReadOnly: core.propNonEnumerableLazyLoaded( + (geometry) => geometry.DOMRectReadOnly, + loadGeometry, + ), ErrorEvent: core.propNonEnumerable(event.ErrorEvent), Event: core.propNonEnumerable(event.Event), EventTarget: core.propNonEnumerable(event.EventTarget), diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 12c66c0963d1da..b798a3bd684c65 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -390,6 +390,12 @@ core.registerErrorBuilder( return new DOMException(msg, "InvalidStateError"); }, ); +core.registerErrorBuilder( + "DOMExceptionSyntaxError", + function DOMExceptionSyntaxError(msg) { + return new DOMException(msg, "SyntaxError"); + }, +); function runtimeStart( denoVersion, diff --git a/runtime/lib.rs b/runtime/lib.rs index 882e7168debf05..7a001ff97be590 100644 --- a/runtime/lib.rs +++ b/runtime/lib.rs @@ -10,6 +10,7 @@ pub use deno_crypto; pub use deno_fetch; pub use deno_ffi; pub use deno_fs; +pub use deno_geometry; pub use deno_http; pub use deno_io; pub use deno_kv; diff --git a/runtime/shared.rs b/runtime/shared.rs index a5735919f7a884..716b198cda7308 100644 --- a/runtime/shared.rs +++ b/runtime/shared.rs @@ -13,6 +13,7 @@ extension!(runtime, deno_web, deno_fetch, deno_cache, + deno_geometry, deno_websocket, deno_webstorage, deno_crypto, diff --git a/runtime/snapshot.rs b/runtime/snapshot.rs index d3f46ed8aaa6cb..42be64b9a15a64 100644 --- a/runtime/snapshot.rs +++ b/runtime/snapshot.rs @@ -31,6 +31,7 @@ pub fn create_runtime_snapshot( deno_url::deno_url::lazy_init(), deno_web::deno_web::lazy_init::(), deno_webgpu::deno_webgpu::lazy_init(), + deno_geometry::deno_geometry::lazy_init(), deno_canvas::deno_canvas::lazy_init(), deno_fetch::deno_fetch::lazy_init::(), deno_cache::deno_cache::lazy_init(), diff --git a/runtime/snapshot_info.rs b/runtime/snapshot_info.rs index d9cf57a20adb1e..2c8759880a364a 100644 --- a/runtime/snapshot_info.rs +++ b/runtime/snapshot_info.rs @@ -224,6 +224,7 @@ pub fn get_extensions_in_snapshot() -> Vec { Default::default(), ), deno_webgpu::deno_webgpu::init(), + deno_geometry::deno_geometry::init(false), deno_canvas::deno_canvas::init(), deno_fetch::deno_fetch::init::(Default::default()), deno_cache::deno_cache::init(None), diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index f6d52398c83383..3877119390ffc6 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -529,6 +529,7 @@ impl WebWorker { Some(options.main_module.clone()), ), deno_webgpu::deno_webgpu::init(), + deno_geometry::deno_geometry::init(false), deno_canvas::deno_canvas::init(), deno_fetch::deno_fetch::init::( deno_fetch::Options { diff --git a/runtime/worker.rs b/runtime/worker.rs index a0b35339d93ec6..cebc8ee4a902d7 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -534,6 +534,7 @@ impl MainWorker { services.blob_store.clone(), options.bootstrap.location.clone(), ), + deno_geometry::deno_geometry::args(true), deno_fetch::deno_fetch::args::( deno_fetch::Options { user_agent: options.bootstrap.user_agent.clone(), @@ -1056,6 +1057,7 @@ fn common_extensions< deno_url::deno_url::init(), deno_web::deno_web::lazy_init::(), deno_webgpu::deno_webgpu::init(), + deno_geometry::deno_geometry::lazy_init(), deno_canvas::deno_canvas::init(), deno_fetch::deno_fetch::lazy_init::(), deno_cache::deno_cache::lazy_init(), diff --git a/tests/integration/js_unit_tests.rs b/tests/integration/js_unit_tests.rs index dc8eeff183efb7..f3bd81fd896e52 100644 --- a/tests/integration/js_unit_tests.rs +++ b/tests/integration/js_unit_tests.rs @@ -41,6 +41,7 @@ util::unit_test_factory!( filereader_test, files_test, fs_events_test, + geometry_test, get_random_values_test, globals_test, headers_test, diff --git a/tests/unit/geometry_test.ts b/tests/unit/geometry_test.ts new file mode 100644 index 00000000000000..3ea1806db45724 --- /dev/null +++ b/tests/unit/geometry_test.ts @@ -0,0 +1,1195 @@ +// Copyright 2018-2025 the Deno authors. MIT license. +import { + assertAlmostEquals, + assertEquals, + assertStrictEquals, + assertThrows, +} from "./test_util.ts"; + +Deno.test(function matrixTransformPoint() { + const point = new DOMPoint(1, 2, 3, 4); + // deno-fmt-ignore + const matrix = DOMMatrix.fromMatrix({ + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }); + const point2 = point.matrixTransform(matrix); + const point3 = matrix.transformPoint(point); + assertEquals( + point, + new DOMPoint(1, 2, 3, 4), + ); + assertEquals( + point2, + new DOMPoint(30, 70, 110, 150), + ); + assertEquals( + point3, + new DOMPoint(30, 70, 110, 150), + ); +}); + +Deno.test(function matrixTranslate() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.translate(1, 2, 3); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2, m31: 3, m41: 1 * 1 + 2 * 2 + 3 * 3 + 4 * 1, + m12: 5, m22: 6, m32: 7, m42: 5 * 1 + 6 * 2 + 7 * 3 + 8 * 1, + m13: 9, m23: 10, m33: 11, m43: 9 * 1 + 10 * 2 + 11 * 3 + 12 * 1, + m14: 13, m24: 14, m34: 15, m44: 13 * 1 + 14 * 2 + 15 * 3 + 16 * 1, + }), + ); +}); + +Deno.test(function matrixTranslateSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.translateSelf(1, 2, 3); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2, m31: 3, m41: 1 * 1 + 2 * 2 + 3 * 3 + 4 * 1, + m12: 5, m22: 6, m32: 7, m42: 5 * 1 + 6 * 2 + 7 * 3 + 8 * 1, + m13: 9, m23: 10, m33: 11, m43: 9 * 1 + 10 * 2 + 11 * 3 + 12 * 1, + m14: 13, m24: 14, m34: 15, m44: 13 * 1 + 14 * 2 + 15 * 3 + 16 * 1, + }), + ); +}); + +Deno.test(function matrixScale() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale(1, 2, 3); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2 * 2, m31: 3 * 3, m41: 4, + m12: 5, m22: 6 * 2, m32: 7 * 3, m42: 8, + m13: 9, m23: 10 * 2, m33: 11 * 3, m43: 12, + m14: 13, m24: 14 * 2, m34: 15 * 3, m44: 16, + }), + ); +}); + +Deno.test(function matrixScaleSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scaleSelf(1, 2, 3); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2 * 2, m31: 3 * 3, m41: 4, + m12: 5, m22: 6 * 2, m32: 7 * 3, m42: 8, + m13: 9, m23: 10 * 2, m33: 11 * 3, m43: 12, + m14: 13, m24: 14 * 2, m34: 15 * 3, m44: 16, + }), + ); +}); + +Deno.test(function matrixScaleWithOrigin() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale(1, 2, 3, 4, 5, 6); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2 * 2, m31: 3 * 3, m41: -42, + m12: 5, m22: 6 * 2, m32: 7 * 3, m42: -106, + m13: 9, m23: 10 * 2, m33: 11 * 3, m43: -170, + m14: 13, m24: 14 * 2, m34: 15 * 3, m44: -234, + }), + ); +}); + +Deno.test(function matrixScaleWithOriginSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scaleSelf(1, 2, 3, 4, 5, 6); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2 * 2, m31: 3 * 3, m41: -42, + m12: 5, m22: 6 * 2, m32: 7 * 3, m42: -106, + m13: 9, m23: 10 * 2, m33: 11 * 3, m43: -170, + m14: 13, m24: 14 * 2, m34: 15 * 3, m44: -234, + }), + ); +}); + +Deno.test(function matrixScaleNonUniform() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scaleNonUniform(1, 2); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2 * 2, m31: 3, m41: 4, + m12: 5, m22: 6 * 2, m32: 7, m42: 8, + m13: 9, m23: 10 * 2, m33: 11, m43: 12, + m14: 13, m24: 14 * 2, m34: 15, m44: 16, + }), + ); +}); + +Deno.test(function matrixScale3d() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale3d(2); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 2, m21: 2 * 2, m31: 3 * 2, m41: 4, + m12: 5 * 2, m22: 6 * 2, m32: 7 * 2, m42: 8, + m13: 9 * 2, m23: 10 * 2, m33: 11 * 2, m43: 12, + m14: 13 * 2, m24: 14 * 2, m34: 15 * 2, m44: 16, + }), + ); +}); + +Deno.test(function matrixScale3dSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale3dSelf(2); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 2, m21: 2 * 2, m31: 3 * 2, m41: 4, + m12: 5 * 2, m22: 6 * 2, m32: 7 * 2, m42: 8, + m13: 9 * 2, m23: 10 * 2, m33: 11 * 2, m43: 12, + m14: 13 * 2, m24: 14 * 2, m34: 15 * 2, m44: 16, + }), + ); +}); + +Deno.test(function matrixScale3dWithOrigin() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale3d(2, 4, 5, 6); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 2, m21: 2 * 2, m31: 3 * 2, m41: -28, + m12: 5 * 2, m22: 6 * 2, m32: 7 * 2, m42: -84, + m13: 9 * 2, m23: 10 * 2, m33: 11 * 2, m43: -140, + m14: 13 * 2, m24: 14 * 2, m34: 15 * 2, m44: -196, + }), + ); +}); + +Deno.test(function matrixScale3dWithOriginSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale3dSelf(2, 4, 5, 6); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 2, m21: 2 * 2, m31: 3 * 2, m41: -28, + m12: 5 * 2, m22: 6 * 2, m32: 7 * 2, m42: -84, + m13: 9 * 2, m23: 10 * 2, m33: 11 * 2, m43: -140, + m14: 13 * 2, m24: 14 * 2, m34: 15 * 2, m44: -196, + }), + ); +}); + +Deno.test(function matrixRotate() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: -3, m21: -2, m31: -1, m41: 4, + m12: -7, m22: -6, m32: -5, m42: 8, + m13: -11, m23: -10, m33: -9, m43: 12, + m14: -15, m24: -14, m34: -13, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotate(0, 90, 180); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix2[key], + value, + ); + } +}); + +Deno.test(function matrixRotateSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: -3, m21: -2, m31: -1, m41: 4, + m12: -7, m22: -6, m32: -5, m42: 8, + m13: -11, m23: -10, m33: -9, m43: 12, + m14: -15, m24: -14, m34: -13, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotateSelf(0, 90, 180); + assertStrictEquals( + matrix, + matrix2, + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix[key], + value, + ); + } +}); + +Deno.test(function matrixRotateFromVector() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 2.121320343559643, m21: 0.7071067811865476, m31: 3, m41: 4, + m12: 7.778174593052023, m22: 0.7071067811865479, m32: 7, m42: 8, + m13: 13.435028842544405, m23: 0.7071067811865470, m33: 11, m43: 12, + m14: 19.091883092036785, m24: 0.7071067811865461, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotateFromVector(1, 1); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix2[key], + value, + ); + } +}); + +Deno.test(function matrixRotateFromVectorSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 2.121320343559643, m21: 0.7071067811865476, m31: 3, m41: 4, + m12: 7.778174593052023, m22: 0.7071067811865479, m32: 7, m42: 8, + m13: 13.435028842544405, m23: 0.7071067811865470, m33: 11, m43: 12, + m14: 19.091883092036785, m24: 0.7071067811865461, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotateFromVectorSelf(1, 1); + assertStrictEquals( + matrix, + matrix2, + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix[key], + value, + ); + } +}); + +Deno.test(function matrixRotateAxisAngle() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5.228294835332138, m22: 4.854398120227125, m32: 7.6876363080712045, m42: 8, + m13: 9.456589670664275, m23: 7.708796240454249, m33: 12.3752726161424090, m43: 12, + m14: 13.684884505996411, m24: 10.563194360681376, m34: 17.0629089242136120, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotateAxisAngle(1, 2, 3, 30); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix2[key], + value, + ); + } +}); + +Deno.test(function matrixRotateAxisAngleSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5.228294835332138, m22: 4.854398120227125, m32: 7.6876363080712045, m42: 8, + m13: 9.456589670664275, m23: 7.708796240454249, m33: 12.3752726161424090, m43: 12, + m14: 13.684884505996411, m24: 10.563194360681376, m34: 17.0629089242136120, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotateAxisAngleSelf(1, 2, 3, 30); + assertStrictEquals( + matrix, + matrix2, + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix[key], + value, + ); + } +}); + +Deno.test(function matrixSkewX() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 1, m21: 2.5773502691896257, m31: 3, m41: 4, + m12: 5, m22: 8.8867513459481270, m32: 7, m42: 8, + m13: 9, m23: 15.1961524227066300, m33: 11, m43: 12, + m14: 13, m24: 21.5055534994651330, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.skewX(30); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix2[key], + value, + ); + } +}); + +Deno.test(function matrixSkewXSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 1, m21: 2.5773502691896257, m31: 3, m41: 4, + m12: 5, m22: 8.8867513459481270, m32: 7, m42: 8, + m13: 9, m23: 15.1961524227066300, m33: 11, m43: 12, + m14: 13, m24: 21.5055534994651330, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.skewXSelf(30); + assertStrictEquals( + matrix, + matrix2, + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix[key], + value, + ); + } +}); + +Deno.test(function matrixSkewY() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 2.1547005383792515, m21: 2, m31: 3, m41: 4, + m12: 8.4641016151377530, m22: 6, m32: 7, m42: 8, + m13: 14.7735026918962560, m23: 10, m33: 11, m43: 12, + m14: 21.0829037686547600, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.skewY(30); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix2[key], + value, + ); + } +}); + +Deno.test(function matrixSkewYSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 2.1547005383792515, m21: 2, m31: 3, m41: 4, + m12: 8.4641016151377530, m22: 6, m32: 7, m42: 8, + m13: 14.7735026918962560, m23: 10, m33: 11, m43: 12, + m14: 21.0829037686547600, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.skewYSelf(30); + assertStrictEquals( + matrix, + matrix2, + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix[key], + value, + ); + } +}); + +Deno.test(function matrixMultiply() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.multiply({ m11: 1, m22: 2, m33: 3, m44: 4 }); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 1, m21: 2 * 2, m31: 3 * 3, m41: 4 * 4, + m12: 5 * 1, m22: 6 * 2, m32: 7 * 3, m42: 8 * 4, + m13: 9 * 1, m23: 10 * 2, m33: 11 * 3, m43: 12 * 4, + m14: 13 * 1, m24: 14 * 2, m34: 15 * 3, m44: 16 * 4, + }), + ); +}); + +Deno.test(function matrixMultiplySelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.multiplySelf({ m11: 1, m22: 2, m33: 3, m44: 4 }); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 1, m21: 2 * 2, m31: 3 * 3, m41: 4 * 4, + m12: 5 * 1, m22: 6 * 2, m32: 7 * 3, m42: 8 * 4, + m13: 9 * 1, m23: 10 * 2, m33: 11 * 3, m43: 12 * 4, + m14: 13 * 1, m24: 14 * 2, m34: 15 * 3, m44: 16 * 4, + }), + ); +}); + +Deno.test(function matrixMultiplySelfWithSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.multiplySelf(matrix); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 90, m21: 100, m31: 110, m41: 120, + m12: 202, m22: 228, m32: 254, m42: 280, + m13: 314, m23: 356, m33: 398, m43: 440, + m14: 426, m24: 484, m34: 542, m44: 600, + }), + ); +}); + +Deno.test(function matrixPreMultiplySelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.preMultiplySelf({ m11: 1, m22: 2, m33: 3, m44: 4 }); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 1, m21: 2 * 1, m31: 3 * 1, m41: 4 * 1, + m12: 5 * 2, m22: 6 * 2, m32: 7 * 2, m42: 8 * 2, + m13: 9 * 3, m23: 10 * 3, m33: 11 * 3, m43: 12 * 3, + m14: 13 * 4, m24: 14 * 4, m34: 15 * 4, m44: 16 * 4, + }), + ); +}); + +Deno.test(function matrixPreMultiplySelfWithSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.preMultiplySelf(matrix); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 90, m21: 100, m31: 110, m41: 120, + m12: 202, m22: 228, m32: 254, m42: 280, + m13: 314, m23: 356, m33: 398, m43: 440, + m14: 426, m24: 484, m34: 542, m44: 600, + }), + ); +}); + +Deno.test(function matrixFlipX() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.flipX(); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: -1, m21: 2, m31: 3, m41: 4, + m12: -5, m22: 6, m32: 7, m42: 8, + m13: -9, m23: 10, m33: 11, m43: 12, + m14: -13, m24: 14, m34: 15, m44: 16, + }), + ); +}); + +Deno.test(function matrixFlipY() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.flipY(); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: -2, m31: 3, m41: 4, + m12: 5, m22: -6, m32: 7, m42: 8, + m13: 9, m23: -10, m33: 11, m43: 12, + m14: 13, m24: -14, m34: 15, m44: 16, + }), + ); +}); + +Deno.test(function matrixInverse() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 0, m22: 1, m32: 7, m42: 8, + m13: 0, m23: 0, m33: 1, m43: 12, + m14: 0, m24: 0, m34: 0, m44: 1, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.inverse(); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: -2, m31: 11, m41: -120, + m12: 0, m22: 1, m32: -7, m42: 76, + m13: 0, m23: 0, m33: 1, m43: -12, + m14: 0, m24: 0, m34: 0, m44: 1, + }), + ); +}); + +Deno.test(function matrixInvertSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 0, m22: 1, m32: 7, m42: 8, + m13: 0, m23: 0, m33: 1, m43: 12, + m14: 0, m24: 0, m34: 0, m44: 1, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.invertSelf(); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: -2, m31: 11, m41: -120, + m12: 0, m22: 1, m32: -7, m42: 76, + m13: 0, m23: 0, m33: 1, m43: -12, + m14: 0, m24: 0, m34: 0, m44: 1, + }), + ); +}); + +Deno.test(function matrixInverse2D() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 0, m41: 4, + m12: 0, m22: 1, m32: 0, m42: 8, + m13: 0, m23: 0, m33: 1, m43: 0, + m14: 0, m24: 0, m34: 0, m44: 1, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.inverse(); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: -2, m31: 0, m41: 12, + m12: 0, m22: 1, m32: 0, m42: -8, + m13: 0, m23: 0, m33: 1, m43: 0, + m14: 0, m24: 0, m34: 0, m44: 1, + }), + ); +}); + +Deno.test(function matrixInvert2DSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 0, m41: 4, + m12: 0, m22: 1, m32: 0, m42: 8, + m13: 0, m23: 0, m33: 1, m43: 0, + m14: 0, m24: 0, m34: 0, m44: 1, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.invertSelf(); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: -2, m31: 0, m41: 12, + m12: 0, m22: 1, m32: 0, m42: -8, + m13: 0, m23: 0, m33: 1, m43: 0, + m14: 0, m24: 0, m34: 0, m44: 1, + }), + ); +}); + +Deno.test(function prototypeOverwrite() { + const point = new DOMPointReadOnly(); + Object.setPrototypeOf(point, DOMPoint.prototype); + assertThrows( + () => { + // @ts-ignore test + point.x = 1; + }, + TypeError, + "expected DOMPoint", + ); + assertThrows( + () => { + // @ts-ignore test + point.y = 1; + }, + TypeError, + "expected DOMPoint", + ); + assertThrows( + () => { + // @ts-ignore test + point.z = 1; + }, + TypeError, + "expected DOMPoint", + ); + assertThrows( + () => { + // @ts-ignore test + point.w = 1; + }, + TypeError, + "expected DOMPoint", + ); + + const rect = new DOMRectReadOnly(); + Object.setPrototypeOf(rect, DOMRect.prototype); + assertThrows( + () => { + // @ts-ignore test + rect.x = 1; + }, + TypeError, + "expected DOMRect", + ); + assertThrows( + () => { + // @ts-ignore test + rect.y = 1; + }, + TypeError, + "expected DOMRect", + ); + assertThrows( + () => { + // @ts-ignore test + rect.width = 1; + }, + TypeError, + "expected DOMRect", + ); + assertThrows( + () => { + // @ts-ignore test + rect.height = 1; + }, + TypeError, + "expected DOMRect", + ); + + const matrix = new DOMMatrixReadOnly(); + Object.setPrototypeOf(matrix, DOMMatrix.prototype); + assertThrows( + () => { + // @ts-ignore test + matrix.a = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.b = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.c = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.d = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.e = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.f = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m11 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m12 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m13 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m14 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m21 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m22 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m23 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m24 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m31 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m32 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m33 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m34 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m41 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m42 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m43 = 1; + }, + TypeError, + "expected DOMMatrix", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m44 = 1; + }, + TypeError, + "expected DOMMatrix", + ); +}); diff --git a/tests/unit/test_util.ts b/tests/unit/test_util.ts index fb1a8aa940ffe7..fd371b89e016ef 100644 --- a/tests/unit/test_util.ts +++ b/tests/unit/test_util.ts @@ -6,6 +6,7 @@ export { colors }; import { join, resolve } from "@std/path"; export { assert, + assertAlmostEquals, assertEquals, assertFalse, AssertionError, diff --git a/tests/wpt/runner/expectation.json b/tests/wpt/runner/expectation.json index 654087a969e72b..41f41271db7807 100644 --- a/tests/wpt/runner/expectation.json +++ b/tests/wpt/runner/expectation.json @@ -17828,5 +17828,129 @@ "request-credentials.window.html": false, "request-redirect.window.html": false, "eventsource-request-cancellation.window.html": false + }, + "css": { + "geometry": { + "DOMMatrix-001.html": true, + "DOMMatrix-002.html": true, + "DOMMatrix-003.html": true, + "DOMMatrix-a-f-alias.html": true, + "DOMMatrix-attributes.html": true, + "DOMMatrix-css-string.worker.html": true, + "DOMMatrix-invert-invertible.html": true, + "DOMMatrix-invert-non-invertible.html": true, + "DOMMatrix-invert-preserves-2d.html": true, + "DOMMatrix-newobject.html": true, + "DOMMatrix-stringifier.html": [ + "WebKitCSSMatrix stringifier: identity (2d)", + "WebKitCSSMatrix stringifier: identity (3d)", + "WebKitCSSMatrix stringifier: NaN (2d)", + "WebKitCSSMatrix stringifier: NaN (3d)", + "WebKitCSSMatrix stringifier: Infinity (2d)", + "WebKitCSSMatrix stringifier: Infinity (3d)", + "WebKitCSSMatrix stringifier: -Infinity (2d)", + "WebKitCSSMatrix stringifier: -Infinity (3d)", + "WebKitCSSMatrix stringifier: 1/3 (2d)", + "WebKitCSSMatrix stringifier: 1/3 (3d)", + "WebKitCSSMatrix stringifier: 1/300000 (2d)", + "WebKitCSSMatrix stringifier: 1/300000 (3d)", + "WebKitCSSMatrix stringifier: 1/300000000 (2d)", + "WebKitCSSMatrix stringifier: 1/300000000 (3d)", + "WebKitCSSMatrix stringifier: 100000 + (1/3) (2d)", + "WebKitCSSMatrix stringifier: 100000 + (1/3) (3d)", + "WebKitCSSMatrix stringifier: Math.pow(2, 53) + 1 (2d)", + "WebKitCSSMatrix stringifier: Math.pow(2, 53) + 1 (3d)", + "WebKitCSSMatrix stringifier: Math.pow(2, 53) + 2 (2d)", + "WebKitCSSMatrix stringifier: Math.pow(2, 53) + 2 (3d)", + "WebKitCSSMatrix stringifier: Number.MAX_VALUE (2d)", + "WebKitCSSMatrix stringifier: Number.MAX_VALUE (3d)", + "WebKitCSSMatrix stringifier: Number.MIN_VALUE (2d)", + "WebKitCSSMatrix stringifier: Number.MIN_VALUE (3d)", + "WebKitCSSMatrix stringifier: throwing getters (2d)", + "WebKitCSSMatrix stringifier: throwing getters (3d)" + ], + "DOMMatrix2DInit-validate-fixup.html": false, + "DOMMatrixInit-validate-fixup.html": true, + "DOMPoint-001.html": true, + "DOMPoint-002.html": true, + "DOMQuad-001.html": true, + "DOMQuad-002.html": true, + "DOMQuad-nan.html": true, + "DOMRect-001.html": true, + "DOMRect-002.html": true, + "DOMRect-nan.html": true, + "DOMRectList.html": false, + "WebKitCSSMatrix.html": false, + "WebKitCSSMatrix.worker.html": true, + "historical.html": true, + "idlharness.any.html": [ + "DOMPointReadOnly interface: existence and properties of interface object", + "DOMPointReadOnly interface: existence and properties of interface prototype object", + "DOMPoint interface: existence and properties of interface object", + "DOMPoint interface: existence and properties of interface prototype object", + "DOMRectReadOnly interface: existence and properties of interface object", + "DOMRectReadOnly interface: existence and properties of interface prototype object", + "DOMRect interface: existence and properties of interface object", + "DOMRect interface: existence and properties of interface prototype object", + "DOMRectList interface: existence and properties of interface object", + "DOMRectList interface object length", + "DOMRectList interface object name", + "DOMRectList interface: existence and properties of interface prototype object", + "DOMRectList interface: existence and properties of interface prototype object's \"constructor\" property", + "DOMRectList interface: existence and properties of interface prototype object's @@unscopables property", + "DOMRectList interface: attribute length", + "DOMRectList interface: operation item(unsigned long)", + "DOMQuad interface: existence and properties of interface object", + "DOMQuad interface: existence and properties of interface prototype object", + "DOMMatrixReadOnly interface: existence and properties of interface object", + "DOMMatrixReadOnly interface: existence and properties of interface prototype object", + "DOMMatrix interface: existence and properties of interface object", + "DOMMatrix interface: existence and properties of interface prototype object" + ], + "idlharness.any.worker.html": [ + "DOMPointReadOnly interface: existence and properties of interface object", + "DOMPointReadOnly interface: existence and properties of interface prototype object", + "DOMPoint interface: existence and properties of interface object", + "DOMPoint interface: existence and properties of interface prototype object", + "DOMRectReadOnly interface: existence and properties of interface object", + "DOMRectReadOnly interface: existence and properties of interface prototype object", + "DOMRect interface: existence and properties of interface object", + "DOMRect interface: existence and properties of interface prototype object", + "DOMQuad interface: existence and properties of interface object", + "DOMQuad interface: existence and properties of interface prototype object", + "DOMMatrixReadOnly interface: existence and properties of interface object", + "DOMMatrixReadOnly interface: existence and properties of interface prototype object", + "DOMMatrix interface: existence and properties of interface object", + "DOMMatrix interface: existence and properties of interface prototype object" + ], + "spec-examples.html": true, + "structured-serialization.html": [ + "DOMPointReadOnly clone: basic", + "DOMPointReadOnly clone: custom property", + "DOMPointReadOnly clone: non-initial values", + "DOMPoint clone: basic", + "DOMPoint clone: custom property", + "DOMPoint clone: non-initial values", + "DOMRectReadOnly clone: basic", + "DOMRectReadOnly clone: custom property", + "DOMRectReadOnly clone: non-initial values", + "DOMRect clone: basic", + "DOMRect clone: custom property", + "DOMRect clone: non-initial values", + "DOMQuad clone: basic", + "DOMQuad clone: custom property", + "DOMQuad clone: non-initial values", + "DOMMatrixReadOnly clone: basic", + "DOMMatrixReadOnly clone: custom property", + "DOMMatrixReadOnly clone: non-initial values (2d)", + "DOMMatrixReadOnly clone: non-initial values (3d)", + "DOMMatrix clone: basic", + "DOMMatrix clone: custom property", + "DOMMatrix clone: non-initial values (2d)", + "DOMMatrix clone: non-initial values (3d)", + "DOMRectList clone" + ], + "DOMMatrix-invertSelf.html": true + } } } diff --git a/tools/core_import_map.json b/tools/core_import_map.json index f4e749c2898d72..775f71806672d0 100644 --- a/tools/core_import_map.json +++ b/tools/core_import_map.json @@ -519,6 +519,8 @@ "ext:deno_fetch/26_fetch.js": "../ext/fetch/26_fetch.js", "ext:deno_ffi/00_ffi.js": "../ext/ffi/00_ffi.js", "ext:deno_fs/30_fs.js": "../ext/fs/30_fs.js", + "ext:deno_geometry/00_init.js": "../ext/geometry/00_init.js", + "ext:deno_geometry/01_geometry.js": "../ext/geometry/01_geometry.js", "ext:deno_http/00_serve.ts": "../ext/http/00_serve.ts", "ext:deno_http/01_http.js": "../ext/http/01_http.js", "ext:deno_io/12_io.js": "../ext/io/12_io.js", diff --git a/tools/jsdoc_checker.js b/tools/jsdoc_checker.js index 409f1e01d563bb..93e4ed98cfaca6 100755 --- a/tools/jsdoc_checker.js +++ b/tools/jsdoc_checker.js @@ -13,6 +13,7 @@ const libs = [ join(ROOT_PATH, "cli/tsc/dts/lib.deno_webstorage.d.ts"), join(ROOT_PATH, "cli/tsc/dts/lib.deno_canvas.d.ts"), join(ROOT_PATH, "cli/tsc/dts/lib.deno_crypto.d.ts"), + join(ROOT_PATH, "cli/tsc/dts/lib.deno_geometry.d.ts"), join(ROOT_PATH, "cli/tsc/dts/lib.deno_net.d.ts"), join(ROOT_PATH, "cli/tsc/dts/lib.deno.ns.d.ts"), join(ROOT_PATH, "cli/tsc/dts/lib.deno.shared_globals.d.ts"),