diff --git a/Cargo.lock b/Cargo.lock index 6a758ce09b2e00..28d0cbe02092ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -204,6 +204,15 @@ version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +[[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.3.2" @@ -1562,6 +1571,14 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "deno_geometry" +version = "0.1.0" +dependencies = [ + "deno_core", + "nalgebra", +] + [[package]] name = "deno_graph" version = "0.81.2" @@ -1918,6 +1935,7 @@ dependencies = [ "deno_fetch", "deno_ffi", "deno_fs", + "deno_geometry", "deno_http", "deno_io", "deno_kv", @@ -4284,6 +4302,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" +[[package]] +name = "matrixmultiply" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +dependencies = [ + "autocfg", + "rawpointer", +] + [[package]] name = "md-5" version = "0.10.6" @@ -4425,6 +4453,21 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "nalgebra" +version = "0.32.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" +dependencies = [ + "approx", + "matrixmultiply", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum", +] + [[package]] name = "napi-build" version = "1.2.1" @@ -4607,6 +4650,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -4633,6 +4685,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.18" @@ -5559,6 +5621,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" @@ -6007,6 +6075,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5" +[[package]] +name = "safe_arch" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" +dependencies = [ + "bytemuck", +] + [[package]] name = "saffron" version = "0.1.0" @@ -6310,6 +6387,19 @@ dependencies = [ "rand_core", ] +[[package]] +name = "simba" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + [[package]] name = "simd-abstraction" version = "0.7.1" @@ -8180,6 +8270,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wide" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901e8597c777fa042e9e245bd56c0dc4418c5db3f845b6ff94fbac732c6a0692" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "widestring" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 076ebdf4f609bf..80a7a4c749763d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ members = [ "ext/fetch", "ext/ffi", "ext/fs", + "ext/geometry", "ext/http", "ext/io", "ext/kv", @@ -71,6 +72,7 @@ deno_crypto = { version = "0.178.0", path = "./ext/crypto" } deno_fetch = { version = "0.188.0", path = "./ext/fetch" } deno_ffi = { version = "0.151.0", path = "./ext/ffi" } deno_fs = { version = "0.74.0", path = "./ext/fs" } +deno_geometry = { version = "0.1.0", path = "./ext/geometry" } deno_http = { version = "0.162.0", path = "./ext/http" } deno_io = { version = "0.74.0", path = "./ext/io" } deno_kv = { version = "0.72.0", path = "./ext/kv" } @@ -199,6 +201,9 @@ zstd = "=0.12.4" hkdf = "0.12.3" rsa = { version = "0.9.3", default-features = false, features = ["std", "pem", "hazmat"] } # hazmat needed for PrehashSigner in ext/node +# geometry +nalgebra = { version = "0.32.4", default-features = false, features = ["std"] } + # webgpu raw-window-handle = "0.6.0" wgpu-core = "0.21.1" @@ -268,6 +273,8 @@ opt-level = 3 opt-level = 3 [profile.bench.package.deno_ffi] opt-level = 3 +[profile.bench.package.deno_geometry] +opt-level = 3 [profile.bench.package.deno_http] opt-level = 3 [profile.bench.package.deno_napi] @@ -336,6 +343,8 @@ opt-level = 3 opt-level = 3 [profile.release.package.deno_crypto] opt-level = 3 +[profile.release.package.deno_geometry] +opt-level = 3 [profile.release.package.deno_fetch] opt-level = 3 [profile.release.package.deno_ffi] diff --git a/cli/build.rs b/cli/build.rs index 4fe6fd1eabaeee..827ba7c4a3433b 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -150,6 +150,7 @@ mod ts { op_crate_libs.insert("deno.url", deno_url::get_declaration()); op_crate_libs.insert("deno.web", deno_web::get_declaration()); op_crate_libs.insert("deno.fetch", deno_fetch::get_declaration()); + op_crate_libs.insert("deno.geometry", deno_geometry::get_declaration()); op_crate_libs.insert("deno.webgpu", deno_webgpu_get_declaration()); op_crate_libs.insert("deno.websocket", deno_websocket::get_declaration()); op_crate_libs.insert("deno.webstorage", deno_webstorage::get_declaration()); diff --git a/cli/tsc/dts/lib.deno.shared_globals.d.ts b/cli/tsc/dts/lib.deno.shared_globals.d.ts index 1521cf12de0491..778c28d073fe90 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/mod.rs b/cli/tsc/mod.rs index ac7fc48e37516c..69bd47ce5b5c54 100644 --- a/cli/tsc/mod.rs +++ b/cli/tsc/mod.rs @@ -96,6 +96,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", diff --git a/ext/geometry/00_init.js b/ext/geometry/00_init.js new file mode 100644 index 00000000000000..d1b89bac5cadc6 --- /dev/null +++ b/ext/geometry/00_init.js @@ -0,0 +1,27 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +import { core } from "ext:core/mod.js"; + +const lazyLoad = core.createLazyLoader("ext:deno_geometry/01_geometry.js"); + +let geometry; + +/** + * @param {(transformList: string, prefix: string) => { matrix: Float64Array, is2D: boolean }} transformListParser + * @param {boolean} enableWindowFeatures + */ +export function createGeometryLoader( + transformListParser, + enableWindowFeatures, +) { + return () => { + if (geometry !== undefined) { + return geometry; + } + + geometry = lazyLoad(); + geometry.init(transformListParser, enableWindowFeatures); + + return geometry; + }; +} diff --git a/ext/geometry/01_geometry.js b/ext/geometry/01_geometry.js new file mode 100644 index 00000000000000..8b5957ee4e2610 --- /dev/null +++ b/ext/geometry/01_geometry.js @@ -0,0 +1,2117 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +import { primordials } from "ext:core/mod.js"; +import { + op_geometry_flip_x_self, + op_geometry_flip_y_self, + op_geometry_invert_2d_self, + op_geometry_invert_self, + op_geometry_multiply, + op_geometry_multiply_self, + op_geometry_premultiply_point_self, + op_geometry_premultiply_self, + op_geometry_rotate_axis_angle_self, + op_geometry_rotate_from_vector_self, + op_geometry_rotate_self, + op_geometry_scale_self, + op_geometry_scale_with_origin_self, + op_geometry_skew_self, + op_geometry_translate_self, +} from "ext:core/ops"; +const { + ArrayPrototypeJoin, + Float32Array, + Float64Array, + MathMax, + MathMin, + NumberIsFinite, + ObjectDefineProperty, + ObjectIs, + ObjectPrototypeIsPrototypeOf, + Symbol, + SymbolFor, + SymbolIterator, + TypeError, + TypedArrayPrototypeEvery, + TypedArrayPrototypeJoin, +} = primordials; + +import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; +import * as webidl from "ext:deno_webidl/00_webidl.js"; +import { DOMException } from "ext:deno_web/01_dom_exception.js"; + +webidl.converters.DOMPointInit = webidl.createDictionaryConverter( + "DOMPointInit", + [ + { + key: "x", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "y", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "z", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "w", + converter: webidl.converters["unrestricted double"], + defaultValue: 1, + }, + ], +); + +webidl.converters.DOMRectInit = webidl.createDictionaryConverter( + "DOMRectInit", + [ + { + key: "x", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "y", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "width", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "height", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + ], +); + +webidl.converters.DOMQuadInit = webidl.createDictionaryConverter( + "DOMQuadInit", + [ + { + key: "p1", + converter: webidl.converters.DOMPointInit, + }, + { + key: "p2", + converter: webidl.converters.DOMPointInit, + }, + { + key: "p3", + converter: webidl.converters.DOMPointInit, + }, + { + key: "p4", + converter: webidl.converters.DOMPointInit, + }, + ], +); + +/** @type {webidl.Dictionary} */ +const dictDOMMatrix2DInit = [ + { + key: "a", + converter: webidl.converters["unrestricted double"], + }, + { + key: "b", + converter: webidl.converters["unrestricted double"], + }, + { + key: "c", + converter: webidl.converters["unrestricted double"], + }, + { + key: "d", + converter: webidl.converters["unrestricted double"], + }, + { + key: "e", + converter: webidl.converters["unrestricted double"], + }, + { + key: "f", + converter: webidl.converters["unrestricted double"], + }, + { + key: "m11", + converter: webidl.converters["unrestricted double"], + }, + { + key: "m12", + converter: webidl.converters["unrestricted double"], + }, + { + key: "m21", + converter: webidl.converters["unrestricted double"], + }, + { + key: "m22", + converter: webidl.converters["unrestricted double"], + }, + { + key: "m41", + converter: webidl.converters["unrestricted double"], + }, + { + key: "m42", + converter: webidl.converters["unrestricted double"], + }, +]; + +webidl.converters.DOMMatrix2DInit = webidl.createDictionaryConverter( + "DOMMatrix2DInit", + dictDOMMatrix2DInit, +); + +webidl.converters.DOMMatrixInit = webidl.createDictionaryConverter( + "DOMMatrixInit", + dictDOMMatrix2DInit, + [ + { + key: "m13", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "m14", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "m23", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "m24", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "m31", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "m32", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "m33", + converter: webidl.converters["unrestricted double"], + defaultValue: 1, + }, + { + key: "m34", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "m43", + converter: webidl.converters["unrestricted double"], + defaultValue: 0, + }, + { + key: "m44", + converter: webidl.converters["unrestricted double"], + defaultValue: 1, + }, + { + key: "is2D", + converter: webidl.converters["boolean"], + }, + ], +); + +const _raw = Symbol("[[raw]]"); +// Property to prevent writing values when an immutable instance is changed to +// a mutable instance by Object.setPrototypeOf +// TODO(petamoriken): Implementing resistance to Object.setPrototypeOf in the WebIDL layer +const _writable = Symbol("[[writable]]"); +const _brand = webidl.brand; + +class DOMPointReadOnly { + [_writable] = false; + /** @type {Float64Array} */ + [_raw]; + + constructor(x = 0, y = 0, z = 0, w = 1) { + this[_raw] = new Float64Array([ + webidl.converters["unrestricted double"](x), + webidl.converters["unrestricted double"](y), + webidl.converters["unrestricted double"](z), + webidl.converters["unrestricted double"](w), + ]); + this[_brand] = _brand; + } + + static fromPoint(other = {}) { + other = webidl.converters.DOMPointInit( + other, + "Failed to execute 'DOMPointReadOnly.fromPoint'", + "Argument 1", + ); + const point = webidl.createBranded(DOMPointReadOnly); + point[_writable] = false; + point[_raw] = new Float64Array([ + other.x, + other.y, + other.z, + other.w, + ]); + return point; + } + + get x() { + webidl.assertBranded(this, DOMPointReadOnlyPrototype); + return this[_raw][0]; + } + get y() { + webidl.assertBranded(this, DOMPointReadOnlyPrototype); + return this[_raw][1]; + } + get z() { + webidl.assertBranded(this, DOMPointReadOnlyPrototype); + return this[_raw][2]; + } + get w() { + webidl.assertBranded(this, DOMPointReadOnlyPrototype); + return this[_raw][3]; + } + + matrixTransform(matrix = {}) { + webidl.assertBranded(this, DOMPointReadOnlyPrototype); + const prefix = "Failed to execute 'matrixTransform' on 'DOMPointReadOnly'"; + if (!ObjectPrototypeIsPrototypeOf(DOMMatrixReadOnlyPrototype, matrix)) { + const _matrix = webidl.converters.DOMMatrixInit( + matrix, + prefix, + "Argument 1", + ); + validateAndFixupMatrixDictionary(_matrix, prefix); + matrix = {}; + initMatrixFromDictonary(matrix, _matrix); + } + + const point = webidl.createBranded(DOMPoint); + point[_writable] = true; + point[_raw] = new Float64Array(this[_raw]); + op_geometry_premultiply_point_self(matrix[_raw], point[_raw]); + return point; + } + + toJSON() { + webidl.assertBranded(this, DOMPointReadOnlyPrototype); + const raw = this[_raw]; + return { + x: raw[0], + y: raw[1], + z: raw[2], + w: raw[3], + }; + } + + [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf(DOMPointReadOnlyPrototype, this), + keys: [ + "x", + "y", + "z", + "w", + ], + }), + inspectOptions, + ); + } +} + +webidl.configureInterface(DOMPointReadOnly); +const DOMPointReadOnlyPrototype = DOMPointReadOnly.prototype; + +class DOMPoint extends DOMPointReadOnly { + [_writable] = true; + + static fromPoint(other = {}) { + other = webidl.converters.DOMPointInit( + other, + "Failed to execute 'DOMPoint.fromPoint'", + "Argument 1", + ); + const point = webidl.createBranded(DOMPoint); + point[_writable] = true; + point[_raw] = new Float64Array([ + other.x, + other.y, + other.z, + other.w, + ]); + return point; + } + + get x() { + webidl.assertBranded(this, DOMPointPrototype); + return this[_raw][0]; + } + set x(value) { + webidl.assertBranded(this, DOMPointPrototype); + assertWritable(this); + this[_raw][0] = webidl.converters["unrestricted double"](value); + } + get y() { + webidl.assertBranded(this, DOMPointPrototype); + return this[_raw][1]; + } + set y(value) { + webidl.assertBranded(this, DOMPointPrototype); + assertWritable(this); + this[_raw][1] = webidl.converters["unrestricted double"](value); + } + get z() { + webidl.assertBranded(this, DOMPointPrototype); + return this[_raw][2]; + } + set z(value) { + webidl.assertBranded(this, DOMPointPrototype); + assertWritable(this); + this[_raw][2] = webidl.converters["unrestricted double"](value); + } + get w() { + webidl.assertBranded(this, DOMPointPrototype); + return this[_raw][3]; + } + set w(value) { + webidl.assertBranded(this, DOMPointPrototype); + assertWritable(this); + this[_raw][3] = webidl.converters["unrestricted double"](value); + } + + [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf(DOMPointPrototype, this), + keys: [ + "x", + "y", + "z", + "w", + ], + }), + inspectOptions, + ); + } +} + +webidl.configureInterface(DOMPoint); +const DOMPointPrototype = DOMPoint.prototype; + +class DOMRectReadOnly { + [_writable] = false; + /** @type {Float64Array} */ + [_raw]; + + constructor(x = 0, y = 0, width = 0, height = 0) { + this[_raw] = new Float64Array([ + webidl.converters["unrestricted double"](x), + webidl.converters["unrestricted double"](y), + webidl.converters["unrestricted double"](width), + webidl.converters["unrestricted double"](height), + ]); + this[_brand] = _brand; + } + + static fromRect(other = {}) { + other = webidl.converters.DOMRectInit( + other, + "Failed to execute 'DOMRectReadOnly.fromRect'", + "Argument 1", + ); + const rect = webidl.createBranded(DOMRectReadOnly); + rect[_writable] = false; + rect[_raw] = new Float64Array([ + other.x, + other.y, + other.width, + other.height, + ]); + return rect; + } + + get x() { + webidl.assertBranded(this, DOMRectReadOnlyPrototype); + return this[_raw][0]; + } + get y() { + webidl.assertBranded(this, DOMRectReadOnlyPrototype); + return this[_raw][1]; + } + get width() { + webidl.assertBranded(this, DOMRectReadOnlyPrototype); + return this[_raw][2]; + } + get height() { + webidl.assertBranded(this, DOMRectReadOnlyPrototype); + return this[_raw][3]; + } + get top() { + webidl.assertBranded(this, DOMRectReadOnlyPrototype); + const raw = this[_raw]; + return MathMin(raw[1], raw[1] + raw[3]); + } + get right() { + webidl.assertBranded(this, DOMRectReadOnlyPrototype); + const raw = this[_raw]; + return MathMax(raw[0], raw[0] + raw[2]); + } + get bottom() { + webidl.assertBranded(this, DOMRectReadOnlyPrototype); + const raw = this[_raw]; + return MathMax(raw[1], raw[1] + raw[3]); + } + get left() { + webidl.assertBranded(this, DOMRectReadOnlyPrototype); + const raw = this[_raw]; + return MathMin(raw[0], raw[0] + raw[2]); + } + + toJSON() { + webidl.assertBranded(this, DOMRectReadOnlyPrototype); + const raw = this[_raw]; + return { + x: raw[0], + y: raw[1], + width: raw[2], + height: raw[3], + top: MathMin(raw[1], raw[1] + raw[3]), + right: MathMax(raw[0], raw[0] + raw[2]), + bottom: MathMax(raw[1], raw[1] + raw[3]), + left: MathMin(raw[0], raw[0] + raw[2]), + }; + } + + [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf(DOMRectReadOnlyPrototype, this), + keys: [ + "x", + "y", + "width", + "height", + "top", + "right", + "bottom", + "left", + ], + }), + inspectOptions, + ); + } +} + +webidl.configureInterface(DOMRectReadOnly); +const DOMRectReadOnlyPrototype = DOMRectReadOnly.prototype; + +class DOMRect extends DOMRectReadOnly { + [_writable] = true; + + static fromRect(other = {}) { + other = webidl.converters.DOMRectInit( + other, + "Failed to execute 'DOMRect.fromRect'", + "Argument 1", + ); + const rect = webidl.createBranded(DOMRect); + rect[_writable] = true; + rect[_raw] = new Float64Array([ + other.x, + other.y, + other.width, + other.height, + ]); + return rect; + } + + get x() { + webidl.assertBranded(this, DOMRectPrototype); + return this[_raw][0]; + } + set x(value) { + webidl.assertBranded(this, DOMRectPrototype); + assertWritable(this); + this[_raw][0] = webidl.converters["unrestricted double"](value); + } + get y() { + webidl.assertBranded(this, DOMRectPrototype); + return this[_raw][1]; + } + set y(value) { + webidl.assertBranded(this, DOMRectPrototype); + assertWritable(this); + this[_raw][1] = webidl.converters["unrestricted double"](value); + } + get width() { + webidl.assertBranded(this, DOMRectPrototype); + return this[_raw][2]; + } + set width(value) { + webidl.assertBranded(this, DOMRectPrototype); + assertWritable(this); + this[_raw][2] = webidl.converters["unrestricted double"](value); + } + get height() { + webidl.assertBranded(this, DOMRectPrototype); + return this[_raw][3]; + } + set height(value) { + webidl.assertBranded(this, DOMRectPrototype); + assertWritable(this); + this[_raw][3] = webidl.converters["unrestricted double"](value); + } + + [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf(DOMRectPrototype, this), + keys: [ + "x", + "y", + "width", + "height", + "top", + "right", + "bottom", + "left", + ], + }), + inspectOptions, + ); + } +} + +webidl.configureInterface(DOMRect); +const DOMRectPrototype = DOMRect.prototype; + +const _p1 = Symbol("[[p1]]"); +const _p2 = Symbol("[[p2]]"); +const _p3 = Symbol("[[p3]]"); +const _p4 = Symbol("[[p4]]"); + +class DOMQuad { + /** @type {DOMPoint} */ + [_p1]; + /** @type {DOMPoint} */ + [_p2]; + /** @type {DOMPoint} */ + [_p3]; + /** @type {DOMPoint} */ + [_p4]; + + constructor(p1 = {}, p2 = {}, p3 = {}, p4 = {}) { + this[_p1] = DOMPoint.fromPoint(p1); + this[_p2] = DOMPoint.fromPoint(p2); + this[_p3] = DOMPoint.fromPoint(p3); + this[_p4] = DOMPoint.fromPoint(p4); + this[_brand] = _brand; + } + + static fromRect(other = {}) { + other = webidl.converters.DOMRectInit( + other, + "Failed to execute 'DOMQuad.fromRect'", + "Argument 1", + ); + const { x, y, width, height } = other; + const quad = webidl.createBranded(DOMQuad); + quad[_p1] = new DOMPoint(x, y, 0, 1); + quad[_p2] = new DOMPoint(x + width, y, 0, 1); + quad[_p3] = new DOMPoint(x + width, y + height, 0, 1); + quad[_p4] = new DOMPoint(x, y + height, 0, 1); + return quad; + } + + static fromQuad(other = {}) { + other = webidl.converters.DOMQuadInit( + other, + "Failed to execute 'DOMQuad.fromQuad'", + "Argument 1", + ); + const quad = webidl.createBranded(DOMQuad); + quad[_p1] = DOMPoint.fromPoint(other.p1); + quad[_p2] = DOMPoint.fromPoint(other.p2); + quad[_p3] = DOMPoint.fromPoint(other.p3); + quad[_p4] = DOMPoint.fromPoint(other.p4); + return quad; + } + + get p1() { + webidl.assertBranded(this, DOMQuadPrototype); + return this[_p1]; + } + get p2() { + webidl.assertBranded(this, DOMQuadPrototype); + return this[_p2]; + } + get p3() { + webidl.assertBranded(this, DOMQuadPrototype); + return this[_p3]; + } + get p4() { + webidl.assertBranded(this, DOMQuadPrototype); + return this[_p4]; + } + + getBounds() { + webidl.assertBranded(this, DOMQuadPrototype); + const { x: p1x, y: p1y } = this[_p1]; + const { x: p2x, y: p2y } = this[_p2]; + const { x: p3x, y: p3y } = this[_p3]; + const { x: p4x, y: p4y } = this[_p4]; + + const left = MathMin(p1x, p2x, p3x, p4x); + const top = MathMin(p1y, p2y, p3y, p4y); + const right = MathMax(p1x, p2x, p3x, p4x); + const bottom = MathMax(p1y, p2y, p3y, p4y); + + const bounds = webidl.createBranded(DOMRect); + bounds[_writable] = true; + bounds[_raw] = new Float64Array([ + left, + top, + right - left, + bottom - top, + ]); + return bounds; + } + + toJSON() { + webidl.assertBranded(this, DOMQuadPrototype); + return { + p1: this[_p1], + p2: this[_p2], + p3: this[_p3], + p4: this[_p4], + }; + } + + [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf(DOMQuadPrototype, this), + keys: [ + "p1", + "p2", + "p3", + "p4", + ], + }), + inspectOptions, + ); + } +} + +webidl.configureInterface(DOMQuad); +const DOMQuadPrototype = DOMQuad.prototype; + +/* + * 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 = 0; +const INDEX_B = 1; +const INDEX_C = 4; +const INDEX_D = 5; +const INDEX_E = 12; +const INDEX_F = 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 = 0; +const INDEX_M12 = 1; +const INDEX_M13 = 2; +const INDEX_M14 = 3; +const INDEX_M21 = 4; +const INDEX_M22 = 5; +const INDEX_M23 = 6; +const INDEX_M24 = 7; +const INDEX_M31 = 8; +const INDEX_M32 = 9; +const INDEX_M33 = 10; +const INDEX_M34 = 11; +const INDEX_M41 = 12; +const INDEX_M42 = 13; +const INDEX_M43 = 14; +const INDEX_M44 = 15; + +const _is2D = Symbol("[[is2D]]"); + +class DOMMatrixReadOnly { + [_writable] = false; + /** @type {Float64Array} */ + [_raw]; + /** @type {boolean} */ + [_is2D]; + + constructor(init = undefined) { + const prefix = `Failed to construct '${this.constructor.name}'`; + this[_brand] = _brand; + if (init === undefined) { + // deno-fmt-ignore + this[_raw] = new Float64Array([ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + ]); + this[_is2D] = true; + } else if ( + webidl.type(init) === "Object" && init[SymbolIterator] !== undefined + ) { + init = webidl.converters["sequence"]( + init, + prefix, + "Argument 1", + ); + initMatrixFromSequence(this, init, prefix); + } else { + init = webidl.converters.DOMString( + init, + prefix, + "Argument 1", + ); + const { matrix, is2D } = parseTransformList(init, prefix); + this[_raw] = matrix; + this[_is2D] = is2D; + } + } + + static fromMatrix(other = {}) { + const prefix = "Failed to execute 'DOMMatrixReadOnly.fromMatrix'"; + const matrix = webidl.createBranded(DOMMatrixReadOnly); + matrix[_writable] = false; + // fast path for DOMMatrix or DOMMatrixReadOnly + if (ObjectPrototypeIsPrototypeOf(DOMMatrixReadOnlyPrototype, other)) { + initMatrixFromMatrix(matrix, other); + } else { + other = webidl.converters.DOMMatrixInit(other, prefix, "Argument 1"); + validateAndFixupMatrixDictionary(other, prefix); + initMatrixFromDictonary(matrix, other); + } + return matrix; + } + + static fromFloat32Array(float32) { + const prefix = "Failed to execute 'DOMMatrixReadOnly.fromFloat32Array'"; + webidl.requiredArguments(arguments.length, 1, prefix); + float32 = webidl.converters.Float32Array(float32, prefix, "Argument 1"); + const matrix = webidl.createBranded(DOMMatrixReadOnly); + matrix[_writable] = false; + initMatrixFromSequence(matrix, float32, prefix); + return matrix; + } + + static fromFloat64Array(float64) { + const prefix = "Failed to execute 'DOMMatrixReadOnly.fromFloat64Array'"; + webidl.requiredArguments(arguments.length, 1, prefix); + float64 = webidl.converters.Float64Array(float64, prefix, "Argument 1"); + const matrix = webidl.createBranded(DOMMatrixReadOnly); + matrix[_writable] = false; + initMatrixFromSequence(matrix, float64, prefix); + return matrix; + } + + get a() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_A]; + } + get b() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_B]; + } + get c() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_C]; + } + get d() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_D]; + } + get e() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_E]; + } + get f() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_F]; + } + get m11() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M11]; + } + get m12() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M12]; + } + get m13() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M13]; + } + get m14() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M14]; + } + get m21() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M21]; + } + get m22() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M22]; + } + get m23() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M23]; + } + get m24() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M24]; + } + get m31() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M31]; + } + get m32() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M32]; + } + get m33() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M33]; + } + get m34() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M34]; + } + get m41() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M41]; + } + get m42() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M42]; + } + get m43() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M43]; + } + get m44() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_raw][INDEX_M44]; + } + get is2D() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return this[_is2D]; + } + get isIdentity() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return isIdentityMatrix(this); + } + + translate(tx = 0, ty = 0, tz = 0) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + tx = webidl.converters["unrestricted double"](tx); + ty = webidl.converters["unrestricted double"](ty); + tz = webidl.converters["unrestricted double"](tz); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + op_geometry_translate_self( + tx, + ty, + tz, + matrix[_raw], + ); + matrix[_is2D] = this[_is2D] && tz === 0; + return matrix; + } + + scale( + scaleX = 1, + scaleY = scaleX, + scaleZ = 1, + originX = 0, + originY = 0, + originZ = 0, + ) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + scaleX = webidl.converters["unrestricted double"](scaleX); + scaleY = webidl.converters["unrestricted double"](scaleY); + scaleZ = webidl.converters["unrestricted double"](scaleZ); + originX = webidl.converters["unrestricted double"](originX); + originY = webidl.converters["unrestricted double"](originY); + originZ = webidl.converters["unrestricted double"](originZ); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + if (originX === 0 && originY === 0 && originZ === 0) { + op_geometry_scale_self( + scaleX, + scaleY, + scaleZ, + matrix[_raw], + ); + } else { + op_geometry_scale_with_origin_self( + scaleX, + scaleY, + scaleZ, + originX, + originY, + originZ, + matrix[_raw], + ); + } + matrix[_is2D] = this[_is2D] && scaleZ === 1 && originZ === 0; + return matrix; + } + + scaleNonUniform(scaleX = 1, scaleY = 1) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + scaleX = webidl.converters["unrestricted double"](scaleX); + scaleY = webidl.converters["unrestricted double"](scaleY); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + op_geometry_scale_self( + scaleX, + scaleY, + 1, + matrix[_raw], + ); + matrix[_is2D] = this[_is2D]; + return matrix; + } + + scale3d(scale = 1, originX = 0, originY = 0, originZ = 0) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + scale = webidl.converters["unrestricted double"](scale); + originX = webidl.converters["unrestricted double"](originX); + originY = webidl.converters["unrestricted double"](originY); + originZ = webidl.converters["unrestricted double"](originZ); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + if (originX === 0 && originY === 0 && originZ === 0) { + op_geometry_scale_self( + scale, + scale, + scale, + matrix[_raw], + ); + } else { + op_geometry_scale_with_origin_self( + scale, + scale, + scale, + originX, + originY, + originZ, + matrix[_raw], + ); + } + matrix[_is2D] = this[_is2D] && scale === 1 && originZ === 0; + return matrix; + } + + rotate(rotX = 0, rotY, rotZ) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + rotX = webidl.converters["unrestricted double"](rotX); + if (rotY === undefined && rotZ === undefined) { + rotZ = rotX; + rotX = 0; + rotY = 0; + } else { + rotY = rotY !== undefined + ? webidl.converters["unrestricted double"](rotY) + : 0; + rotZ = rotZ !== undefined + ? webidl.converters["unrestricted double"](rotZ) + : 0; + } + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + op_geometry_rotate_self( + rotX, + rotY, + rotZ, + matrix[_raw], + ); + matrix[_is2D] = this[_is2D] && rotX === 0 && rotY === 0; + return matrix; + } + + rotateFromVector(x = 0, y = 0) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + x = webidl.converters["unrestricted double"](x); + y = webidl.converters["unrestricted double"](y); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + op_geometry_rotate_from_vector_self( + x, + y, + matrix[_raw], + ); + matrix[_is2D] = this[_is2D]; + return matrix; + } + + rotateAxisAngle(x = 0, y = 0, z = 0, angle = 0) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + x = webidl.converters["unrestricted double"](x); + y = webidl.converters["unrestricted double"](y); + z = webidl.converters["unrestricted double"](z); + angle = webidl.converters["unrestricted double"](angle); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + if (x !== 0 || y !== 0 || z !== 0) { + op_geometry_rotate_axis_angle_self( + x, + y, + z, + angle, + matrix[_raw], + ); + } + matrix[_is2D] = this[_is2D] && x === 0 && y === 0; + return matrix; + } + + skewX(sx = 0) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + sx = webidl.converters["unrestricted double"](sx); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + op_geometry_skew_self( + sx, + 0, + matrix[_raw], + ); + matrix[_is2D] = this[_is2D]; + return matrix; + } + + skewY(sy = 0) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + sy = webidl.converters["unrestricted double"](sy); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + op_geometry_skew_self( + 0, + sy, + matrix[_raw], + ); + matrix[_is2D] = this[_is2D]; + return matrix; + } + + multiply(other = {}) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + const prefix = "Failed to execute 'multiply' on 'DOMMatrixReadOnly'"; + if (!ObjectPrototypeIsPrototypeOf(DOMMatrixReadOnlyPrototype, other)) { + const _other = webidl.converters.DOMMatrixInit( + other, + prefix, + "Argument 1", + ); + validateAndFixupMatrixDictionary(_other, prefix); + other = {}; + initMatrixFromDictonary(other, _other); + } + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(16); + op_geometry_multiply(this[_raw], other[_raw], matrix[_raw]); + matrix[_is2D] = this[_is2D] && other[_is2D]; + return matrix; + } + + flipX() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + op_geometry_flip_x_self(matrix[_raw]); + matrix[_is2D] = this[_is2D]; + return matrix; + } + + flipY() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + op_geometry_flip_y_self(matrix[_raw]); + matrix[_is2D] = this[_is2D]; + return matrix; + } + + inverse() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + matrix[_raw] = new Float64Array(this[_raw]); + let invertible; + if (this[_is2D]) { + invertible = op_geometry_invert_2d_self(matrix[_raw]); + } else { + invertible = op_geometry_invert_self(matrix[_raw]); + } + matrix[_is2D] = this[_is2D] && invertible; + return matrix; + } + + transformPoint(point = {}) { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + point = webidl.converters.DOMPointInit( + point, + "Failed to execute 'transformPoint' on 'DOMMatrixReadOnly'", + "Argument 1", + ); + const result = webidl.createBranded(DOMPoint); + result[_writable] = true; + result[_raw] = new Float64Array([ + point.x, + point.y, + point.z, + point.w, + ]); + op_geometry_premultiply_point_self(this[_raw], result[_raw]); + return result; + } + + toFloat32Array() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return new Float32Array(this[_raw]); + } + + toFloat64Array() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + return new Float64Array(this[_raw]); + } + + toJSON() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + const raw = this[_raw]; + return { + a: raw[INDEX_A], + b: raw[INDEX_B], + c: raw[INDEX_C], + d: raw[INDEX_D], + e: raw[INDEX_E], + f: raw[INDEX_F], + m11: raw[INDEX_M11], + m12: raw[INDEX_M12], + m13: raw[INDEX_M13], + m14: raw[INDEX_M14], + m21: raw[INDEX_M21], + m22: raw[INDEX_M22], + m23: raw[INDEX_M23], + m24: raw[INDEX_M24], + m31: raw[INDEX_M31], + m32: raw[INDEX_M32], + m33: raw[INDEX_M33], + m34: raw[INDEX_M34], + m41: raw[INDEX_M41], + m42: raw[INDEX_M42], + m43: raw[INDEX_M43], + m44: raw[INDEX_M44], + is2D: this[_is2D], + isIdentity: isIdentityMatrix(this), + }; + } + + [SymbolFor("Deno.privateCustomInspect")](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, + ); + } +} + +webidl.configureInterface(DOMMatrixReadOnly); +const DOMMatrixReadOnlyPrototype = DOMMatrixReadOnly.prototype; + +class DOMMatrix extends DOMMatrixReadOnly { + [_writable] = true; + + static fromMatrix(other = {}) { + const prefix = "Failed to execute 'DOMMatrix.fromMatrix'"; + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + // fast path for DOMMatrix or DOMMatrixReadOnly + if (ObjectPrototypeIsPrototypeOf(DOMMatrixReadOnlyPrototype, other)) { + initMatrixFromMatrix(matrix, other); + } else { + other = webidl.converters.DOMMatrixInit(other, prefix, "Argument 1"); + validateAndFixupMatrixDictionary(other, prefix); + initMatrixFromDictonary(matrix, other); + } + return matrix; + } + + static fromFloat32Array(float32) { + const prefix = "Failed to execute 'DOMMatrix.fromFloat32Array'"; + webidl.requiredArguments(arguments.length, 1, prefix); + float32 = webidl.converters.Float32Array(float32, prefix, "Argument 1"); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + initMatrixFromSequence(matrix, float32, prefix); + return matrix; + } + + static fromFloat64Array(float64) { + const prefix = "Failed to execute 'DOMMatrix.fromFloat64Array'"; + webidl.requiredArguments(arguments.length, 1, prefix); + float64 = webidl.converters.Float64Array(float64, prefix, "Argument 1"); + const matrix = webidl.createBranded(DOMMatrix); + matrix[_writable] = true; + initMatrixFromSequence(matrix, float64, prefix); + return matrix; + } + + get a() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_A]; + } + set a(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_A] = webidl.converters["unrestricted double"](value); + } + get b() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_B]; + } + set b(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_B] = webidl.converters["unrestricted double"](value); + } + get c() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_C]; + } + set c(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_C] = webidl.converters["unrestricted double"](value); + } + get d() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_D]; + } + set d(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_D] = webidl.converters["unrestricted double"](value); + } + get e() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_E]; + } + set e(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_E] = webidl.converters["unrestricted double"](value); + } + get f() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_F]; + } + set f(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_F] = webidl.converters["unrestricted double"](value); + } + get m11() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M11]; + } + set m11(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_M11] = webidl.converters["unrestricted double"](value); + } + get m12() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M12]; + } + set m12(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_M12] = webidl.converters["unrestricted double"](value); + } + get m13() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M13]; + } + set m13(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + if (value !== 0) { + this[_is2D] = false; + } + this[_raw][INDEX_M13] = webidl.converters["unrestricted double"](value); + } + get m14() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M14]; + } + set m14(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + if (value !== 0) { + this[_is2D] = false; + } + this[_raw][INDEX_M14] = webidl.converters["unrestricted double"](value); + } + get m21() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M21]; + } + set m21(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_M21] = webidl.converters["unrestricted double"](value); + } + get m22() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M22]; + } + set m22(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_M22] = webidl.converters["unrestricted double"](value); + } + get m23() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M23]; + } + set m23(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + if (value !== 0) { + this[_is2D] = false; + } + this[_raw][INDEX_M23] = webidl.converters["unrestricted double"](value); + } + get m24() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M24]; + } + set m24(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + if (value !== 0) { + this[_is2D] = false; + } + this[_raw][INDEX_M24] = webidl.converters["unrestricted double"](value); + } + get m31() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M31]; + } + set m31(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + if (value !== 0) { + this[_is2D] = false; + } + this[_raw][INDEX_M31] = webidl.converters["unrestricted double"](value); + } + get m32() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M32]; + } + set m32(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + if (value !== 0) { + this[_is2D] = false; + } + this[_raw][INDEX_M32] = webidl.converters["unrestricted double"](value); + } + get m33() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M33]; + } + set m33(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + if (value !== 1) { + this[_is2D] = false; + } + this[_raw][INDEX_M33] = webidl.converters["unrestricted double"](value); + } + get m34() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M34]; + } + set m34(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + if (value !== 0) { + this[_is2D] = false; + } + this[_raw][INDEX_M34] = webidl.converters["unrestricted double"](value); + } + get m41() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M41]; + } + set m41(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_M41] = webidl.converters["unrestricted double"](value); + } + get m42() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M42]; + } + set m42(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + this[_raw][INDEX_M42] = webidl.converters["unrestricted double"](value); + } + get m43() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M43]; + } + set m43(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + if (value !== 0) { + this[_is2D] = false; + } + this[_raw][INDEX_M43] = webidl.converters["unrestricted double"](value); + } + get m44() { + webidl.assertBranded(this, DOMMatrixPrototype); + return this[_raw][INDEX_M44]; + } + set m44(value) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + if (value !== 1) { + this[_is2D] = false; + } + this[_raw][INDEX_M44] = webidl.converters["unrestricted double"](value); + } + + multiplySelf(other = {}) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + const prefix = "Failed to execute 'multiplySelf' on 'DOMMatrix'"; + if (!ObjectPrototypeIsPrototypeOf(DOMMatrixReadOnlyPrototype, other)) { + const _other = webidl.converters.DOMMatrixInit( + other, + prefix, + "Argument 1", + ); + validateAndFixupMatrixDictionary(_other, prefix); + other = {}; + initMatrixFromDictonary(other, _other); + } else if (this[_raw] === other[_raw]) { + other = {}; + initMatrixFromMatrix(other, this); + } + + op_geometry_multiply_self(other[_raw], this[_raw]); + this[_is2D] &&= other[_is2D]; + return this; + } + + preMultiplySelf(other = {}) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + const prefix = "Failed to execute 'premultiplySelf' on 'DOMMatrix'"; + if (!ObjectPrototypeIsPrototypeOf(DOMMatrixReadOnlyPrototype, other)) { + const _other = webidl.converters.DOMMatrixInit( + other, + prefix, + "Argument 1", + ); + validateAndFixupMatrixDictionary(_other, prefix); + other = {}; + initMatrixFromDictonary(other, _other); + } else if (this[_raw] === other[_raw]) { + other = {}; + initMatrixFromMatrix(other, this); + } + + op_geometry_premultiply_self(other[_raw], this[_raw]); + this[_is2D] &&= other[_is2D]; + return this; + } + + translateSelf(tx = 0, ty = 0, tz = 0) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + tx = webidl.converters["unrestricted double"](tx); + ty = webidl.converters["unrestricted double"](ty); + tz = webidl.converters["unrestricted double"](tz); + op_geometry_translate_self( + tx, + ty, + tz, + this[_raw], + ); + this[_is2D] &&= tz === 0; + return this; + } + + scaleSelf( + scaleX = 1, + scaleY = scaleX, + scaleZ = 1, + originX = 0, + originY = 0, + originZ = 0, + ) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + scaleX = webidl.converters["unrestricted double"](scaleX); + scaleY = webidl.converters["unrestricted double"](scaleY); + scaleZ = webidl.converters["unrestricted double"](scaleZ); + originX = webidl.converters["unrestricted double"](originX); + originY = webidl.converters["unrestricted double"](originY); + originZ = webidl.converters["unrestricted double"](originZ); + if (originX === 0 && originY === 0 && originZ === 0) { + op_geometry_scale_self( + scaleX, + scaleY, + scaleZ, + this[_raw], + ); + } else { + op_geometry_scale_with_origin_self( + scaleX, + scaleY, + scaleZ, + originX, + originY, + originZ, + this[_raw], + ); + } + this[_is2D] &&= scaleZ === 1 && originZ === 0; + return this; + } + + scale3dSelf(scale = 1, originX = 0, originY = 0, originZ = 0) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + scale = webidl.converters["unrestricted double"](scale); + originX = webidl.converters["unrestricted double"](originX); + originY = webidl.converters["unrestricted double"](originY); + originZ = webidl.converters["unrestricted double"](originZ); + if (originX === 0 && originY === 0 && originZ === 0) { + op_geometry_scale_self( + scale, + scale, + scale, + this[_raw], + ); + } else { + op_geometry_scale_with_origin_self( + scale, + scale, + scale, + originX, + originY, + originZ, + this[_raw], + ); + } + this[_is2D] &&= scale === 1 && originZ === 0; + return this; + } + + rotateSelf(rotX = 0, rotY, rotZ) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + rotX = webidl.converters["unrestricted double"](rotX); + if (rotY === undefined && rotZ === undefined) { + rotZ = rotX; + rotX = 0; + rotY = 0; + } else { + rotY = rotY !== undefined + ? webidl.converters["unrestricted double"](rotY) + : 0; + rotZ = rotZ !== undefined + ? webidl.converters["unrestricted double"](rotZ) + : 0; + } + op_geometry_rotate_self( + rotX, + rotY, + rotZ, + this[_raw], + ); + this[_is2D] &&= rotX === 0 && rotY === 0; + return this; + } + + rotateFromVectorSelf(x = 0, y = 0) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + x = webidl.converters["unrestricted double"](x); + y = webidl.converters["unrestricted double"](y); + op_geometry_rotate_from_vector_self( + x, + y, + this[_raw], + ); + return this; + } + + rotateAxisAngleSelf(x = 0, y = 0, z = 0, angle = 0) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + x = webidl.converters["unrestricted double"](x); + y = webidl.converters["unrestricted double"](y); + z = webidl.converters["unrestricted double"](z); + angle = webidl.converters["unrestricted double"](angle); + if (x !== 0 || y !== 0 || z !== 0) { + op_geometry_rotate_axis_angle_self( + x, + y, + z, + angle, + this[_raw], + ); + } + this[_is2D] &&= x === 0 && y === 0; + return this; + } + + skewXSelf(sx = 0) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + sx = webidl.converters["unrestricted double"](sx); + op_geometry_skew_self( + sx, + 0, + this[_raw], + ); + return this; + } + + skewYSelf(sy = 0) { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + sy = webidl.converters["unrestricted double"](sy); + op_geometry_skew_self( + 0, + sy, + this[_raw], + ); + return this; + } + + invertSelf() { + webidl.assertBranded(this, DOMMatrixPrototype); + assertWritable(this); + let invertible; + if (this[_is2D]) { + invertible = op_geometry_invert_2d_self(this[_raw]); + } else { + invertible = op_geometry_invert_self(this[_raw]); + } + this[_is2D] &&= invertible; + return this; + } + + [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf(DOMMatrixPrototype, 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, + ); + } +} + +webidl.configureInterface(DOMMatrix); +const DOMMatrixPrototype = DOMMatrix.prototype; + +/** + * TODO(petamoriken): Support this by updating WebIDL's brand features + * @param {DOMRect | DOMPoint | DOMMatrix} self + */ +function assertWritable(self) { + if (self[_writable] !== true) { + throw new TypeError("Illegal invocation"); + } +} + +/** + * https://tc39.es/ecma262/#sec-samevaluezero + * @param {number} x + * @param {number} y + */ +function sameValueZero(x, y) { + return x === y || ObjectIs(x, y); +} + +/** + * https://drafts.fxtf.org/geometry/#matrix-validate-and-fixup-2d + * @param {object} dict + * @param {string} prefix + */ +function validateAndFixup2DMatrixDictionary(dict, prefix) { + if ( + ( + dict.a !== undefined && dict.m11 !== undefined && + !sameValueZero(dict.a, dict.m11) + ) || + ( + dict.b !== undefined && dict.m12 !== undefined && + !sameValueZero(dict.b, dict.m12) + ) || + ( + dict.c !== undefined && dict.m21 !== undefined && + !sameValueZero(dict.c, dict.m21) + ) || + ( + dict.d !== undefined && dict.m22 !== undefined && + !sameValueZero(dict.d, dict.m22) + ) || + ( + dict.e !== undefined && dict.m41 !== undefined && + !sameValueZero(dict.e, dict.m41) + ) || + ( + dict.f !== undefined && dict.m42 !== undefined && + !sameValueZero(dict.f, dict.m42) + ) + ) { + throw new TypeError(`${prefix}: Inconsistent 2d matrix value`); + } + if (dict.m11 === undefined) dict.m11 = dict.a ?? 1; + if (dict.m12 === undefined) dict.m12 = dict.b ?? 0; + if (dict.m21 === undefined) dict.m21 = dict.c ?? 0; + if (dict.m22 === undefined) dict.m22 = dict.d ?? 1; + if (dict.m41 === undefined) dict.m41 = dict.e ?? 0; + if (dict.m42 === undefined) dict.m42 = dict.f ?? 0; +} + +/** + * https://drafts.fxtf.org/geometry/#matrix-validate-and-fixup + * @param {object} dict + * @param {string} prefix + */ +function validateAndFixupMatrixDictionary(dict, prefix) { + validateAndFixup2DMatrixDictionary(dict, prefix); + const is2DCanBeTrue = dict.m13 === 0 && + dict.m14 === 0 && + dict.m23 === 0 && + dict.m24 === 0 && + dict.m31 === 0 && + dict.m32 === 0 && + dict.m33 === 1 && + dict.m34 === 0 && + dict.m43 === 0 && + dict.m44 === 1; + if (dict.is2D === true && !is2DCanBeTrue) { + throw new TypeError( + `${prefix}: is2D property is true but the input matrix is a 3d matrix`, + ); + } + if (dict.is2D === undefined) { + dict.is2D = is2DCanBeTrue; + } +} + +/** + * @param {object} target + * @param {number[] | Float32Array | Float64Array} seq + * @param {string} prefix + */ +function initMatrixFromSequence(target, seq, prefix) { + if (seq.length === 6) { + const { 0: a, 1: b, 2: c, 3: d, 4: e, 5: f } = seq; + // deno-fmt-ignore + target[_raw] = new Float64Array([ + a, b, 0, 0, + c, d, 0, 0, + 0, 0, 1, 0, + e, f, 0, 1, + ]); + target[_is2D] = true; + } else if (seq.length === 16) { + target[_raw] = new Float64Array(seq); + target[_is2D] = false; + } else { + throw new TypeError( + `${prefix}: The sequence must contain 6 elements for a 2D matrix or 16 elements for a 3D matrix`, + ); + } +} + +/** + * @param {object} target + * @param {object} dict + */ +function initMatrixFromDictonary(target, dict) { + if (dict.is2D) { + const { m11, m12, m21, m22, m41, m42 } = dict; + // deno-fmt-ignore + target[_raw] = new Float64Array([ + m11, m12, 0, 0, + m21, m22, 0, 0, + 0, 0, 1, 0, + m41, m42, 0, 1, + ]); + target[_is2D] = true; + } else { + const { + m11, + m12, + m13, + m14, + m21, + m22, + m23, + m24, + m31, + m32, + m33, + m34, + m41, + m42, + m43, + m44, + } = dict; + // deno-fmt-ignore + target[_raw] = new Float64Array([ + m11, m12, m13, m14, + m21, m22, m23, m24, + m31, m32, m33, m34, + m41, m42, m43, m44, + ]); + target[_is2D] = false; + } +} + +/** + * @param {object} target + * @type {DOMMatrixReadOnly} matrix + */ +function initMatrixFromMatrix(target, matrix) { + target[_raw] = new Float64Array(matrix[_raw]); + target[_is2D] = matrix[_is2D]; +} + +/** + * https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-isidentity + * @param {DOMMatrixReadOnly} matrix + */ +function isIdentityMatrix(matrix) { + const raw = matrix[_raw]; + return ( + raw[INDEX_M11] === 1 && + raw[INDEX_M12] === 0 && + raw[INDEX_M13] === 0 && + raw[INDEX_M14] === 0 && + raw[INDEX_M21] === 0 && + raw[INDEX_M22] === 1 && + raw[INDEX_M23] === 0 && + raw[INDEX_M24] === 0 && + raw[INDEX_M31] === 0 && + raw[INDEX_M32] === 0 && + raw[INDEX_M33] === 1 && + raw[INDEX_M34] === 0 && + raw[INDEX_M41] === 0 && + raw[INDEX_M42] === 0 && + raw[INDEX_M43] === 0 && + raw[INDEX_M44] === 1 + ); +} + +/** + * CSS parser + * @type {((transformList: string, prefix: string) => { matrix: Float64Array, is2D: boolean })} + */ +let parseTransformList; + +/** + * @param {(transformList: string, prefix: string) => { matrix: Float64Array, is2D: boolean }} transformListParser + * @param {boolean} enableWindowFeatures + */ +function init(transformListParser, enableWindowFeatures) { + parseTransformList = transformListParser; + + if (enableWindowFeatures) { + // https://drafts.fxtf.org/geometry/#dommatrixreadonly-stringification-behavior + ObjectDefineProperty(DOMMatrixReadOnlyPrototype, "toString", { + value: function toString() { + webidl.assertBranded(this, DOMMatrixReadOnlyPrototype); + const raw = this[_raw]; + if (!TypedArrayPrototypeEvery(raw, (value) => NumberIsFinite(value))) { + throw new DOMException( + "Failed to execute 'toString' on 'DOMMatrixReadOnly': Cannot be serialized with NaN or Infinity values", + "InvalidStateError", + ); + } + if (this[_is2D]) { + return `matrix(${ + ArrayPrototypeJoin([ + raw[INDEX_A], + raw[INDEX_B], + raw[INDEX_C], + raw[INDEX_D], + raw[INDEX_E], + raw[INDEX_F], + ], ", ") + })`; + } else { + return `matrix3d(${TypedArrayPrototypeJoin(raw, ", ")})`; + } + }, + writable: true, + enumerable: true, + configurable: true, + }); + + // https://drafts.fxtf.org/geometry/#dom-dommatrix-setmatrixvalue + ObjectDefineProperty(DOMMatrixPrototype, "setMatrixValue", { + value: function setMatrixValue(transformList) { + webidl.assertBranded(this, DOMMatrixPrototype); + const prefix = "Failed to execute 'setMatrixValue' on 'DOMMatrix'"; + webidl.requiredArguments(arguments.length, 1, prefix); + transformList = webidl.converters.DOMString( + transformList, + prefix, + "Argument 1", + ); + const { matrix, is2D } = parseTransformList(transformList, prefix); + this[_raw] = matrix; + this[_is2D] = is2D; + }, + writable: true, + enumerable: true, + configurable: true, + }); + } +} + +export { + DOMMatrix, + DOMMatrixPrototype, + DOMMatrixReadOnly, + DOMMatrixReadOnlyPrototype, + DOMPoint, + DOMPointPrototype, + DOMPointReadOnly, + DOMPointReadOnlyPrototype, + DOMQuad, + DOMQuadPrototype, + DOMRect, + DOMRectPrototype, + DOMRectReadOnly, + DOMRectReadOnlyPrototype, + init, +}; diff --git a/ext/geometry/Cargo.toml b/ext/geometry/Cargo.toml new file mode 100644 index 00000000000000..9ab2c7c698eaeb --- /dev/null +++ b/ext/geometry/Cargo.toml @@ -0,0 +1,18 @@ +# Copyright 2018-2024 the Deno authors. All rights reserved. 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 +nalgebra.workspace = true diff --git a/ext/geometry/README.md b/ext/geometry/README.md new file mode 100644 index 00000000000000..a8ea2cba96ce81 --- /dev/null +++ b/ext/geometry/README.md @@ -0,0 +1,5 @@ +# deno_geometry + +This crate implements the Geometry Interfaces Module API. + +Spec: https://drafts.fxtf.org/geometry/ diff --git a/ext/geometry/lib.deno_geometry.d.ts b/ext/geometry/lib.deno_geometry.d.ts new file mode 100644 index 00000000000000..44b06d763ebf50 --- /dev/null +++ b/ext/geometry/lib.deno_geometry.d.ts @@ -0,0 +1,602 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-var + +/// +/// + +/** @category Geometry Interfaces Module API */ +declare 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 */ +declare 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; +} + +/** + * 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 + */ +declare interface DOMMatrix extends DOMMatrixReadOnly { + a: number; + b: number; + c: number; + d: number; + e: number; + f: number; + m11: number; + m12: number; + m13: number; + m14: number; + m21: number; + m22: number; + m23: number; + m24: number; + m31: number; + m32: number; + m33: number; + m34: number; + m41: number; + m42: number; + m43: number; + m44: number; + /** + * Modifies the matrix by inverting it. + * If the matrix can't be inverted, its components are all set to `NaN`, and is2D property is set to `false`. + */ + invertSelf(): DOMMatrix; + /** + * Modifies the matrix by post-multiplying it with the specified DOMMatrix. + * This is equivalent to the dot product `A⋅B`, where matrix `A` is the source matrix and `B` is the matrix given as an input to the method. + * + * @param other + */ + multiplySelf(other?: DOMMatrixInit): DOMMatrix; + /** + * Modifies the matrix by pre-multiplying it with the specified DOMMatrix. + * This is equivalent to the dot product B⋅A, where matrix `A` is the source matrix and `B` is the matrix given as an input to the method. + * + * @param other + */ + preMultiplySelf(other?: DOMMatrixInit): DOMMatrix; + /** + * Modifies the matrix by rotating it by the specified angle around the given vector. + * + * @param x + * @param y + * @param z + * @param angle in degrees + */ + rotateAxisAngleSelf( + x?: number, + y?: number, + z?: number, + angle?: number, + ): DOMMatrix; + /** + * Modifies the matrix by rotating it by the angle between the specified vector and `(1, 0)`. + * + * @param x + * @param y + */ + rotateFromVectorSelf(x?: number, y?: number): DOMMatrix; + /** + * Modifies the matrix by rotating itself around each axis by the specified number of degrees. + * + * @param rotZ yaw angle in degrees + */ + rotateSelf(rotZ?: number): DOMMatrix; + /** + * Modifies the matrix by rotating itself around each axis by the specified number of degrees. + * + * @param rotX roll angle in degrees + * @param rotY pitch angle in degrees + * @param rotZ yaw angle in degrees + */ + rotateSelf(rotX?: number, rotY?: number, rotZ?: number): DOMMatrix; + /** + * Modifies the matrix by applying the specified scaling factor to all three axes, centered on the given origin. + * + * @param scale + * @param originX + * @param originY + * @param originZ + */ + scale3dSelf( + scale?: number, + originX?: number, + originY?: number, + originZ?: number, + ): DOMMatrix; + /** + * Modifies the matrix by applying the specified scaling factors, with the center located at the specified origin. Also returns itself. + * By default, the X and Z axes are scaled by `1` and the Y axis is given the same scaling value as the X axis. + * The default origin is `(0, 0, 0)`. + * + * @param scaleX + * @param scaleY + * @param scaleZ + * @param originX + * @param originY + * @param originZ + */ + scaleSelf( + scaleX?: number, + scaleY?: number, + scaleZ?: number, + originX?: number, + originY?: number, + originZ?: number, + ): DOMMatrix; + /** + * NOTE: Not available in Worker + * + * Replaces the contents of the matrix with the matrix described by the specified transform or transforms. + * + * @param transformList + */ + setMatrixValue(transformList: string): DOMMatrix; + /** + * Modifies the matrix by applying the specified skew transformation along the X-axis. + * + * @param sx in degrees + */ + skewXSelf(sx?: number): DOMMatrix; + /** + * Modifies the matrix by applying the specified skew transformation along the Y-axis. + * + * @param sy in degrees + */ + skewYSelf(sy?: number): DOMMatrix; + /** + * Modifies the matrix by applying the specified vector. The default vector is `(0, 0, 0)`. + * + * @param tx + * @param ty + * @param tz + */ + 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 + */ +declare var DOMMatrix: { + prototype: DOMMatrix; + new (init?: number[]): DOMMatrix; + new (init: DOMMatrix | DOMMatrixReadOnly): DOMMatrix; + /** NOTE: Not available in Worker */ + new (init: string): DOMMatrix; + fromFloat32Array(array32: Float32Array): DOMMatrix; + fromFloat64Array(array64: Float64Array): DOMMatrix; + fromMatrix(other?: DOMMatrixInit): DOMMatrix; +}; + +/** + * A read-only 4×4 matrix (column-major order), suitable for 2D and 3D operations including rotation and translation. + * [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 + */ +declare interface DOMMatrixReadOnly { + readonly a: number; + readonly b: number; + readonly c: number; + readonly d: number; + readonly e: number; + readonly f: number; + readonly is2D: boolean; + readonly isIdentity: boolean; + readonly m11: number; + readonly m12: number; + readonly m13: number; + readonly m14: number; + readonly m21: number; + readonly m22: number; + readonly m23: number; + readonly m24: number; + readonly m31: number; + readonly m32: number; + readonly m33: number; + readonly m34: number; + readonly m41: number; + readonly m42: number; + readonly m43: number; + readonly m44: number; + /** Returns a new `DOMMatrix` created by flipping the source matrix around its X-axis. */ + flipX(): DOMMatrix; + /** Returns a new `DOMMatrix` created by flipping the source matrix around its Y-axis. */ + flipY(): DOMMatrix; + /** + * Returns a new `DOMMatrix` created by inverting the source matrix. + * If the matrix cannot be inverted, the new matrix's components are all set to `NaN` and its is2D property is set to `false`. + */ + inverse(): DOMMatrix; + /** + * Returns a new `DOMMatrix` created by computing the dot product of the source matrix and the specified matrix: `A⋅B`. + * + * @param other + */ + multiply(other?: DOMMatrixInit): DOMMatrix; + /** + * Returns a new `DOMMatrix` created by rotating the source matrix around each of its axes by the specified number of degrees. + * + * @param rotZ yaw angle in degrees + */ + rotate(rotZ?: number): DOMMatrix; + /** + * Returns a new `DOMMatrix` created by rotating the source matrix around each of its axes by the specified number of degrees. + * + * @param rotX roll angle in degrees + * @param rotY pitch angle in degrees + * @param rotZ yaw angle in degrees + */ + rotate(rotX?: number, rotY?: number, rotZ?: number): DOMMatrix; + /** + * Returns a new DOMMatrix created by rotating the source matrix by the given angle around the specified vector. + * + * @param x + * @param y + * @param z + * @param angle in degrees + */ + rotateAxisAngle( + x?: number, + y?: number, + z?: number, + angle?: number, + ): DOMMatrix; + /** + * Returns a new `DOMMatrix` created by rotating the source matrix by the angle between the specified vector and `(1, 0)`. + * + * @param x + * @param y + */ + rotateFromVector(x?: number, y?: number): DOMMatrix; + /** + * Returns a new `DOMMatrix` created by scaling the source matrix by the amount specified for each axis, centered on the given origin. + * By default, the X and Z axes are scaled by `1` and the Y axis is given the same scaling value as the X axis. + * The default origin is `(0, 0, 0)`. + * + * @param scaleX + * @param scaleY + * @param scaleZ + * @param originX + * @param originY + * @param originZ + */ + scale( + scaleX?: number, + scaleY?: number, + scaleZ?: number, + originX?: number, + originY?: number, + originZ?: number, + ): DOMMatrix; + /** + * Returns a new `DOMMatrix` created by scaling the source 3D matrix by the given factor along all its axes, centered on the specified origin point. + * The default origin is `(0, 0, 0)`. + * + * @param scale + * @param originX + * @param originY + * @param originZ + */ + scale3d( + scale?: number, + originX?: number, + originY?: number, + originZ?: number, + ): DOMMatrix; + /** + * Returns a new `DOMMatrix` created by applying the specified scaling on the X, Y, and Z axes, centered at the given origin. + * By default, the X and Y axes' scaling factors are both `1`. + * + * @deprecated Supported for legacy reasons to be compatible with `SVGMatrix` as defined in SVG 1.1. Use `scale()` instead. + * + * @param scaleX + * @param scaleY + */ + scaleNonUniform(scaleX?: number, scaleY?: number): DOMMatrix; + /** + * Returns a new DOMMatrix created by applying the specified skew transformation to the source matrix along its X-axis. + * + * @param sx in degrees + */ + skewX(sx?: number): DOMMatrix; + /** + * Returns a new DOMMatrix created by applying the specified skew transformation to the source matrix along its Y-axis. + * + * @param sy in degrees + */ + skewY(sy?: number): DOMMatrix; + toFloat32Array(): Float32Array; + toFloat64Array(): Float64Array; + toJSON(): { + a: number; + b: number; + c: number; + d: number; + e: number; + f: number; + is2D: boolean; + isIdentity: boolean; + m11: number; + m12: number; + m13: number; + m14: number; + m21: number; + m22: number; + m23: number; + m24: number; + m31: number; + m32: number; + m33: number; + m34: number; + m41: number; + m42: number; + m43: number; + m44: number; + }; + transformPoint(point?: DOMPointInit): DOMPoint; + translate(tx?: number, ty?: number, tz?: number): DOMMatrix; + /** NOTE: Not available in Worker */ + toString(): string; +} + +/** + * A read-only 4×4 matrix (column-major order), suitable for 2D and 3D operations including rotation and translation. + * [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 + */ +declare var DOMMatrixReadOnly: { + prototype: DOMMatrixReadOnly; + new (init?: number[]): DOMMatrixReadOnly; + new (init: DOMMatrix | DOMMatrixReadOnly): DOMMatrixReadOnly; + /** Not available in Worker */ + new (init: string): DOMMatrixReadOnly; + fromFloat32Array(array32: Float32Array): DOMMatrixReadOnly; + fromFloat64Array(array64: Float64Array): DOMMatrixReadOnly; + fromMatrix(other?: DOMMatrixInit): DOMMatrixReadOnly; +}; + +/** @category Geometry Interfaces Module API */ +declare interface DOMPointInit { + w?: number; + x?: number; + y?: number; + z?: number; +} + +/** + * A 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 + */ +declare interface DOMPoint extends DOMPointReadOnly { + w: number; + x: number; + y: number; + z: number; +} + +/** + * A 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 + */ +declare var DOMPoint: { + prototype: DOMPoint; + new (x?: number, y?: number, z?: number, w?: number): DOMPoint; + fromPoint(other?: DOMPointInit): DOMPoint; +}; + +/** + * A read-only 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/DOMPointReadOnly) + * + * @category Geometry Interfaces Module API + */ +declare interface DOMPointReadOnly { + readonly w: number; + readonly x: number; + readonly y: number; + readonly z: number; + matrixTransform(matrix?: DOMMatrixInit): DOMPoint; + toJSON(): { + w: number; + x: number; + y: number; + z: number; + }; +} + +/** + * A read-only 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/DOMPointReadOnly) + * + * @category Geometry Interfaces Module API + */ +declare var DOMPointReadOnly: { + prototype: DOMPointReadOnly; + new (x?: number, y?: number, z?: number, w?: number): DOMPointReadOnly; + fromPoint(other?: DOMPointInit): DOMPointReadOnly; +}; + +/** @category Geometry Interfaces Module API */ +declare interface DOMQuadInit { + p1?: DOMPointInit; + p2?: DOMPointInit; + p3?: DOMPointInit; + p4?: DOMPointInit; +} + +/** + * A collection of four DOMPoints defining the corners of an arbitrary quadrilateral. + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMQuad) + * + * @category Geometry Interfaces Module API + */ +declare interface DOMQuad { + readonly p1: DOMPoint; + readonly p2: DOMPoint; + readonly p3: DOMPoint; + readonly p4: DOMPoint; + getBounds(): DOMRect; + toJSON(): { + p1: DOMPoint; + p2: DOMPoint; + p3: DOMPoint; + p4: DOMPoint; + }; +} + +/** + * A collection of four DOMPoints defining the corners of an arbitrary quadrilateral. + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMQuad) + * + * @category Geometry Interfaces Module API + */ +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 */ +declare interface DOMRectInit { + height?: number; + width?: number; + x?: number; + y?: number; +} + +/** + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMRect) + * + * @category Geometry Interfaces Module API + */ +declare interface DOMRect extends DOMRectReadOnly { + height: number; + width: number; + x: number; + y: number; +} + +/** + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMRect) + * + * @category Geometry Interfaces Module API + */ +declare var DOMRect: { + prototype: DOMRect; + new (x?: number, y?: number, width?: number, height?: number): DOMRect; + fromRect(other?: DOMRectInit): DOMRect; +}; + +/** + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly) + * + * @category Geometry Interfaces Module API + */ +declare interface DOMRectReadOnly { + readonly bottom: number; + readonly height: number; + readonly left: number; + readonly right: number; + readonly top: number; + readonly width: number; + readonly x: number; + readonly y: number; + toJSON(): { + bottom: number; + height: number; + left: number; + right: number; + top: number; + width: number; + x: number; + y: number; + }; +} + +/** + * [MDN](https://developer.mozilla.org/docs/Web/API/DOMRectReadOnly) + * + * @category Geometry Interfaces Module API + */ +declare var DOMRectReadOnly: { + prototype: DOMRectReadOnly; + new ( + x?: number, + y?: number, + width?: number, + height?: number, + ): DOMRectReadOnly; + fromRect(other?: DOMRectInit): DOMRectReadOnly; +}; diff --git a/ext/geometry/lib.rs b/ext/geometry/lib.rs new file mode 100644 index 00000000000000..16879f4ddf2071 --- /dev/null +++ b/ext/geometry/lib.rs @@ -0,0 +1,269 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use deno_core::op2; +use nalgebra::Matrix3; +use nalgebra::Matrix4; +use nalgebra::Matrix4x2; +use nalgebra::Matrix4x3; +use nalgebra::MatrixView4; +use nalgebra::MatrixViewMut4; +use nalgebra::Rotation3; +use nalgebra::UnitVector3; +use nalgebra::Vector3; +use nalgebra::Vector4; +use nalgebra::VectorViewMut4; +use std::path::PathBuf; + +deno_core::extension!( + deno_geometry, + deps = [deno_webidl, deno_web, deno_console], + ops = [ + op_geometry_translate_self, + op_geometry_scale_self, + op_geometry_scale_with_origin_self, + op_geometry_rotate_self, + op_geometry_rotate_from_vector_self, + op_geometry_rotate_axis_angle_self, + op_geometry_skew_self, + op_geometry_multiply, + op_geometry_multiply_self, + op_geometry_premultiply_self, + op_geometry_flip_x_self, + op_geometry_flip_y_self, + op_geometry_invert_self, + op_geometry_invert_2d_self, + op_geometry_premultiply_point_self, + ], + esm = ["00_init.js"], + lazy_loaded_esm = ["01_geometry.js"], +); + +pub fn get_declaration() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_geometry.d.ts") +} + +#[op2(fast)] +pub fn op_geometry_translate_self( + x: f64, + y: f64, + z: f64, + #[buffer] inout: &mut [f64], +) { + let shift = Vector3::new(x, y, z); + let mut inout = MatrixViewMut4::from_slice(inout); + inout.prepend_translation_mut(&shift); +} + +#[op2(fast)] +pub fn op_geometry_scale_self( + x: f64, + y: f64, + z: f64, + #[buffer] inout: &mut [f64], +) { + let scaling = Vector3::new(x, y, z); + let mut inout = MatrixViewMut4::from_slice(inout); + inout.prepend_nonuniform_scaling_mut(&scaling); +} + +#[op2(fast)] +pub fn op_geometry_scale_with_origin_self( + x: f64, + y: f64, + z: f64, + origin_x: f64, + origin_y: f64, + origin_z: f64, + #[buffer] inout: &mut [f64], +) { + let scaling = Vector3::new(x, y, z); + let mut shift = Vector3::new(origin_x, origin_y, origin_z); + let mut inout = MatrixViewMut4::from_slice(inout); + inout.prepend_translation_mut(&shift); + inout.prepend_nonuniform_scaling_mut(&scaling); + shift.neg_mut(); + inout.prepend_translation_mut(&shift); +} + +#[op2(fast)] +pub fn op_geometry_rotate_self( + roll_degrees: f64, + pitch_degrees: f64, + yaw_degrees: f64, + #[buffer] inout: &mut [f64], +) { + let rotation = Rotation3::from_euler_angles( + roll_degrees.to_radians(), + pitch_degrees.to_radians(), + yaw_degrees.to_radians(), + ) + .to_homogeneous(); + let mut inout = MatrixViewMut4::from_slice(inout); + let mut result = Matrix4x3::zeros(); + inout.mul_to(&rotation.fixed_view::<4, 3>(0, 0), &mut result); + inout.set_column(0, &result.column(0)); + inout.set_column(1, &result.column(1)); + inout.set_column(2, &result.column(2)); +} + +#[op2(fast)] +pub fn op_geometry_rotate_from_vector_self( + x: f64, + y: f64, + #[buffer] inout: &mut [f64], +) { + let rotation = + Rotation3::from_axis_angle(&Vector3::z_axis(), y.atan2(x)).to_homogeneous(); + let mut inout = MatrixViewMut4::from_slice(inout); + let mut result = Matrix4x3::zeros(); + inout.mul_to(&rotation.fixed_view::<4, 3>(0, 0), &mut result); + inout.set_column(0, &result.column(0)); + inout.set_column(1, &result.column(1)); + inout.set_column(2, &result.column(2)); +} + +#[op2(fast)] +pub fn op_geometry_rotate_axis_angle_self( + x: f64, + y: f64, + z: f64, + angle_degrees: f64, + #[buffer] inout: &mut [f64], +) { + let rotation = Rotation3::from_axis_angle( + &UnitVector3::new_normalize(Vector3::new(x, y, z)), + angle_degrees.to_radians(), + ) + .to_homogeneous(); + let mut inout = MatrixViewMut4::from_slice(inout); + let mut result = Matrix4x3::zeros(); + inout.mul_to(&rotation.fixed_view::<4, 3>(0, 0), &mut result); + inout.set_column(0, &result.column(0)); + inout.set_column(1, &result.column(1)); + inout.set_column(2, &result.column(2)); +} + +#[op2(fast)] +pub fn op_geometry_skew_self( + x_degrees: f64, + y_degrees: f64, + #[buffer] inout: &mut [f64], +) { + let skew = Matrix4x2::new( + 1.0, + x_degrees.to_radians().tan(), + y_degrees.to_radians().tan(), + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + ); + let mut inout = MatrixViewMut4::from_slice(inout); + let mut result = Matrix4x2::zeros(); + inout.mul_to(&skew, &mut result); + inout.set_column(0, &result.column(0)); + inout.set_column(1, &result.column(1)); +} + +#[op2(fast)] +pub fn op_geometry_multiply( + #[buffer] lhs: &[f64], + #[buffer] rhs: &[f64], + #[buffer] out: &mut [f64], +) { + let lhs = MatrixView4::from_slice(lhs); + let rhs = MatrixView4::from_slice(rhs); + let mut out = MatrixViewMut4::from_slice(out); + lhs.mul_to(&rhs, &mut out); +} + +#[op2(fast)] +pub fn op_geometry_multiply_self( + #[buffer] rhs: &[f64], + #[buffer] inout: &mut [f64], +) { + let rhs = MatrixView4::from_slice(rhs); + let mut inout = MatrixViewMut4::from_slice(inout); + let mut result = Matrix4::zeros(); + inout.mul_to(&rhs, &mut result); + inout.copy_from(&result); +} + +#[op2(fast)] +pub fn op_geometry_premultiply_self( + #[buffer] lhs: &[f64], + #[buffer] inout: &mut [f64], +) { + let lhs = MatrixView4::from_slice(lhs); + let mut inout = MatrixViewMut4::from_slice(inout); + let mut result = Matrix4::zeros(); + lhs.mul_to(&inout, &mut result); + inout.copy_from(&result); +} + +#[op2(fast)] +pub fn op_geometry_flip_x_self(#[buffer] inout: &mut [f64]) { + let mut inout = MatrixViewMut4::from_slice(inout); + inout.column_mut(0).neg_mut(); +} + +#[op2(fast)] +pub fn op_geometry_flip_y_self(#[buffer] inout: &mut [f64]) { + let mut inout = MatrixViewMut4::from_slice(inout); + inout.column_mut(1).neg_mut(); +} + +#[op2(fast)] +pub fn op_geometry_invert_self(#[buffer] inout: &mut [f64]) -> bool { + if inout.iter().any(|&x| x.is_infinite()) { + inout.fill(f64::NAN); + return false; + } + + let mut inout = MatrixViewMut4::from_slice(inout); + if !inout.try_inverse_mut() { + inout.fill(f64::NAN); + return false; + } + + true +} + +#[op2(fast)] +pub fn op_geometry_invert_2d_self(#[buffer] inout: &mut [f64]) -> bool { + if inout.iter().any(|&x| x.is_infinite()) { + inout.fill(f64::NAN); + return false; + } + + let mut matrix = Matrix3::new( + inout[0], inout[4], inout[12], inout[1], inout[5], inout[13], 0.0, 0.0, 1.0, + ); + if !matrix.try_inverse_mut() { + inout.fill(f64::NAN); + return false; + } + + let matrix = matrix.as_slice(); + inout[0] = matrix[0]; + inout[1] = matrix[1]; + inout[4] = matrix[3]; + inout[5] = matrix[4]; + inout[12] = matrix[6]; + inout[13] = matrix[7]; + + true +} + +#[op2(fast)] +pub fn op_geometry_premultiply_point_self( + #[buffer] lhs: &[f64], + #[buffer] inout: &mut [f64], +) { + let lhs = MatrixView4::from_slice(lhs); + let mut inout = VectorViewMut4::from_slice(inout); + let mut result = Vector4::zeros(); + lhs.mul_to(&inout, &mut result); + inout.copy_from(&result); +} diff --git a/ext/webidl/00_webidl.js b/ext/webidl/00_webidl.js index 7440e47e7baf3a..dbd6b14e13a3e1 100644 --- a/ext/webidl/00_webidl.js +++ b/ext/webidl/00_webidl.js @@ -679,6 +679,9 @@ converters["UVString?"] = createNullableConverter( converters["sequence"] = createSequenceConverter( converters.double, ); +converters["sequence"] = createSequenceConverter( + converters["unrestricted double"], +); converters["sequence"] = createSequenceConverter( converters.object, ); diff --git a/ext/webidl/internal.d.ts b/ext/webidl/internal.d.ts index d9266f5f548a3c..3d730ab84e8f50 100644 --- a/ext/webidl/internal.d.ts +++ b/ext/webidl/internal.d.ts @@ -348,6 +348,12 @@ declare module "ext:deno_webidl/00_webidl.js" { context?: string, opts?: any, ): number[]; + ["sequence"]( + v: any, + prefix?: string, + context?: string, + opts?: any, + ): number[]; [type: string]: ( v: any, diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 8c1d07a1e43b4d..b1a406391b54ca 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -51,6 +51,7 @@ deno_crypto.workspace = true deno_fetch.workspace = true deno_ffi.workspace = true deno_fs = { workspace = true, features = ["sync_fs"] } +deno_geometry.workspace = true deno_http.workspace = true deno_io.workspace = true deno_net.workspace = true @@ -82,6 +83,7 @@ deno_crypto.workspace = true deno_fetch.workspace = true deno_ffi.workspace = true deno_fs = { workspace = true, features = ["sync_fs"] } +deno_geometry.workspace = true deno_http.workspace = true deno_io.workspace = true deno_kv.workspace = true diff --git a/runtime/js/98_global_scope_window.js b/runtime/js/98_global_scope_window.js index aa18ed36136139..c8ca3cb8c167ee 100644 --- a/runtime/js/98_global_scope_window.js +++ b/runtime/js/98_global_scope_window.js @@ -7,18 +7,93 @@ import { op_bootstrap_user_agent, } from "ext:core/ops"; const { + ArrayPrototypeMap, + ArrayPrototypeSome, + Float64Array, + Number, + NumberIsNaN, ObjectDefineProperties, ObjectPrototypeIsPrototypeOf, + SafeRegExp, + StringPrototypeMatch, + StringPrototypeSplit, SymbolFor, + TypeError, } = primordials; import * as location from "ext:deno_web/12_location.js"; import * as console from "ext:deno_console/01_console.js"; import * as webidl from "ext:deno_webidl/00_webidl.js"; +import { DOMException } from "ext:deno_web/01_dom_exception.js"; import * as globalInterfaces from "ext:deno_web/04_global_interfaces.js"; import * as webStorage from "ext:deno_webstorage/01_webstorage.js"; import * as prompt from "ext:runtime/41_prompt.js"; import { loadWebGPU } from "ext:deno_webgpu/00_init.js"; +import { createGeometryLoader } from "ext:deno_geometry/00_init.js"; + +const MATRIX_PATTERN = new SafeRegExp( + /^\s*matrix(3d)?\(([-\+0-9.e,\s]+)\)\s*$/iu, +); + +const loadGeometry = createGeometryLoader((transformList, prefix) => { + if (transformList === "") { + return { + // deno-fmt-ignore + matrix: new Float64Array([ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + ]), + is2D: true, + }; + } + + // Currently only parsing of a single matrix, matrix3d function without units + // as arguments is implemented + // TODO(petamoriken): Add CSS parser such as lightningcss to support more cases + const matrixMatch = StringPrototypeMatch(transformList, MATRIX_PATTERN); + if (matrixMatch !== null) { + const is2D = matrixMatch[1] === undefined; + /** @type {number[]} */ + const seq = ArrayPrototypeMap( + StringPrototypeSplit(matrixMatch[2], ","), + (str) => Number(str), + ); + if ( + is2D && seq.length !== 6 || + !is2D && seq.length !== 16 || + ArrayPrototypeSome(seq, (num) => NumberIsNaN(num)) + ) { + throw new DOMException( + `${prefix}: Failed to parse '${transformList}'`, + "SyntaxError", + ); + } + if (is2D) { + const { 0: a, 1: b, 2: c, 3: d, 4: e, 5: f } = seq; + return { + // deno-fmt-ignore + matrix: new Float64Array([ + a, b, 0, 0, + c, d, 0, 0, + 0, 0, 1, 0, + e, f, 0, 1, + ]), + is2D, + }; + } else { + return { + matrix: new Float64Array(seq), + is2D, + }; + } + } + + throw new TypeError( + `${prefix}: CSS parser is not fully implemented`, + ); +}, true); class Navigator { constructor() { @@ -117,6 +192,34 @@ const mainRuntimeGlobalProperties = { localStorage: core.propGetterOnly(webStorage.localStorage), sessionStorage: core.propGetterOnly(webStorage.sessionStorage), Storage: core.propNonEnumerable(webStorage.Storage), + 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, + ), }; export { mainRuntimeGlobalProperties, memoizeLazy }; diff --git a/runtime/js/98_global_scope_worker.js b/runtime/js/98_global_scope_worker.js index 8e292108f8305e..20783c17b292f1 100644 --- a/runtime/js/98_global_scope_worker.js +++ b/runtime/js/98_global_scope_worker.js @@ -10,6 +10,7 @@ const { ObjectDefineProperties, ObjectPrototypeIsPrototypeOf, SymbolFor, + TypeError, } = primordials; import * as location from "ext:deno_web/12_location.js"; @@ -17,6 +18,13 @@ import * as console from "ext:deno_console/01_console.js"; import * as webidl from "ext:deno_webidl/00_webidl.js"; import * as globalInterfaces from "ext:deno_web/04_global_interfaces.js"; import { loadWebGPU } from "ext:deno_webgpu/00_init.js"; +import { createGeometryLoader } from "ext:deno_geometry/00_init.js"; + +const loadGeometry = createGeometryLoader((_transformList, prefix) => { + throw new TypeError( + `${prefix}: Cannot parse CSS on Workers`, + ); +}, false); function memoizeLazy(f) { let v_ = null; @@ -110,6 +118,34 @@ const workerRuntimeGlobalProperties = { WorkerNavigator: core.propNonEnumerable(WorkerNavigator), navigator: core.propGetterOnly(() => workerNavigator), self: core.propGetterOnly(() => 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, + ), }; export { workerRuntimeGlobalProperties }; diff --git a/runtime/lib.rs b/runtime/lib.rs index a729d88f76b3ab..1f60dde1554bd1 100644 --- a/runtime/lib.rs +++ b/runtime/lib.rs @@ -10,6 +10,7 @@ pub use deno_crypto; pub use deno_fetch; pub use deno_ffi; pub use deno_fs; +pub use deno_geometry; pub use deno_http; pub use deno_io; pub use deno_kv; diff --git a/runtime/shared.rs b/runtime/shared.rs index 1b2136c6383ca7..828b3b6e336a8f 100644 --- a/runtime/shared.rs +++ b/runtime/shared.rs @@ -21,6 +21,7 @@ extension!(runtime, deno_web, deno_fetch, deno_cache, + deno_geometry, deno_websocket, deno_webstorage, deno_crypto, diff --git a/runtime/snapshot.rs b/runtime/snapshot.rs index 659356ae66ea56..9b372f65b1d337 100644 --- a/runtime/snapshot.rs +++ b/runtime/snapshot.rs @@ -230,6 +230,7 @@ pub fn create_runtime_snapshot( deno_webgpu::deno_webgpu::init_ops_and_esm(), deno_canvas::deno_canvas::init_ops_and_esm(), deno_fetch::deno_fetch::init_ops_and_esm::(Default::default()), + deno_geometry::deno_geometry::init_ops_and_esm(), deno_cache::deno_cache::init_ops_and_esm::(None), deno_websocket::deno_websocket::init_ops_and_esm::( "".to_owned(), diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index ed1e19c9ec596b..6d485074cb3135 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -447,6 +447,7 @@ impl WebWorker { ..Default::default() }, ), + deno_geometry::deno_geometry::init_ops_and_esm(), deno_cache::deno_cache::init_ops_and_esm::( create_cache, ), diff --git a/runtime/worker.rs b/runtime/worker.rs index 696786b56485b6..ddcbd939e5cfcd 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -369,6 +369,7 @@ impl MainWorker { ..Default::default() }, ), + deno_geometry::deno_geometry::init_ops_and_esm(), deno_cache::deno_cache::init_ops_and_esm::( create_cache, ), diff --git a/tests/integration/js_unit_tests.rs b/tests/integration/js_unit_tests.rs index cbae4a0b8c4518..67acaf3708ceb6 100644 --- a/tests/integration/js_unit_tests.rs +++ b/tests/integration/js_unit_tests.rs @@ -40,6 +40,7 @@ util::unit_test_factory!( files_test, flock_test, fs_events_test, + geometry_test, get_random_values_test, globals_test, headers_test, diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs index 28c36cd205d611..6d443d8c5ae871 100644 --- a/tests/integration/lsp_tests.rs +++ b/tests/integration/lsp_tests.rs @@ -5373,7 +5373,7 @@ fn lsp_jsr_auto_import_completion() { json!({ "triggerKind": 1 }), ); assert!(!list.is_incomplete); - assert_eq!(list.items.len(), 267); + assert_eq!(list.items.len(), 274); let item = list.items.iter().find(|i| i.label == "add").unwrap(); assert_eq!(&item.label, "add"); assert_eq!( @@ -5453,7 +5453,7 @@ fn lsp_jsr_auto_import_completion_import_map() { json!({ "triggerKind": 1 }), ); assert!(!list.is_incomplete); - assert_eq!(list.items.len(), 267); + assert_eq!(list.items.len(), 274); let item = list.items.iter().find(|i| i.label == "add").unwrap(); assert_eq!(&item.label, "add"); assert_eq!(json!(&item.label_details), json!({ "description": "add" })); diff --git a/tests/unit/geometry_test.ts b/tests/unit/geometry_test.ts new file mode 100644 index 00000000000000..b4910c3e6f5ec6 --- /dev/null +++ b/tests/unit/geometry_test.ts @@ -0,0 +1,1195 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +import { + assertAlmostEquals, + assertEquals, + assertStrictEquals, + assertThrows, +} from "./test_util.ts"; + +Deno.test(function matrixTransformPoint() { + const point = new DOMPoint(1, 2, 3, 4); + // deno-fmt-ignore + const matrix = DOMMatrix.fromMatrix({ + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }); + const point2 = point.matrixTransform(matrix); + const point3 = matrix.transformPoint(point); + assertEquals( + point, + new DOMPoint(1, 2, 3, 4), + ); + assertEquals( + point2, + new DOMPoint(30, 70, 110, 150), + ); + assertEquals( + point3, + new DOMPoint(30, 70, 110, 150), + ); +}); + +Deno.test(function matrixTranslate() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.translate(1, 2, 3); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2, m31: 3, m41: 1 * 1 + 2 * 2 + 3 * 3 + 4 * 1, + m12: 5, m22: 6, m32: 7, m42: 5 * 1 + 6 * 2 + 7 * 3 + 8 * 1, + m13: 9, m23: 10, m33: 11, m43: 9 * 1 + 10 * 2 + 11 * 3 + 12 * 1, + m14: 13, m24: 14, m34: 15, m44: 13 * 1 + 14 * 2 + 15 * 3 + 16 * 1, + }), + ); +}); + +Deno.test(function matrixTranslateSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.translateSelf(1, 2, 3); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2, m31: 3, m41: 1 * 1 + 2 * 2 + 3 * 3 + 4 * 1, + m12: 5, m22: 6, m32: 7, m42: 5 * 1 + 6 * 2 + 7 * 3 + 8 * 1, + m13: 9, m23: 10, m33: 11, m43: 9 * 1 + 10 * 2 + 11 * 3 + 12 * 1, + m14: 13, m24: 14, m34: 15, m44: 13 * 1 + 14 * 2 + 15 * 3 + 16 * 1, + }), + ); +}); + +Deno.test(function matrixScale() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale(1, 2, 3); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2 * 2, m31: 3 * 3, m41: 4, + m12: 5, m22: 6 * 2, m32: 7 * 3, m42: 8, + m13: 9, m23: 10 * 2, m33: 11 * 3, m43: 12, + m14: 13, m24: 14 * 2, m34: 15 * 3, m44: 16, + }), + ); +}); + +Deno.test(function matrixScaleSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scaleSelf(1, 2, 3); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2 * 2, m31: 3 * 3, m41: 4, + m12: 5, m22: 6 * 2, m32: 7 * 3, m42: 8, + m13: 9, m23: 10 * 2, m33: 11 * 3, m43: 12, + m14: 13, m24: 14 * 2, m34: 15 * 3, m44: 16, + }), + ); +}); + +Deno.test(function matrixScaleWithOrigin() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale(1, 2, 3, 4, 5, 6); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2 * 2, m31: 3 * 3, m41: -42, + m12: 5, m22: 6 * 2, m32: 7 * 3, m42: -106, + m13: 9, m23: 10 * 2, m33: 11 * 3, m43: -170, + m14: 13, m24: 14 * 2, m34: 15 * 3, m44: -234, + }), + ); +}); + +Deno.test(function matrixScaleWithOriginSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scaleSelf(1, 2, 3, 4, 5, 6); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2 * 2, m31: 3 * 3, m41: -42, + m12: 5, m22: 6 * 2, m32: 7 * 3, m42: -106, + m13: 9, m23: 10 * 2, m33: 11 * 3, m43: -170, + m14: 13, m24: 14 * 2, m34: 15 * 3, m44: -234, + }), + ); +}); + +Deno.test(function matrixScaleNonUniform() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scaleNonUniform(1, 2); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: 2 * 2, m31: 3, m41: 4, + m12: 5, m22: 6 * 2, m32: 7, m42: 8, + m13: 9, m23: 10 * 2, m33: 11, m43: 12, + m14: 13, m24: 14 * 2, m34: 15, m44: 16, + }), + ); +}); + +Deno.test(function matrixScale3d() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale3d(2); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 2, m21: 2 * 2, m31: 3 * 2, m41: 4, + m12: 5 * 2, m22: 6 * 2, m32: 7 * 2, m42: 8, + m13: 9 * 2, m23: 10 * 2, m33: 11 * 2, m43: 12, + m14: 13 * 2, m24: 14 * 2, m34: 15 * 2, m44: 16, + }), + ); +}); + +Deno.test(function matrixScale3dSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale3dSelf(2); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 2, m21: 2 * 2, m31: 3 * 2, m41: 4, + m12: 5 * 2, m22: 6 * 2, m32: 7 * 2, m42: 8, + m13: 9 * 2, m23: 10 * 2, m33: 11 * 2, m43: 12, + m14: 13 * 2, m24: 14 * 2, m34: 15 * 2, m44: 16, + }), + ); +}); + +Deno.test(function matrixScale3dWithOrigin() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale3d(2, 4, 5, 6); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 2, m21: 2 * 2, m31: 3 * 2, m41: -28, + m12: 5 * 2, m22: 6 * 2, m32: 7 * 2, m42: -84, + m13: 9 * 2, m23: 10 * 2, m33: 11 * 2, m43: -140, + m14: 13 * 2, m24: 14 * 2, m34: 15 * 2, m44: -196, + }), + ); +}); + +Deno.test(function matrixScale3dWithOriginSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.scale3dSelf(2, 4, 5, 6); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 2, m21: 2 * 2, m31: 3 * 2, m41: -28, + m12: 5 * 2, m22: 6 * 2, m32: 7 * 2, m42: -84, + m13: 9 * 2, m23: 10 * 2, m33: 11 * 2, m43: -140, + m14: 13 * 2, m24: 14 * 2, m34: 15 * 2, m44: -196, + }), + ); +}); + +Deno.test(function matrixRotate() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: -3, m21: -2, m31: -1, m41: 4, + m12: -7, m22: -6, m32: -5, m42: 8, + m13: -11, m23: -10, m33: -9, m43: 12, + m14: -15, m24: -14, m34: -13, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotate(0, 90, 180); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix2[key], + value, + ); + } +}); + +Deno.test(function matrixRotateSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: -3, m21: -2, m31: -1, m41: 4, + m12: -7, m22: -6, m32: -5, m42: 8, + m13: -11, m23: -10, m33: -9, m43: 12, + m14: -15, m24: -14, m34: -13, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotateSelf(0, 90, 180); + assertStrictEquals( + matrix, + matrix2, + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix[key], + value, + ); + } +}); + +Deno.test(function matrixRotateFromVector() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 2.121320343559643, m21: 0.7071067811865476, m31: 3, m41: 4, + m12: 7.778174593052023, m22: 0.7071067811865479, m32: 7, m42: 8, + m13: 13.435028842544405, m23: 0.7071067811865470, m33: 11, m43: 12, + m14: 19.091883092036785, m24: 0.7071067811865461, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotateFromVector(1, 1); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix2[key], + value, + ); + } +}); + +Deno.test(function matrixRotateFromVectorSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 2.121320343559643, m21: 0.7071067811865476, m31: 3, m41: 4, + m12: 7.778174593052023, m22: 0.7071067811865479, m32: 7, m42: 8, + m13: 13.435028842544405, m23: 0.7071067811865470, m33: 11, m43: 12, + m14: 19.091883092036785, m24: 0.7071067811865461, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotateFromVectorSelf(1, 1); + assertStrictEquals( + matrix, + matrix2, + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix[key], + value, + ); + } +}); + +Deno.test(function matrixRotateAxisAngle() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5.228294835332138, m22: 4.854398120227125, m32: 7.6876363080712045, m42: 8, + m13: 9.456589670664275, m23: 7.708796240454249, m33: 12.3752726161424090, m43: 12, + m14: 13.684884505996411, m24: 10.563194360681376, m34: 17.0629089242136120, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotateAxisAngle(1, 2, 3, 30); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix2[key], + value, + ); + } +}); + +Deno.test(function matrixRotateAxisAngleSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5.228294835332138, m22: 4.854398120227125, m32: 7.6876363080712045, m42: 8, + m13: 9.456589670664275, m23: 7.708796240454249, m33: 12.3752726161424090, m43: 12, + m14: 13.684884505996411, m24: 10.563194360681376, m34: 17.0629089242136120, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.rotateAxisAngleSelf(1, 2, 3, 30); + assertStrictEquals( + matrix, + matrix2, + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix[key], + value, + ); + } +}); + +Deno.test(function matrixSkewX() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 1, m21: 2.5773502691896257, m31: 3, m41: 4, + m12: 5, m22: 8.8867513459481270, m32: 7, m42: 8, + m13: 9, m23: 15.1961524227066300, m33: 11, m43: 12, + m14: 13, m24: 21.5055534994651330, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.skewX(30); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix2[key], + value, + ); + } +}); + +Deno.test(function matrixSkewXSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 1, m21: 2.5773502691896257, m31: 3, m41: 4, + m12: 5, m22: 8.8867513459481270, m32: 7, m42: 8, + m13: 9, m23: 15.1961524227066300, m33: 11, m43: 12, + m14: 13, m24: 21.5055534994651330, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.skewXSelf(30); + assertStrictEquals( + matrix, + matrix2, + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix[key], + value, + ); + } +}); + +Deno.test(function matrixSkewY() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 2.1547005383792515, m21: 2, m31: 3, m41: 4, + m12: 8.4641016151377530, m22: 6, m32: 7, m42: 8, + m13: 14.7735026918962560, m23: 10, m33: 11, m43: 12, + m14: 21.0829037686547600, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.skewY(30); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix2[key], + value, + ); + } +}); + +Deno.test(function matrixSkewYSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + // deno-fmt-ignore + const expect = { + m11: 2.1547005383792515, m21: 2, m31: 3, m41: 4, + m12: 8.4641016151377530, m22: 6, m32: 7, m42: 8, + m13: 14.7735026918962560, m23: 10, m33: 11, m43: 12, + m14: 21.0829037686547600, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.skewYSelf(30); + assertStrictEquals( + matrix, + matrix2, + ); + for ( + const [key, value] of Object.entries(expect) as [ + keyof typeof expect, + number, + ][] + ) { + assertAlmostEquals( + matrix[key], + value, + ); + } +}); + +Deno.test(function matrixMultiply() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.multiply({ m11: 1, m22: 2, m33: 3, m44: 4 }); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 1, m21: 2 * 2, m31: 3 * 3, m41: 4 * 4, + m12: 5 * 1, m22: 6 * 2, m32: 7 * 3, m42: 8 * 4, + m13: 9 * 1, m23: 10 * 2, m33: 11 * 3, m43: 12 * 4, + m14: 13 * 1, m24: 14 * 2, m34: 15 * 3, m44: 16 * 4, + }), + ); +}); + +Deno.test(function matrixMultiplySelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.multiplySelf({ m11: 1, m22: 2, m33: 3, m44: 4 }); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 1, m21: 2 * 2, m31: 3 * 3, m41: 4 * 4, + m12: 5 * 1, m22: 6 * 2, m32: 7 * 3, m42: 8 * 4, + m13: 9 * 1, m23: 10 * 2, m33: 11 * 3, m43: 12 * 4, + m14: 13 * 1, m24: 14 * 2, m34: 15 * 3, m44: 16 * 4, + }), + ); +}); + +Deno.test(function matrixMultiplySelfWithSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.multiplySelf(matrix); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 90, m21: 100, m31: 110, m41: 120, + m12: 202, m22: 228, m32: 254, m42: 280, + m13: 314, m23: 356, m33: 398, m43: 440, + m14: 426, m24: 484, m34: 542, m44: 600, + }), + ); +}); + +Deno.test(function matrixPreMultiplySelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.preMultiplySelf({ m11: 1, m22: 2, m33: 3, m44: 4 }); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1 * 1, m21: 2 * 1, m31: 3 * 1, m41: 4 * 1, + m12: 5 * 2, m22: 6 * 2, m32: 7 * 2, m42: 8 * 2, + m13: 9 * 3, m23: 10 * 3, m33: 11 * 3, m43: 12 * 3, + m14: 13 * 4, m24: 14 * 4, m34: 15 * 4, m44: 16 * 4, + }), + ); +}); + +Deno.test(function matrixPreMultiplySelfWithSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.preMultiplySelf(matrix); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 90, m21: 100, m31: 110, m41: 120, + m12: 202, m22: 228, m32: 254, m42: 280, + m13: 314, m23: 356, m33: 398, m43: 440, + m14: 426, m24: 484, m34: 542, m44: 600, + }), + ); +}); + +Deno.test(function matrixFlipX() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.flipX(); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: -1, m21: 2, m31: 3, m41: 4, + m12: -5, m22: 6, m32: 7, m42: 8, + m13: -9, m23: 10, m33: 11, m43: 12, + m14: -13, m24: 14, m34: 15, m44: 16, + }), + ); +}); + +Deno.test(function matrixFlipY() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 5, m22: 6, m32: 7, m42: 8, + m13: 9, m23: 10, m33: 11, m43: 12, + m14: 13, m24: 14, m34: 15, m44: 16, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.flipY(); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: -2, m31: 3, m41: 4, + m12: 5, m22: -6, m32: 7, m42: 8, + m13: 9, m23: -10, m33: 11, m43: 12, + m14: 13, m24: -14, m34: 15, m44: 16, + }), + ); +}); + +Deno.test(function matrixInverse() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 0, m22: 1, m32: 7, m42: 8, + m13: 0, m23: 0, m33: 1, m43: 12, + m14: 0, m24: 0, m34: 0, m44: 1, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.inverse(); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: -2, m31: 11, m41: -120, + m12: 0, m22: 1, m32: -7, m42: 76, + m13: 0, m23: 0, m33: 1, m43: -12, + m14: 0, m24: 0, m34: 0, m44: 1, + }), + ); +}); + +Deno.test(function matrixInvertSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 3, m41: 4, + m12: 0, m22: 1, m32: 7, m42: 8, + m13: 0, m23: 0, m33: 1, m43: 12, + m14: 0, m24: 0, m34: 0, m44: 1, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.invertSelf(); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: -2, m31: 11, m41: -120, + m12: 0, m22: 1, m32: -7, m42: 76, + m13: 0, m23: 0, m33: 1, m43: -12, + m14: 0, m24: 0, m34: 0, m44: 1, + }), + ); +}); + +Deno.test(function matrixInverse2D() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 0, m41: 4, + m12: 0, m22: 1, m32: 0, m42: 8, + m13: 0, m23: 0, m33: 1, m43: 0, + m14: 0, m24: 0, m34: 0, m44: 1, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.inverse(); + assertEquals( + matrix, + DOMMatrix.fromMatrix(init), + ); + assertEquals( + matrix2, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: -2, m31: 0, m41: 12, + m12: 0, m22: 1, m32: 0, m42: -8, + m13: 0, m23: 0, m33: 1, m43: 0, + m14: 0, m24: 0, m34: 0, m44: 1, + }), + ); +}); + +Deno.test(function matrixInvert2DSelf() { + // deno-fmt-ignore + const init = { + m11: 1, m21: 2, m31: 0, m41: 4, + m12: 0, m22: 1, m32: 0, m42: 8, + m13: 0, m23: 0, m33: 1, m43: 0, + m14: 0, m24: 0, m34: 0, m44: 1, + }; + const matrix = DOMMatrix.fromMatrix(init); + const matrix2 = matrix.invertSelf(); + assertStrictEquals( + matrix, + matrix2, + ); + assertEquals( + matrix, + // deno-fmt-ignore + DOMMatrix.fromMatrix({ + m11: 1, m21: -2, m31: 0, m41: 12, + m12: 0, m22: 1, m32: 0, m42: -8, + m13: 0, m23: 0, m33: 1, m43: 0, + m14: 0, m24: 0, m34: 0, m44: 1, + }), + ); +}); + +Deno.test(function prototypeOverwrite() { + const point = new DOMPointReadOnly(); + Object.setPrototypeOf(point, DOMPoint.prototype); + assertThrows( + () => { + // @ts-ignore test + point.x = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + point.y = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + point.z = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + point.w = 1; + }, + TypeError, + "Illegal invocation", + ); + + const rect = new DOMRectReadOnly(); + Object.setPrototypeOf(rect, DOMRect.prototype); + assertThrows( + () => { + // @ts-ignore test + rect.x = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + rect.y = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + rect.width = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + rect.height = 1; + }, + TypeError, + "Illegal invocation", + ); + + const matrix = new DOMMatrixReadOnly(); + Object.setPrototypeOf(matrix, DOMMatrix.prototype); + assertThrows( + () => { + // @ts-ignore test + matrix.a = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.b = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.c = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.d = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.e = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.f = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m11 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m12 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m13 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m14 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m21 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m22 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m23 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m24 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m31 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m32 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m33 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m34 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m41 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m42 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m43 = 1; + }, + TypeError, + "Illegal invocation", + ); + assertThrows( + () => { + // @ts-ignore test + matrix.m44 = 1; + }, + TypeError, + "Illegal invocation", + ); +}); diff --git a/tests/unit/test_util.ts b/tests/unit/test_util.ts index e45a963e9a1764..65c5a415a78700 100644 --- a/tests/unit/test_util.ts +++ b/tests/unit/test_util.ts @@ -6,6 +6,7 @@ export { colors }; import { join, resolve } from "@std/path"; export { assert, + assertAlmostEquals, assertEquals, assertFalse, AssertionError, diff --git a/tests/wpt/runner/expectation.json b/tests/wpt/runner/expectation.json index f59806feae3127..d12f71fdc71a33 100644 --- a/tests/wpt/runner/expectation.json +++ b/tests/wpt/runner/expectation.json @@ -15146,18 +15146,222 @@ "request-accept.any.worker.html": true, "request-cache-control.any.html": false, "request-cache-control.any.worker.html": false, + "request-status-error.window.html": false, "eventsource-close.window.html": false, "eventsource-constructor-document-domain.window.html": false, "eventsource-constructor-non-same-origin.window.html": false, "eventsource-constructor-stringify.window.html": false, "eventsource-cross-origin.window.html": false, "eventsource-reconnect.window.html": false, - "request-status-error.window.html": false, "eventsource-constructor-empty-url.any.serviceworker.html": false, "eventsource-constructor-empty-url.any.sharedworker.html": false, "eventsource-constructor-url-bogus.any.serviceworker.html": false, "eventsource-constructor-url-bogus.any.sharedworker.html": false, "request-credentials.window.html": false, "request-redirect.window.html": false + }, + "css": { + "geometry": { + "DOMMatrix-001.html": [ + "new DOMMatrix(\"none\")", + "new DOMMatrix(\" none\")", + "new DOMMatrix(\"none \")", + "new DOMMatrix(\"NONE\")", + "new DOMMatrix(\"none/**/\")", + "new DOMMatrix(\"/**/none\")", + "new DOMMatrix(\"scale(2) translateX(5px) translateY(5px)\")", + "new DOMMatrix(\"scale(2, 2) translateX(5px) translateY(5px)\")", + "new DOMMatrix(\"scale(2)translateX(5px)translateY(5px)\")", + "new DOMMatrix(\"scale(2) translateX(calc(2 * 2.5px)) translateY(5px)\")", + "new DOMMatrix(\"scale(2) translateX(5px) translateY(5px) rotate(5deg) rotate(-5deg)\")", + "new DOMMatrix(\"translateX (5px)\")", + "new DOMMatrix(\"scale(2 2) translateX(5) translateY(5)\")", + "new DOMMatrix(\"scale(2, 2), translateX(5) ,translateY(5)\")", + "new DOMMatrix(\"translateX(5em)\")", + "new DOMMatrix(\"translateX(5ex)\")", + "new DOMMatrix(\"translateX(5ch)\")", + "new DOMMatrix(\"translateX(5rem)\")", + "new DOMMatrix(\"translateX(5cqw)\")", + "new DOMMatrix(\"translateX(5cqh)\")", + "new DOMMatrix(\"translateX(5cqb)\")", + "new DOMMatrix(\"translateX(5cqi)\")", + "new DOMMatrix(\"translateX(5cqmin)\")", + "new DOMMatrix(\"translateX(5cqmax)\")", + "new DOMMatrix(\"translateX(5vw)\")", + "new DOMMatrix(\"translateX(5vh)\")", + "new DOMMatrix(\"translateX(5vb)\")", + "new DOMMatrix(\"translateX(5vi)\")", + "new DOMMatrix(\"translateX(5vmin)\")", + "new DOMMatrix(\"translateX(5vmax)\")", + "new DOMMatrix(\"translateX(5%)\")", + "new DOMMatrix(\"rotate(5)\")", + "new DOMMatrix(\"rotate(5, 5, 5)\")", + "new DOMMatrix(\"rotate(5, 5px, 5px)\")", + "new DOMMatrix(\"rotate(5deg, 5px, 5px)\")", + "new DOMMatrix(\" \")", + "new DOMMatrix(\"/**/\")", + "new DOMMatrix(\"\\0\")", + "new DOMMatrix(\";\")", + "new DOMMatrix(\"none;\")", + "new DOMMatrix(\"null\")", + "new DOMMatrix(null)", + "new DOMMatrix(\"undefined\")", + "new DOMMatrix(\"inherit\")", + "new DOMMatrix(\"initial\")", + "new DOMMatrix(\"unset\")", + "new DOMMatrix(\"scale(2, 2), translateX(5px) translateY(5px)\")", + "new DOMMatrixReadOnly(\"none\")", + "new DOMMatrixReadOnly(\" none\")", + "new DOMMatrixReadOnly(\"none \")", + "new DOMMatrixReadOnly(\"NONE\")", + "new DOMMatrixReadOnly(\"none/**/\")", + "new DOMMatrixReadOnly(\"/**/none\")", + "new DOMMatrixReadOnly(\"scale(2) translateX(5px) translateY(5px)\")", + "new DOMMatrixReadOnly(\"scale(2, 2) translateX(5px) translateY(5px)\")", + "new DOMMatrixReadOnly(\"scale(2)translateX(5px)translateY(5px)\")", + "new DOMMatrixReadOnly(\"scale(2) translateX(calc(2 * 2.5px)) translateY(5px)\")", + "new DOMMatrixReadOnly(\"scale(2) translateX(5px) translateY(5px) rotate(5deg) rotate(-5deg)\")", + "new DOMMatrixReadOnly(\"translateX (5px)\")", + "new DOMMatrixReadOnly(\"scale(2 2) translateX(5) translateY(5)\")", + "new DOMMatrixReadOnly(\"scale(2, 2), translateX(5) ,translateY(5)\")", + "new DOMMatrixReadOnly(\"translateX(5em)\")", + "new DOMMatrixReadOnly(\"translateX(5ex)\")", + "new DOMMatrixReadOnly(\"translateX(5ch)\")", + "new DOMMatrixReadOnly(\"translateX(5rem)\")", + "new DOMMatrixReadOnly(\"translateX(5cqw)\")", + "new DOMMatrixReadOnly(\"translateX(5cqh)\")", + "new DOMMatrixReadOnly(\"translateX(5cqb)\")", + "new DOMMatrixReadOnly(\"translateX(5cqi)\")", + "new DOMMatrixReadOnly(\"translateX(5cqmin)\")", + "new DOMMatrixReadOnly(\"translateX(5cqmax)\")", + "new DOMMatrixReadOnly(\"translateX(5vw)\")", + "new DOMMatrixReadOnly(\"translateX(5vh)\")", + "new DOMMatrixReadOnly(\"translateX(5vb)\")", + "new DOMMatrixReadOnly(\"translateX(5vi)\")", + "new DOMMatrixReadOnly(\"translateX(5vmin)\")", + "new DOMMatrixReadOnly(\"translateX(5vmax)\")", + "new DOMMatrixReadOnly(\"translateX(5%)\")", + "new DOMMatrixReadOnly(\"rotate(5)\")", + "new DOMMatrixReadOnly(\"rotate(5, 5, 5)\")", + "new DOMMatrixReadOnly(\"rotate(5, 5px, 5px)\")", + "new DOMMatrixReadOnly(\"rotate(5deg, 5px, 5px)\")", + "new DOMMatrixReadOnly(\" \")", + "new DOMMatrixReadOnly(\"/**/\")", + "new DOMMatrixReadOnly(\"\\0\")", + "new DOMMatrixReadOnly(\";\")", + "new DOMMatrixReadOnly(\"none;\")", + "new DOMMatrixReadOnly(\"null\")", + "new DOMMatrixReadOnly(null)", + "new DOMMatrixReadOnly(\"undefined\")", + "new DOMMatrixReadOnly(\"inherit\")", + "new DOMMatrixReadOnly(\"initial\")", + "new DOMMatrixReadOnly(\"unset\")", + "new DOMMatrixReadOnly(\"scale(2, 2), translateX(5px) translateY(5px)\")" + ], + "DOMMatrix-002.html": true, + "DOMMatrix-003.html": true, + "DOMMatrix-a-f-alias.html": true, + "DOMMatrix-attributes.html": true, + "DOMMatrix-css-string.worker.html": true, + "DOMMatrix-invert-invertible.html": true, + "DOMMatrix-invert-non-invertible.html": true, + "DOMMatrix-invert-preserves-2d.html": true, + "DOMMatrix-newobject.html": true, + "DOMMatrix-stringifier.html": [ + "WebKitCSSMatrix stringifier: identity (2d)", + "WebKitCSSMatrix stringifier: identity (3d)", + "WebKitCSSMatrix stringifier: NaN (2d)", + "WebKitCSSMatrix stringifier: NaN (3d)", + "WebKitCSSMatrix stringifier: Infinity (2d)", + "WebKitCSSMatrix stringifier: Infinity (3d)", + "WebKitCSSMatrix stringifier: -Infinity (2d)", + "WebKitCSSMatrix stringifier: -Infinity (3d)", + "WebKitCSSMatrix stringifier: 1/3 (2d)", + "WebKitCSSMatrix stringifier: 1/3 (3d)", + "WebKitCSSMatrix stringifier: 1/300000 (2d)", + "WebKitCSSMatrix stringifier: 1/300000 (3d)", + "WebKitCSSMatrix stringifier: 1/300000000 (2d)", + "WebKitCSSMatrix stringifier: 1/300000000 (3d)", + "WebKitCSSMatrix stringifier: 100000 + (1/3) (2d)", + "WebKitCSSMatrix stringifier: 100000 + (1/3) (3d)", + "WebKitCSSMatrix stringifier: Math.pow(2, 53) + 1 (2d)", + "WebKitCSSMatrix stringifier: Math.pow(2, 53) + 1 (3d)", + "WebKitCSSMatrix stringifier: Math.pow(2, 53) + 2 (2d)", + "WebKitCSSMatrix stringifier: Math.pow(2, 53) + 2 (3d)", + "WebKitCSSMatrix stringifier: Number.MAX_VALUE (2d)", + "WebKitCSSMatrix stringifier: Number.MAX_VALUE (3d)", + "WebKitCSSMatrix stringifier: Number.MIN_VALUE (2d)", + "WebKitCSSMatrix stringifier: Number.MIN_VALUE (3d)", + "WebKitCSSMatrix stringifier: throwing getters (2d)", + "WebKitCSSMatrix stringifier: throwing getters (3d)" + ], + "DOMMatrix2DInit-validate-fixup.html": false, + "DOMMatrixInit-validate-fixup.html": true, + "DOMPoint-001.html": true, + "DOMPoint-002.html": true, + "DOMQuad-001.html": true, + "DOMQuad-002.html": true, + "DOMQuad-nan.html": true, + "DOMRect-001.html": true, + "DOMRect-002.html": true, + "DOMRect-nan.html": true, + "DOMRectList.html": false, + "WebKitCSSMatrix.html": false, + "WebKitCSSMatrix.worker.html": true, + "historical.html": true, + "idlharness.any.html": [ + "DOMPointReadOnly interface: existence and properties of interface object", + "DOMPoint interface: existence and properties of interface object", + "DOMRectReadOnly interface: existence and properties of interface object", + "DOMRect interface: existence and properties of interface object", + "DOMRectList interface: existence and properties of interface object", + "DOMRectList interface object length", + "DOMRectList interface object name", + "DOMRectList interface: existence and properties of interface prototype object", + "DOMRectList interface: existence and properties of interface prototype object's \"constructor\" property", + "DOMRectList interface: existence and properties of interface prototype object's @@unscopables property", + "DOMRectList interface: attribute length", + "DOMRectList interface: operation item(unsigned long)", + "DOMQuad interface: existence and properties of interface object", + "DOMMatrixReadOnly interface: existence and properties of interface object", + "DOMMatrix interface: existence and properties of interface object" + ], + "idlharness.any.worker.html": [ + "DOMPointReadOnly interface: existence and properties of interface object", + "DOMPoint interface: existence and properties of interface object", + "DOMRectReadOnly interface: existence and properties of interface object", + "DOMRect interface: existence and properties of interface object", + "DOMQuad interface: existence and properties of interface object", + "DOMMatrixReadOnly interface: existence and properties of interface object", + "DOMMatrix interface: existence and properties of interface object" + ], + "spec-examples.html": true, + "structured-serialization.html": [ + "DOMPointReadOnly clone: basic", + "DOMPointReadOnly clone: custom property", + "DOMPointReadOnly clone: non-initial values", + "DOMPoint clone: basic", + "DOMPoint clone: custom property", + "DOMPoint clone: non-initial values", + "DOMRectReadOnly clone: basic", + "DOMRectReadOnly clone: custom property", + "DOMRectReadOnly clone: non-initial values", + "DOMRect clone: basic", + "DOMRect clone: custom property", + "DOMRect clone: non-initial values", + "DOMQuad clone: basic", + "DOMQuad clone: custom property", + "DOMQuad clone: non-initial values", + "DOMMatrixReadOnly clone: basic", + "DOMMatrixReadOnly clone: custom property", + "DOMMatrixReadOnly clone: non-initial values (2d)", + "DOMMatrixReadOnly clone: non-initial values (3d)", + "DOMMatrix clone: basic", + "DOMMatrix clone: custom property", + "DOMMatrix clone: non-initial values (2d)", + "DOMMatrix clone: non-initial values (3d)", + "DOMRectList clone" + ] + } } } diff --git a/tools/core_import_map.json b/tools/core_import_map.json index d31821fb7f76e8..1a8e94a001731c 100644 --- a/tools/core_import_map.json +++ b/tools/core_import_map.json @@ -17,6 +17,8 @@ "ext:deno_fetch/26_fetch.js": "../ext/fetch/26_fetch.js", "ext:deno_ffi/00_ffi.js": "../ext/ffi/00_ffi.js", "ext:deno_fs/30_fs.js": "../ext/fs/30_fs.js", + "ext:deno_geometry/00_init.js": "../ext/geometry/00_init.js", + "ext:deno_geometry/01_geometry.js": "../ext/geometry/01_geometry.js", "ext:deno_http/00_serve.ts": "../ext/http/00_serve.ts", "ext:deno_http/01_http.js": "../ext/http/01_http.js", "ext:deno_io/12_io.js": "../ext/io/12_io.js", diff --git a/tools/jsdoc_checker.js b/tools/jsdoc_checker.js index 3e5dc03718e472..b791d63cf78b69 100755 --- a/tools/jsdoc_checker.js +++ b/tools/jsdoc_checker.js @@ -13,6 +13,7 @@ const libs = [ join(ROOT_PATH, "ext/webstorage/lib.deno_webstorage.d.ts"), join(ROOT_PATH, "ext/canvas/lib.deno_canvas.d.ts"), join(ROOT_PATH, "ext/crypto/lib.deno_crypto.d.ts"), + join(ROOT_PATH, "ext/geometry/lib.deno_geometry.d.ts"), join(ROOT_PATH, "ext/net/lib.deno_net.d.ts"), join(ROOT_PATH, "cli/tsc/dts/lib.deno.ns.d.ts"), join(ROOT_PATH, "cli/tsc/dts/lib.deno.shared_globals.d.ts"),