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