summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/geometry
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/css/geometry')
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-001.html204
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-002.html113
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-003.html318
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-a-f-alias.html57
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-attributes.html66
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-css-string.worker.js38
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-invert-invertible.html76
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-invert-non-invertible.html50
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-invert-preserves-2d.html41
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-newobject.html44
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix-stringifier.html79
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrix2DInit-validate-fixup.html147
-rw-r--r--testing/web-platform/tests/css/geometry/DOMMatrixInit-validate-fixup.html132
-rw-r--r--testing/web-platform/tests/css/geometry/DOMPoint-001.html83
-rw-r--r--testing/web-platform/tests/css/geometry/DOMPoint-002.html177
-rw-r--r--testing/web-platform/tests/css/geometry/DOMQuad-001.html156
-rw-r--r--testing/web-platform/tests/css/geometry/DOMQuad-002.html173
-rw-r--r--testing/web-platform/tests/css/geometry/DOMQuad-nan.html34
-rw-r--r--testing/web-platform/tests/css/geometry/DOMRect-001.html161
-rw-r--r--testing/web-platform/tests/css/geometry/DOMRect-002.html171
-rw-r--r--testing/web-platform/tests/css/geometry/DOMRect-nan.html79
-rw-r--r--testing/web-platform/tests/css/geometry/DOMRectList.html36
-rw-r--r--testing/web-platform/tests/css/geometry/META.yml4
-rw-r--r--testing/web-platform/tests/css/geometry/WebKitCSSMatrix.html25
-rw-r--r--testing/web-platform/tests/css/geometry/WebKitCSSMatrix.worker.js9
-rw-r--r--testing/web-platform/tests/css/geometry/historical.html91
-rw-r--r--testing/web-platform/tests/css/geometry/idlharness.any.js32
-rw-r--r--testing/web-platform/tests/css/geometry/spec-examples.html92
-rw-r--r--testing/web-platform/tests/css/geometry/structured-serialization.html165
-rw-r--r--testing/web-platform/tests/css/geometry/support/dommatrix-test-util.js85
30 files changed, 2938 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-001.html b/testing/web-platform/tests/css/geometry/DOMMatrix-001.html
new file mode 100644
index 0000000000..1752c2c5ca
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-001.html
@@ -0,0 +1,204 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Geometry Interfaces: DOMMatrix and DOMMatrixReadOnly constructors</title>
+ <link rel="author" title="Dirk Schulze" href="mailto:dschulze@adobe.com" />
+ <link rel="help" href="https://drafts.fxtf.org/geometry/#DOMMatrix">
+ <link rel="help" href="https://drafts.fxtf.org/geometry/#dommatrix-constructors">
+ <link rel="help" href="https://drafts.fxtf.org/geometry/#dom-dommatrix-dommatrix">
+ <script src="support/dommatrix-test-util.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script>
+ var initial = {
+ m11: 1, m21: 0, m31: 0, m41: 0,
+ m12: 0, m22: 1, m32: 0, m42: 0,
+ m13: 0, m23: 0, m33: 1, m43: 0,
+ m14: 0, m24: 0, m34: 0, m44: 1,
+ is2D: true,
+ isIdentity: true
+ };
+ var scaleTranslate2D = {
+ m11: 2, m21: 0, m31: 0, m41: 10,
+ m12: 0, m22: 2, m32: 0, m42: 10,
+ m13: 0, m23: 0, m33: 1, m43: 0,
+ m14: 0, m24: 0, m34: 0, m44: 1,
+ is2D: true,
+ isIdentity: false
+ };
+ ["DOMMatrix", "DOMMatrixReadOnly"].forEach(function(constr) {
+ test(function() {
+ checkDOMMatrix(new self[constr](), initial);
+ }, `new ${constr}()`);
+
+ test(function() {
+ checkDOMMatrix(new self[constr](undefined), initial);
+ }, `new ${constr}(undefined)`);
+
+ test(function() {
+ checkDOMMatrix(new self[constr](new self[constr]()), initial);
+ }, `new ${constr}(new ${constr}())`);
+
+ ['none',
+ ' none',
+ 'none ',
+ 'NONE',
+ 'none/**/',
+ '/**/none',
+ '',
+ ].forEach(function(string) {
+ test(function() {
+ checkDOMMatrix(new self[constr](string), initial);
+ }, `new ${constr}(${format_value(string)})`);
+ });
+
+ test(function() {
+ var float32Array = new Float32Array([
+ 2.0, 0.0, 0.0, 0.0,
+ 0.0, 2.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 10.0, 10.0, 0.0, 1.0]);
+ checkDOMMatrix(new self[constr](float32Array), scaleTranslate2D, false);
+ }, `new ${constr}(float32Array) 16 elements`);
+
+ test(function() {
+ var float32Array = new Float32Array([2.0, 0.0, 0.0, 2.0, 10.0, 10.0]);
+ checkDOMMatrix(new self[constr](float32Array), scaleTranslate2D);
+ }, `new ${constr}(float32Array) 6 elements`);
+
+ test(function() {
+ var float64Array = new Float64Array([
+ 2.0, 0.0, 0.0, 0.0,
+ 0.0, 2.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 10.0, 10.0, 0.0, 1.0]);
+ checkDOMMatrix(new self[constr](float64Array), scaleTranslate2D, false);
+ }, `new ${constr}(float64Array) 16 elements`);
+
+ test(function() {
+ var float64Array = new Float64Array([2.0, 0.0, 0.0, 2.0, 10.0, 10.0]);
+ checkDOMMatrix(new self[constr](float64Array), scaleTranslate2D);
+ }, `new ${constr}((float64Array) 6 elements`);
+
+ [
+ [2.0, 0.0, 0.0, 0.0,
+ 0.0, 2.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 10.0, 10.0, 0.0, 1.0],
+ [2.0, 0.0, 0.0, 2.0, 10.0, 10.0],
+ ].forEach(function(sequence) {
+ test(function() {
+ checkDOMMatrix(new self[constr](sequence), scaleTranslate2D,
+ sequence.length == 6);
+ }, `new ${constr}(sequence) ${sequence.length} elements`);
+ });
+
+ {
+ const epsilon = 0.0000000005;
+ ['scale(2) translateX(5px) translateY(5px)',
+ 'scale(2, 2) translateX(5px) translateY(5px)',
+ 'scale(2)translateX(5px)translateY(5px)',
+ 'scale(2) translateX(calc(2 * 2.5px)) translateY(5px)',
+ 'scale(2) translateX(5px) translateY(5px) rotate(5deg) rotate(-5deg)',
+ ].forEach(function(string) {
+ test(function() {
+ checkMatrix(new self[constr](string), scaleTranslate2D, { epsilon });
+ }, `new ${constr}(${format_value(string)})`);
+ });
+ }
+
+ ['translateX (5px)',
+ 'scale(2 2) translateX(5) translateY(5)',
+ 'scale(2, 2), translateX(5) ,translateY(5)',
+ 'translateX(5em)',
+ 'translateX(5ex)',
+ 'translateX(5ch)',
+ 'translateX(5rem)',
+ 'translateX(5vw)',
+ 'translateX(5vh)',
+ 'translateX(5vmin)',
+ 'translateX(5vmax)',
+ 'translateX(5%)',
+ 'rotate(5)',
+ 'rotate(5, 5, 5)',
+ 'rotate(5, 5px, 5px)',
+ 'rotate(5deg, 5px, 5px)',
+ ' ',
+ '/**/',
+ '\0',
+ ';',
+ 'none;',
+ 'null',
+ null, // is converted to 'null' by IDL
+ 'undefined',
+ 'inherit',
+ 'initial',
+ 'unset',
+ ].forEach(function(string) {
+ test(function() {
+ assert_throws_dom('SyntaxError', function() { new self[constr](string); });
+ }, `new ${constr}(${format_value(string)})`);
+ });
+
+ test(function() {
+ var sequence = [
+ 2.0, 1.0, 0.0, 0.0,
+ 1.0, 2.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 10.0, 10.0, 0.0, 1.0];
+ checkDOMMatrix(new self[constr](sequence), {
+ m11: 2, m21: 1, m31: 0, m41: 10,
+ m12: 1, m22: 2, m32: 0, m42: 10,
+ m13: 0, m23: 0, m33: 1, m43: 0,
+ m14: 0, m24: 0, m34: 0, m44: 1,
+ is2D: false,
+ isIdentity: false
+ });
+ }, `new ${constr}(sequence)`);
+
+ test(function() {
+ var matrix = new self[constr]([
+ 2.0, 1.0, 0.0, 0.0,
+ 1.0, 2.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 10.0, 10.0, 0.0, 1.0]);
+ checkDOMMatrix(new self[constr](matrix), {
+ m11: 2, m21: 1, m31: 0, m41: 10,
+ m12: 1, m22: 2, m32: 0, m42: 10,
+ m13: 0, m23: 0, m33: 1, m43: 0,
+ m14: 0, m24: 0, m34: 0, m44: 1,
+ is2D: false,
+ isIdentity: false
+ });
+ }, `new ${constr}(matrix)`);
+
+ ['scale(2, 2), translateX(5px) translateY(5px)',
+ ].forEach(function(string) {
+ test(function() {
+ assert_throws_dom("SyntaxError", function() { new self[constr](string); });
+ }, `new ${constr}(${format_value(string)})`);
+ });
+
+ [
+ [2.0, 0.0, 0.0, 0.0,
+ 0.0, 2.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 10.0, 10.0, 0.0, 2.0, 0.0], // 17 elements
+ [2.0, 0.0, 0.0, 0.0,
+ 0.0, 2.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 10.0, 10.0, 0.0], // 15 elements
+ [2.0, 0.0, 0.0, 2.0, 10.0], // 5 elements
+ [], // 0 elements
+ ].forEach(function(sequence) {
+ test(function() {
+ assert_throws_js(TypeError, function() { new self[constr](sequence); });
+ }, `new ${constr}(sequence) ${sequence.length} elements`);
+ });
+ });
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-002.html b/testing/web-platform/tests/css/geometry/DOMMatrix-002.html
new file mode 100644
index 0000000000..c262f7822f
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-002.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Geometry Interfaces: DOMMatrixReadOnly methods do not mutate the object</title>
+ <link href="mailto:peter.hall@algomi.com" rel="author" title="Peter Hall">
+ <link rel="help" href="https://drafts.fxtf.org/geometry-1/#DOMMatrix">
+ <script src="support/dommatrix-test-util.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <p>Test DOMMatrixReadOnly methods do not mutate the object</p>
+ <div id="log"></div>
+ <script>
+
+ function initialMatrix(){
+ return DOMMatrixReadOnly.fromMatrix(
+ {
+ m11:1, m12:-0.5, m13: 0.5, m14:0,
+ m21:0.5, m22:2, m23: -0.5, m24:0,
+ m31:0, m32:0, m33: 1, m34:0,
+ m41:0, m42:0, m43: 0, m44:1,
+ is2D: false
+ }
+ );
+ }
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.translate(1,5,3);
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test translate() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.scale(1,5,3,0,1,3);
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test scale() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.scaleNonUniform(1,5);
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test scaleNonUniform() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.scale3d(3,2,1,1);
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test scale3d() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.rotate(Math.PI, Math.PI/2, Math.PI/6);
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test rotate() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.rotateFromVector(10,-4);
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test rotateFromVector() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.rotateAxisAngle(3,4,5, Math.PI/6);
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test rotateAxisAngle() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.skewX(20);
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test skewX() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.skewY(20);
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test skewY() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.multiply({ m11:1, m12:2, m13: 0, m14:0,
+ m21:-1, m22:2, m23: -1, m24:0,
+ m31:0, m32:0, m33: 1, m34:0,
+ m41:5, m42:0, m43: 2, m44:1,
+ is2D: false,
+ isIdentity:false });
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test multiply() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.flipX();
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test flipX() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.flipY();
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test flipY() doesn't mutate");
+
+ test(function() {
+ var matrix = initialMatrix();
+ matrix.inverse();
+ checkDOMMatrix(matrix, initialMatrix());
+ },"test inverse() doesn't mutate");
+
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-003.html b/testing/web-platform/tests/css/geometry/DOMMatrix-003.html
new file mode 100644
index 0000000000..56f463e2ac
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-003.html
@@ -0,0 +1,318 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Geometry Interfaces: Test DOMMatrix non-mutating methods</title>
+ <link href="mailto:peter.hall@algomi.com" rel="author" title="Peter Hall">
+ <link rel="help" href="https://drafts.fxtf.org/geometry-1/#DOMMatrix">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <p>Test DOMMatrix non-mutating methods</p>
+ <div id="log"></div>
+ <script>
+ var epsilon = 0.0000000005;
+
+ function initialMatrix(){
+ return {
+ m11:1, m12:-0.5, m13: 0.5, m14:0,
+ m21:0.5, m22:2, m23: -0.5, m24:0,
+ m31:0, m32:0, m33: 1, m34:0,
+ m41:10, m42:20, m43: 10, m44:1,
+ is2D: false
+ };
+ }
+
+ function initialDOMMatrix() {
+ return DOMMatrixReadOnly.fromMatrix(initialMatrix())
+ }
+
+ function identity() {
+ return new DOMMatrix(
+ [1, 0, 0, 0,
+ 0, 1, 0 ,0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1]);
+ }
+
+ function update(matrix, f) {
+ f(matrix);
+ return matrix;
+ }
+
+ function deg2rad(degrees) {
+ return degrees * Math.PI / 180;
+ }
+
+ function getRotationMatrix(x, y, z, alpha_in_degrees) {
+ // Vector normalizing
+ var nx = x;
+ var ny = y;
+ var nz = z;
+ var length = Math.sqrt(x * x + y * y + z * z);
+ if (length) {
+ nx = x / length;
+ ny = y / length;
+ nz = z / length;
+ }
+
+ // The 3D rotation matrix is described in CSS Transforms with alpha.
+ // Please see: https://drafts.csswg.org/css-transforms-2/#Rotate3dDefined
+ var alpha_in_radians = deg2rad(alpha_in_degrees / 2);
+ var sc = Math.sin(alpha_in_radians) * Math.cos(alpha_in_radians);
+ var sq = Math.sin(alpha_in_radians) * Math.sin(alpha_in_radians);
+
+ var m11 = 1 - 2 * (ny * ny + nz * nz) * sq;
+ var m12 = 2 * (nx * ny * sq + nz * sc);
+ var m13 = 2 * (nx * nz * sq - ny * sc);
+ var m14 = 0;
+ var m21 = 2 * (nx * ny * sq - nz * sc);
+ var m22 = 1 - 2 * (nx * nx + nz * nz) * sq;
+ var m23 = 2 * (ny * nz * sq + nx * sc);
+ var m24 = 0;
+ var m31 = 2 * (nx * nz * sq + ny * sc);
+ var m32 = 2 * (ny * nz * sq - nx * sc);
+ var m33 = 1 - 2 * (nx * nx + ny * ny) * sq;
+ var m34 = 0;
+ var m41 = 0;
+ var m42 = 0;
+ var m43 = 0;
+ var m44 = 1;
+
+ return new DOMMatrix([
+ m11, m12, m13, m14,
+ m21, m22, m23, m24,
+ m31, m32, m33, m34,
+ m41, m42, m43, m44]);
+ }
+
+ function getMatrixTransform(matrix, point) {
+ var x = point.x * matrix.m11 + point.y * matrix.m21 + point.z * matrix.m31 + point.w * matrix.m41;
+ var y = point.x * matrix.m12 + point.y * matrix.m22 + point.z * matrix.m32 + point.w * matrix.m42;
+ var w = point.x * matrix.m13 + point.y * matrix.m23 + point.z * matrix.m33 + point.w * matrix.m43;
+ var z = point.x * matrix.m14 + point.y * matrix.m24 + point.z * matrix.m34 + point.w * matrix.m44;
+ return new DOMPoint(x, y, w, z)
+ }
+
+ test(function() {
+ var tx = 1;
+ var ty = 5;
+ var tz = 3;
+ var result = initialDOMMatrix().translate(tx, ty, tz);
+ var expected = update(initialMatrix(), function(m) {
+ m.m41 += tx * m.m11 + ty * m.m21 + tz * m.m31;
+ m.m42 += tx * m.m12 + ty * m.m22 + tz * m.m32;
+ m.m43 += tx * m.m13 + ty * m.m23 + tz * m.m33;
+ m.m44 += tx * m.m14 + ty * m.m24 + tz * m.m34;
+ });
+ checkDOMMatrix(result, expected);
+ },"test translate()");
+
+ test(function() {
+ var sx = 2;
+ var sy = 5;
+ var sz = 3;
+ var result = initialDOMMatrix().scale(sx, sy, sz);
+ var expected = update(initialMatrix(), function(m) {
+ m.m11 *= sx;
+ m.m12 *= sx;
+ m.m13 *= sx;
+ m.m14 *= sx;
+ m.m21 *= sy;
+ m.m22 *= sy;
+ m.m23 *= sy;
+ m.m24 *= sy;
+ m.m31 *= sz;
+ m.m32 *= sz;
+ m.m33 *= sz;
+ m.m34 *= sz;
+ });
+ checkDOMMatrix(result, expected);
+ },"test scale() without offsets");
+
+ test(function() {
+ var result = initialDOMMatrix().scale(2, 5, 3, 11, 7, 13);
+ var expected = initialDOMMatrix()
+ .translate(11, 7, 13)
+ .scale(2, 5, 3)
+ .translate(-11, -7, -13);
+ checkDOMMatrix(result, expected);
+ },"test scale() with offsets");
+
+ test(function() {
+ var result = new DOMMatrixReadOnly([1, 2, 3, 4, 5, 6])
+ .scale(1, 1, 1, 1, 1, 1);
+ var expected = new DOMMatrixReadOnly([1, 2, 0, 0, 3, 4, 0, 0, 0, 0, 1, 0, 5, 6, 0, 1]);
+ checkDOMMatrix(result, expected);
+ },"test scale() with identity scale and nonzero originZ");
+
+ test(function() {
+ var result = initialDOMMatrix().scaleNonUniform();
+ var expected = initialDOMMatrix()
+ .scale(1, 1, 1, 0, 0, 0);
+ checkDOMMatrix(result, expected);
+ },"test scaleNonUniform()");
+
+ test(function() {
+ var result = initialDOMMatrix().scaleNonUniform(6);
+ var expected = initialDOMMatrix()
+ .scale(6, 1, 1, 0, 0, 0);
+ checkDOMMatrix(result, expected);
+ },"test scaleNonUniform() with sx");
+
+ test(function() {
+ var result = initialDOMMatrix().scaleNonUniform(5, 7);
+ var expected = initialDOMMatrix()
+ .scale(5, 7, 1, 0, 0, 0);
+ checkDOMMatrix(result, expected);
+ },"test scaleNonUniform() with sx, sy");
+
+ test(function() {
+ var result = initialDOMMatrix().scale3d(7, 5, 2, 3);
+ var expected = initialDOMMatrix()
+ .translate(5, 2, 3)
+ .scale(7, 7, 7)
+ .translate(-5, -2, -3);
+ checkDOMMatrix(result, expected);
+ },"test scale3d()");
+
+ test(function() {
+ var result = initialDOMMatrix().rotate(-90);
+ var expected = initialDOMMatrix().multiply(getRotationMatrix(0, 0, 1, -90));
+ checkDOMMatrix(result, expected);
+ },"test rotate() 2d");
+
+ test(function() {
+ var result = initialDOMMatrix().rotate(180, 180, 90);
+ var expected = initialDOMMatrix().rotate(0,0,-90);
+ checkDOMMatrix(result, expected);
+ },"test rotate()");
+
+ test(function() {
+ var result = initialDOMMatrix().rotate(90, 90, 90);
+ var expected = initialDOMMatrix()
+ .rotate(0, 0, 90)
+ .rotate(0, 90, 0)
+ .rotate(90, 0, 0);
+ checkDOMMatrix(result, expected);
+ },"test rotate() order");
+
+ test(function() {
+ var result = initialDOMMatrix().rotateFromVector(1, 1);
+ var expected = initialDOMMatrix().rotate(45);
+ checkDOMMatrix(result, expected);
+ },"test rotateFromVector()");
+
+ test(function() {
+ var result = initialDOMMatrix().rotateFromVector(0, 1);
+ var expected = initialDOMMatrix().rotate(90);
+ checkDOMMatrix(result, expected);
+ },"test rotateFromVector() with x being zero");
+
+ test(function() {
+ var result = initialDOMMatrix().rotateFromVector(1, 0);
+ var expected = initialDOMMatrix()
+ checkDOMMatrix(result, expected);
+ },"test rotateFromVector() with y being zero");
+
+ test(function() {
+ var result = initialDOMMatrix().rotateFromVector(0, 0);
+ var expected = initialDOMMatrix()
+ checkDOMMatrix(result, expected);
+ },"test rotateFromVector() with two zeros");
+
+ test(function() {
+ var result = initialDOMMatrix().rotateAxisAngle(3, 3, 3, 120);
+ var expected = initialDOMMatrix().multiply(getRotationMatrix(3, 3, 3, 120));
+ checkDOMMatrix(result, expected);
+ },"test rotateAxisAngle() ");
+
+ test(function() {
+ var angleDeg = 75;
+ var result = initialDOMMatrix().skewX(angleDeg);
+ var tangent = Math.tan(angleDeg * Math.PI/180);
+ var skew = new DOMMatrix([
+ 1, 0, 0, 0,
+ tangent, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1])
+ var expected = initialDOMMatrix().multiply(skew);
+ checkDOMMatrix(result, expected);
+ },"test skewX()");
+
+ test(function() {
+ var angleDeg = 18;
+ var result = initialDOMMatrix().skewY(angleDeg);
+ var tangent = Math.tan(angleDeg * Math.PI/180);
+ var skew = new DOMMatrix([
+ 1, tangent, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1])
+ var expected = initialDOMMatrix().multiply(skew);
+ checkDOMMatrix(result, expected);
+ },"test skewY()");
+
+ test(function() {
+ var result = initialDOMMatrix().multiply(initialDOMMatrix().inverse());
+ checkDOMMatrix(result, identity());
+ },"test multiply with inverse is identity");
+
+ test(function() {
+ var result = initialDOMMatrix().flipX();
+ var expected = initialDOMMatrix().multiply(new DOMMatrix([-1, 0, 0, 1, 0, 0]));
+ checkDOMMatrix(result, expected);
+ },"test flipX()");
+
+ test(function() {
+ var result = initialDOMMatrix().flipY();
+ var expected = initialDOMMatrix().multiply(new DOMMatrix([1, 0, 0, -1, 0, 0]));
+ checkDOMMatrix(result, expected);
+ },"test flipY()");
+
+ test(function() {
+ var point = new DOMPointReadOnly(1, 2, 3, 4);
+ var matrix = new DOMMatrix([1, 2, 3, 4, 5, 6]);
+ var result = matrix.transformPoint(point);
+ var expected = getMatrixTransform(matrix, point);
+ checkDOMPoint(result, expected);
+ },"test transformPoint() - 2d matrix");
+
+ test(function() {
+ var point = new DOMPointReadOnly(1, 2, 3, 4);
+ var matrix = new DOMMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+ var result = matrix.transformPoint(point);
+ var expected = getMatrixTransform(matrix, point);
+ checkDOMPoint(result, expected);
+ },"test transformPoint() - 3d matrix");
+
+ function checkDOMMatrix(m, exp) {
+ assert_approx_equals(m.m11, exp.m11, epsilon, "Expected value for m11 is " + exp.m11);
+ assert_approx_equals(m.m12, exp.m12, epsilon, "Expected value for m12 is " + exp.m12);
+ assert_approx_equals(m.m13, exp.m13, epsilon, "Expected value for m13 is " + exp.m13);
+ assert_approx_equals(m.m14, exp.m14, epsilon, "Expected value for m14 is " + exp.m14);
+ assert_approx_equals(m.m21, exp.m21, epsilon, "Expected value for m21 is " + exp.m21);
+ assert_approx_equals(m.m22, exp.m22, epsilon, "Expected value for m22 is " + exp.m22);
+ assert_approx_equals(m.m23, exp.m23, epsilon, "Expected value for m23 is " + exp.m23);
+ assert_approx_equals(m.m24, exp.m24, epsilon, "Expected value for m24 is " + exp.m24);
+ assert_approx_equals(m.m31, exp.m31, epsilon, "Expected value for m31 is " + exp.m31);
+ assert_approx_equals(m.m32, exp.m32, epsilon, "Expected value for m32 is " + exp.m32);
+ assert_approx_equals(m.m33, exp.m33, epsilon, "Expected value for m33 is " + exp.m33);
+ assert_approx_equals(m.m34, exp.m34, epsilon, "Expected value for m34 is " + exp.m34);
+ assert_approx_equals(m.m41, exp.m41, epsilon, "Expected value for m41 is " + exp.m41);
+ assert_approx_equals(m.m42, exp.m42, epsilon, "Expected value for m42 is " + exp.m42);
+ assert_approx_equals(m.m43, exp.m43, epsilon, "Expected value for m43 is " + exp.m43);
+ assert_approx_equals(m.m44, exp.m44, epsilon, "Expected value for m44 is " + exp.m44);
+ assert_equals(m.is2D, exp.is2D, "Expected value for is2D is " + exp.is2D);
+ }
+
+ function checkDOMPoint(p, exp) {
+ assert_equals(p.x, exp.x, "x is not matched");
+ assert_equals(p.y, exp.y, "y is not matched");
+ assert_equals(p.z, exp.z, "z is not matched");
+ assert_equals(p.w, exp.w, "w is not matched");
+ }
+
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-a-f-alias.html b/testing/web-platform/tests/css/geometry/DOMMatrix-a-f-alias.html
new file mode 100644
index 0000000000..ab14ec9d5c
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-a-f-alias.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>Geometry Interfaces: DOMMatrix and DOMMatrixReadOnly a-f alias attributes</title>
+<link rel="help" href="https://drafts.fxtf.org/geometry/#DOMMatrix">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function defineThrowingGetter(object, attribute) {
+ Object.defineProperty(object, attribute, {
+ get: () => assert_unreached(`getter for ${attribute}`)
+ });
+}
+
+function defineThrowingSetter(object, attribute) {
+ Object.defineProperty(object, attribute, {
+ set: () => assert_unreached(`setter for ${attribute}`)
+ });
+}
+
+["DOMMatrix", "DOMMatrixReadOnly"].forEach((constr) => {
+ [
+ ["a", "m11"],
+ ["b", "m12"],
+ ["c", "m21"],
+ ["d", "m22"],
+ ["e", "m41"],
+ ["f", "m42"],
+ ].forEach(([aliasAttribute, mAttribute]) => {
+ test(() => {
+ const matrix = new self[constr]([0, 0, 0, 0, 0, 0]);
+ defineThrowingGetter(matrix, mAttribute);
+ assert_equals(matrix[aliasAttribute], 0);
+ }, `${constr} getting ${aliasAttribute} with throwing getter for ${mAttribute}`);
+
+ test(() => {
+ const matrix = new self[constr]([0, 0, 0, 0, 0, 0]);
+ defineThrowingGetter(matrix, aliasAttribute);
+ assert_equals(matrix[mAttribute], 0);
+ }, `${constr} getting ${mAttribute} with throwing getter for ${aliasAttribute}`);
+
+ if (constr === "DOMMatrix") {
+ test(() => {
+ const matrix = new self[constr]([0, 0, 0, 0, 0, 0]);
+ defineThrowingSetter(matrix, mAttribute);
+ matrix[aliasAttribute] = 1;
+ assert_equals(matrix[aliasAttribute], 1);
+ }, `${constr} setting ${aliasAttribute} with throwing setter for ${mAttribute}`);
+
+ test(() => {
+ const matrix = new self[constr]([0, 0, 0, 0, 0, 0]);
+ defineThrowingSetter(matrix, aliasAttribute);
+ matrix[mAttribute] = 1;
+ assert_equals(matrix[mAttribute], 1);
+ }, `${constr} setting ${mAttribute} with throwing setter for ${aliasAttribute}`);
+ }
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-attributes.html b/testing/web-platform/tests/css/geometry/DOMMatrix-attributes.html
new file mode 100644
index 0000000000..4b3db9d550
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-attributes.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<title>Geometry Interfaces: DOMMatrix attributes</title>
+<link rel="help" href="https://drafts.fxtf.org/geometry/#dommatrix-attributes">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const initial = {
+ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0,
+ m11: 1, m12: 0, m13: 0, m14: 0,
+ m21: 0, m22: 1, m23: 0, m24: 0,
+ m31: 0, m32: 0, m33: 1, m34: 0,
+ m41: 0, m42: 0, m43: 0, m44: 1,
+};
+
+// Attributes that always preserve is2D.
+["a", "b", "c", "d", "e", "f",
+ "m11", "m12", "m21", "m22", "m41", "m42" ].forEach(attribute => {
+ test(() => {
+ let m = new DOMMatrix();
+ assert_true(m.is2D);
+ assert_equals(m[attribute], initial[attribute]);
+ m[attribute] = 42;
+ assert_true(m.is2D);
+ assert_equals(m[attribute], 42);
+ }, `DOMMatrix.${attribute}`);
+});
+
+// Attributes that clear is2D for values other than 0 or -0.
+["m13", "m14", "m23", "m24", "m31", "m32", "m34", "m43" ].forEach(attribute => {
+ test(() => {
+ let m = new DOMMatrix();
+ assert_true(m.is2D);
+ assert_equals(m[attribute], initial[attribute]);
+ m[attribute] = 0;
+ assert_true(m.is2D, "0 preserves is2D");
+ assert_equals(m[attribute], 0);
+ m[attribute] = -0;
+ assert_true(m.is2D, "-0 preserves is2D");
+ assert_equals(m[attribute], -0);
+ m[attribute] = 42;
+ assert_false(m.is2D, "a value other than 0 or -0 clears is2D");
+ assert_equals(m[attribute], 42);
+ m[attribute] = 0;
+ assert_false(m.is2D, "is2D can never be set to true after having been set to false");
+ assert_equals(m[attribute], 0);
+ }, `DOMMatrix.${attribute}`);
+});
+
+// Attributes that clear is2D for values other than 1.
+["m33", "m44" ].forEach(attribute => {
+ test(() => {
+ let m = new DOMMatrix();
+ assert_true(m.is2D);
+ assert_equals(m[attribute], initial[attribute]);
+ m[attribute] = 1;
+ assert_true(m.is2D, "1 preserves is2D");
+ assert_equals(m[attribute], 1);
+ m[attribute] = 42;
+ assert_false(m.is2D, "a value other than 1 clears is2D");
+ assert_equals(m[attribute], 42);
+ m[attribute] = 1;
+ assert_false(m.is2D, "is2D can never be set to true after having been set to false");
+ assert_equals(m[attribute], 1);
+ }, `DOMMatrix.${attribute}`);
+});
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-css-string.worker.js b/testing/web-platform/tests/css/geometry/DOMMatrix-css-string.worker.js
new file mode 100644
index 0000000000..d11638b26a
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-css-string.worker.js
@@ -0,0 +1,38 @@
+// https://drafts.fxtf.org/geometry/#DOMMatrix
+
+importScripts("/resources/testharness.js");
+
+['DOMMatrix', 'DOMMatrixReadOnly'].forEach(constr => {
+ test(() => {
+ assert_true(constr in self, `${constr} should exist`);
+ assert_throws_js(TypeError, () => new self[constr]('matrix(1,0,0,1,0,0)') );
+ }, `${constr} constructor with string argument in worker`);
+
+ test(() => {
+ assert_true(constr in self, `${constr} should exist`);
+ assert_throws_js(TypeError, () => new self[constr]('') );
+ }, `${constr} constructor with empty string argument in worker`);
+
+ test(() => {
+ const matrix = new self[constr]();
+ assert_equals(String(matrix), `[object ${constr}]`);
+ }, `${constr} stringifier in worker (2d identity)`);
+
+ test(() => {
+ const matrix = self[constr].fromMatrix({is2D: false});
+ assert_equals(String(matrix), `[object ${constr}]`);
+ }, `${constr} stringifier in worker (3d identity)`);
+
+ test(() => {
+ const matrix = new self[constr]([1, 0, 0, NaN, Infinity, -Infinity]);
+ assert_equals(String(matrix), `[object ${constr}]`);
+ }, `${constr} stringifier in worker (non-finite values)`);
+});
+
+test(() => {
+ assert_false('setMatrixValue' in DOMMatrix.prototype, 'on prototype');
+ const matrix = new DOMMatrix();
+ assert_false('setMatrixValue' in matrix, 'on instance');
+}, 'DOMMatrix setMatrixValue in worker');
+
+done();
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-invert-invertible.html b/testing/web-platform/tests/css/geometry/DOMMatrix-invert-invertible.html
new file mode 100644
index 0000000000..d5bef624d2
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-invert-invertible.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.fxtf.org/geometry-1/#DOMMatrix">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/dommatrix-test-util.js"></script>
+<p>Test DOMMatrix.inverse()/invertSelf() for invertible matrices</p>
+<script>
+test(function() {
+ var m = new DOMMatrix();
+ assert_true(m.isIdentity);
+ var m1 = m.inverse();
+ assert_true(m1.isIdentity);
+ // Use checkMatrix() instead of checkDOMMatrix() because checkMatrix() has
+ // a default epsilon = Number.MIN_VALUE which can at least pass
+ // assert_approx_equal(0, -0, epsilon).
+ checkMatrix(m, m1);
+ m.invertSelf();
+ checkMatrix(m, m1);
+}, "identity");
+
+test(function() {
+ var m = new DOMMatrix().translate(10, -20.5);
+ var m1 = m.inverse();
+ checkMatrix(m1, new DOMMatrix().translate(-10, 20.5));
+ // Check with 'new DOMMatrix()' instead of identity() because the latter is
+ // a 3d identity matrix.
+ checkMatrix(m1.multiply(m), new DOMMatrix());
+ m.invertSelf();
+ checkMatrix(m, m1);
+}, "translate");
+
+test(function() {
+ var m = new DOMMatrix().translate(10, -20.5, 30.5);
+ var m1 = m.inverse();
+ checkMatrix(m1, new DOMMatrix().translate(-10, 20.5, -30.5));
+ checkMatrix(m1.multiply(m), identity());
+ m.invertSelf();
+ checkMatrix(m, m1);
+}, "translate3d");
+
+test(function() {
+ var m = new DOMMatrix().scale(4, -0.5);
+ var m1 = m.inverse();
+ checkMatrix(m1, new DOMMatrix().scale(0.25, -2.0));
+ checkMatrix(m1.multiply(m), new DOMMatrix());
+ m.invertSelf();
+ checkMatrix(m, m1);
+}, "scale");
+
+test(function() {
+ var m = new DOMMatrix().scale(4, -0.5, 2);
+ var m1 = m.inverse();
+ checkMatrix(m1, new DOMMatrix().scale(0.25, -2.0, 0.5));
+ checkMatrix(m1.multiply(m), identity());
+ m.invertSelf();
+ checkMatrix(m, m1);
+}, "scale3d");
+
+test(function() {
+ var m = new DOMMatrix().rotateAxisAngle(0, 0, 1, -30)
+ .scale(10, -0.5, 2.5)
+ .rotateAxisAngle(0, 1, 0, 10)
+ .translate(10, -20.5, 30.5)
+ .rotateAxisAngle(1, 0, 0, 20);
+ var expected = new DOMMatrix().rotateAxisAngle(1, 0, 0, -20)
+ .translate(-10, 20.5, -30.5)
+ .rotateAxisAngle(0, 1, 0, -10)
+ .scale(0.1, -2.0, 0.4)
+ .rotateAxisAngle(0, 0, 1, 30);
+ var m1 = m.inverse();
+ var epsilon = 1e-6;
+ checkMatrix(m1, expected, {epsilon});
+ m.invertSelf();
+ checkMatrix(m, expected, {epsilon});
+}, "complex");
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-invert-non-invertible.html b/testing/web-platform/tests/css/geometry/DOMMatrix-invert-non-invertible.html
new file mode 100644
index 0000000000..b3295321e0
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-invert-non-invertible.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.fxtf.org/geometry-1/#DOMMatrix">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<p>Test DOMMatrix.inverse()/invertSelf() for non-invertible matrix</p>
+<script>
+function checkResult(m) {
+ assert_false(m.is2D, 'is2D');
+ assert_false(m.isIdentity, 'isIdentity');
+ assert_true(isNaN(m.m11), 'm11 isNaN');
+ assert_true(isNaN(m.m12), 'm12 isNaN');
+ assert_true(isNaN(m.m13), 'm13 isNaN');
+ assert_true(isNaN(m.m14), 'm14 isNaN');
+ assert_true(isNaN(m.m21), 'm21 isNaN');
+ assert_true(isNaN(m.m22), 'm22 isNaN');
+ assert_true(isNaN(m.m23), 'm23 isNaN');
+ assert_true(isNaN(m.m24), 'm24 isNaN');
+ assert_true(isNaN(m.m31), 'm31 isNaN');
+ assert_true(isNaN(m.m32), 'm32 isNaN');
+ assert_true(isNaN(m.m33), 'm33 isNaN');
+ assert_true(isNaN(m.m34), 'm34 isNaN');
+ assert_true(isNaN(m.m41), 'm41 isNaN');
+ assert_true(isNaN(m.m42), 'm42 isNaN');
+ assert_true(isNaN(m.m43), 'm43 isNaN');
+ assert_true(isNaN(m.m44), 'm44 isNaN');
+
+ var f32 = m.toFloat32Array();
+ assert_equals(f32.length, 16, 'toFloat32Array().length');
+ for (var i = 0; i < 16; i++)
+ assert_true(isNaN(f32[i]), 'toFloat32Array()[' + i + '] isNaN');
+
+ var f64 = m.toFloat64Array();
+ assert_equals(f64.length, 16, 'toFloat64Array().length');
+ for (var i = 0; i < 16; i++)
+ assert_true(isNaN(f64[i]), 'toFloat64()[' + i + '] isNaN');
+}
+
+test(function() {
+ var m = new DOMMatrix();
+ m.a = 0;
+ m.invertSelf();
+ checkResult(m);
+},"invertSelf()");
+
+test(function() {
+ var m = new DOMMatrix();
+ m.a = 0;
+ checkResult(m.inverse());
+},"inverse()");
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-invert-preserves-2d.html b/testing/web-platform/tests/css/geometry/DOMMatrix-invert-preserves-2d.html
new file mode 100644
index 0000000000..a4f0b58496
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-invert-preserves-2d.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>Test DOMMatrix.inverse()/invertSelf() keep is2D status</title>
+<link rel="help" href="https://drafts.fxtf.org/geometry-1/#DOMMatrix">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function check2D(m) {
+ assert_true(m.is2D);
+ // assert_equals() distinguish 0 and -0, so use '== 0' instead.
+ assert_true(m.m13 == 0);
+ assert_true(m.m14 == 0);
+ assert_true(m.m23 == 0);
+ assert_true(m.m24 == 0);
+ assert_true(m.m31 == 0);
+ assert_true(m.m32 == 0);
+ assert_equals(m.m33, 1);
+ assert_true(m.m34 == 0);
+ assert_true(m.m43 == 0);
+ assert_equals(m.m44, 1);
+}
+
+test(function() {
+ for (var s = 0.1; s < 20; s += 0.1) {
+ m = new DOMMatrix().scale(s, s);
+ check2D(m);
+ check2D(m.inverse());
+ m.invertSelf();
+ check2D(m);
+ }
+}, "scale");
+
+test(function() {
+ for (var r = 0; r < 180; r += 2) {
+ m = new DOMMatrix().rotate(r);
+ check2D(m);
+ check2D(m.inverse());
+ m.invertSelf();
+ check2D(m);
+ }
+}, "rotate");
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-newobject.html b/testing/web-platform/tests/css/geometry/DOMMatrix-newobject.html
new file mode 100644
index 0000000000..33604e3c67
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-newobject.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<title>Geometry Interfaces: DOMMatrix and DOMMatrixReadOnly [NewObject] methods</title>
+<link rel="help" href="https://drafts.fxtf.org/geometry/#DOMMatrix">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function getReturnType(method) {
+ switch(method) {
+ case "transformPoint": return "DOMPoint"; break;
+ case "toFloat32Array": return "Float32Array"; break;
+ case "toFloat64Array": return "Float64Array"; break;
+ default: return "DOMMatrix"; break;
+ }
+}
+["DOMMatrix", "DOMMatrixReadOnly"].forEach((constr) => {
+ ["translate",
+ "scale",
+ "scale3d",
+ "rotate",
+ "rotateFromVector",
+ "rotateAxisAngle",
+ "skewX",
+ "skewY",
+ "multiply",
+ "flipX",
+ "flipY",
+ "inverse",
+ "transformPoint",
+ "toFloat32Array",
+ "toFloat64Array"].forEach((method) => {
+ test(() => {
+ const matrix = new self[constr]();
+ const a = matrix[method]();
+ const b = matrix[method]();
+ assert_class_string(matrix, constr, 'matrix');
+ assert_class_string(a, getReturnType(method), 'a');
+ assert_class_string(b, getReturnType(method), 'b');
+ assert_not_equals(a, b, 'a !== b');
+ assert_not_equals(a, matrix, 'a !== matrix');
+ assert_not_equals(b, matrix, 'b !== matrix');
+ }, `${constr} ${method}`);
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix-stringifier.html b/testing/web-platform/tests/css/geometry/DOMMatrix-stringifier.html
new file mode 100644
index 0000000000..5a39238bef
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix-stringifier.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<title>Geometry Interfaces: DOMMatrix and DOMMatrixReadOnly stringifier</title>
+<link rel="help" href="https://drafts.fxtf.org/geometry/#DOMMatrix">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+["DOMMatrix", "DOMMatrixReadOnly", "WebKitCSSMatrix"].forEach(constr => {
+ const prefix = `${constr} stringifier:`;
+
+ // Basic
+ test(() => {
+ const matrix = new self[constr]();
+ assert_equals(String(matrix), "matrix(1, 0, 0, 1, 0, 0)");
+ }, `${prefix} identity (2d)`);
+
+ test(() => {
+ const matrix = self[constr].fromMatrix({is2D: false});
+ assert_equals(String(matrix), "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)");
+ }, `${prefix} identity (3d)`);
+
+ // Non-finites
+ [NaN, Infinity, -Infinity].forEach(num => {
+ test(() => {
+ const matrix = new self[constr]([1, 0, 0, 1, 0, num]);
+ assert_throws_dom("InvalidStateError", () => String(matrix));
+ }, `${prefix} ${num} (2d)`);
+
+ test(() => {
+ const matrix = new self[constr]([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, num, 0, 1]);
+ assert_throws_dom("InvalidStateError", () => String(matrix));
+ }, `${prefix} ${num} (3d)`);
+ });
+
+ // Precision
+ [
+ ['1/3', '0.3333333333333333'],
+ ['1/300000', '0.0000033333333333333333'],
+ ['1/300000000', '3.3333333333333334e-9'],
+ ['100000 + (1/3)', '100000.33333333333'],
+ ['Math.pow(2, 53) + 1', '9007199254740992'],
+ ['Math.pow(2, 53) + 2', '9007199254740994'],
+ ['Number.MAX_VALUE', '1.7976931348623157e+308'],
+ ['Number.MIN_VALUE', '5e-324'],
+ ].forEach(([input, expected]) => {
+ const num = eval(input);
+ test(() => {
+ const matrix = new self[constr]([1, 0, 0, 1, 0, num]);
+ assert_equals(String(matrix), `matrix(1, 0, 0, 1, 0, ${expected})`);
+ }, `${prefix} ${input} (2d)`);
+
+ test(() => {
+ const matrix = new self[constr]([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, num, 0, 1]);
+ assert_equals(String(matrix), `matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, ${expected}, 0, 1)`);
+ }, `${prefix} ${input} (3d)`);
+ });
+
+ // Should not invoke getters for m11 etc
+ function defineThrowingGetters(matrix) {
+ Object.defineProperty(matrix, 'a', {
+ get: () => assert_unreached('getter for a')
+ });
+ Object.defineProperty(matrix, 'm11', {
+ get: () => assert_unreached('getter for m11')
+ });
+ }
+
+ test(() => {
+ const matrix = new self[constr]();
+ defineThrowingGetters(matrix);
+ assert_equals(String(matrix), "matrix(1, 0, 0, 1, 0, 0)");
+ }, `${prefix} throwing getters (2d)`);
+
+ test(() => {
+ const matrix = self[constr].fromMatrix({is2D: false});
+ defineThrowingGetters(matrix);
+ assert_equals(String(matrix), "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)");
+ }, `${prefix} throwing getters (3d)`);
+});
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrix2DInit-validate-fixup.html b/testing/web-platform/tests/css/geometry/DOMMatrix2DInit-validate-fixup.html
new file mode 100644
index 0000000000..a7257aa288
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrix2DInit-validate-fixup.html
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<title>Geometry Interfaces: DOMMatrix2DInit validate and fixup</title>
+<link rel="help" href="https://drafts.fxtf.org/geometry/#dommatrixinit-dictionary">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/dommatrix-test-util.js"></script>
+<canvas id=canvas hidden></canvas>
+<script>
+setup(() => {
+ window.canvas = document.getElementById('canvas');
+ window.ctx = canvas.getContext('2d');
+ window.ctx.fillStyle = '#000';
+});
+
+function clearCanvas(ctx) {
+ ctx.resetTransform();
+ ctx.clearRect(0, 0, window.canvas.width, window.canvas.height);
+}
+
+function drawRectWithSetTransform(ctx, transform) {
+ clearCanvas(ctx);
+ ctx.setTransform(transform);
+ ctx.fillRect(20, 20, 30, 30);
+ return window.canvas.toDataURL();
+}
+
+function drawRectWithAddPathTransform(ctx, transform) {
+ clearCanvas(ctx);
+ var path = new Path2D();
+ path.rect(20, 20, 30, 30);
+ var transformedPath = new Path2D();
+ if (transform === undefined) {
+ transformedPath.addPath(path);
+ } else {
+ transformedPath.addPath(path, transform);
+ }
+ ctx.fill(transformedPath);
+ return window.canvas.toDataURL();
+}
+
+var emptyCanvasURL = window.canvas.toDataURL();
+
+[
+ {a: 1, m11: 2},
+ {b: 0, m12: -1},
+ {c: Infinity, m21: -Infinity},
+ {d: 0, m22: NaN},
+ {e: 1, m41: 1.00000001},
+ {f: 0, m42: Number.MIN_VALUE},
+].forEach(dict => {
+ test(() => {
+ ctx.resetTransform();
+ assert_throws_js(TypeError, () => ctx.setTransform(dict));
+ }, `setTransform(${format_dict(dict)}) (invalid)`);
+
+ test(() => {
+ assert_throws_js(TypeError, () => drawRectWithAddPathTransform(ctx, dict));
+ }, `addPath(${format_dict(dict)}) (invalid)`);
+});
+
+test(() => {
+ ctx.resetTransform();
+ ctx.setTransform(1, 2, 3, 4, 5, 6);
+ const matrix = ctx.getTransform();
+ checkMatrix(matrix, matrix2D({m11: 1, m12: 2, m21: 3, m22: 4, m41: 5, m42: 6}));
+}, `setTransform (Sanity check without dictionary)`);
+
+test(() => {
+ var ident = matrix2D({});
+ var expectedResultURL = drawRectWithSetTransform(ctx, ident);
+ var actualResultURL = drawRectWithAddPathTransform(ctx);
+ assert_equals(actualResultURL, expectedResultURL);
+}, `addPath (Sanity check without second parameter)`);
+
+[
+ // Input dict that are 2D
+ [{}, matrix2D({})],
+ [{is2D: undefined}, matrix2D({})],
+ [{a: 1, m11: 1}, matrix2D({m11: 1})],
+ [{b: 0, m12: undefined}, matrix2D({m12: 0})],
+ [{c: 0, m21: 0}, matrix2D({m21: 0})],
+ [{c: 0, m21: -0}, matrix2D({m21: -0})],
+ [{c: -0, m21: 0}, matrix2D({m21: 0})],
+ [{c: -0, m21: -0}, matrix2D({m21: -0})],
+ [{d: Infinity, m22: Infinity}, null], // setTransform: silently ignore / addPath: silently halt
+ [{e: -Infinity, m41: -Infinity}, null], // setTransform: silently ignore / addPath: silently halt
+ [{f: NaN, m42: NaN}, null], // setTransform: silently ignore / addPath: silently halt
+ [{f: NaN, m42: NaN, is2D: true}, null], // setTransform: silently ignore / addPath: silently halt
+ [{f: 0, m42: null}, matrix2D({m42: 0})], // null is converted to 0
+ [{f: -0, m42: null}, matrix2D({m42: 0})], // null is converted to 0
+ [{a: 2}, matrix2D({m11: 2})],
+ [{b: 2}, matrix2D({m12: 2})],
+ [{c: 2}, matrix2D({m21: 2})],
+ [{d: 2}, matrix2D({m22: 2})],
+ [{e: 2}, matrix2D({m41: 2})],
+ [{f: 2}, matrix2D({m42: 2})],
+ [{a: -0, b: -0, c: -0, d: -0, e: -0, f: -0},
+ matrix2D({m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0})],
+ [{a: -0, b: -0, c: -0, d: -0, e: -0, f: -0, is2D: true},
+ matrix2D({m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0})],
+ [{m11:2}, matrix2D({m11: 2})],
+ [{m12:2}, matrix2D({m12: 2})],
+ [{m21:2}, matrix2D({m21: 2})],
+ [{m22:2}, matrix2D({m22: 2})],
+ [{m41:2}, matrix2D({m41: 2})],
+ [{m42:2}, matrix2D({m42: 2})],
+ [{m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0},
+ matrix2D({m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0})],
+ [{m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0, is2D: true},
+ matrix2D({m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0})],
+ [{m13: 0, is2D: true}, matrix2D({})],
+ [{m13: -0, is2D: true}, matrix2D({})],
+ [{m14: 0, is2D: true}, matrix2D({})],
+ [{m14: -0, is2D: true}, matrix2D({})],
+ [{m23: 0, is2D: true}, matrix2D({})],
+ [{m23: -0, is2D: true}, matrix2D({})],
+ [{m24: 0, is2D: true}, matrix2D({})],
+ [{m24: -0, is2D: true}, matrix2D({})],
+ [{m31: 0, is2D: true}, matrix2D({})],
+ [{m31: -0, is2D: true}, matrix2D({})],
+ [{m32: 0, is2D: true}, matrix2D({})],
+ [{m32: -0, is2D: true}, matrix2D({})],
+ [{m33: 1, is2D: true}, matrix2D({})],
+ [{m34: 0, is2D: true}, matrix2D({})],
+ [{m34: -0, is2D: true}, matrix2D({})],
+ [{m43: 0, is2D: true}, matrix2D({})],
+ [{m43: -0, is2D: true}, matrix2D({})],
+ [{m44: 1, is2D: true}, matrix2D({})],
+ [{is2D: true}, matrix2D({})],
+].forEach(([dict, expected]) => {
+ test(() => {
+ ctx.resetTransform();
+ ctx.setTransform(dict);
+ const matrix = ctx.getTransform();
+ checkMatrix(matrix, expected || matrix2D({}));
+ }, `setTransform(${format_dict(dict)})`);
+
+ test(() => {
+ var expectedResultURL = expected ?
+ drawRectWithSetTransform(ctx, expected) :
+ emptyCanvasURL;
+ var actualResultURL = drawRectWithAddPathTransform(ctx, dict);
+ assert_equals(actualResultURL, expectedResultURL);
+ }, `addPath(${format_dict(dict)})`);
+ });
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMMatrixInit-validate-fixup.html b/testing/web-platform/tests/css/geometry/DOMMatrixInit-validate-fixup.html
new file mode 100644
index 0000000000..78eaa78e21
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMMatrixInit-validate-fixup.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<title>Geometry Interfaces: DOMMatrixInit validate and fixup</title>
+<link rel="help" href="https://drafts.fxtf.org/geometry/#dommatrixinit-dictionary">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/dommatrix-test-util.js"></script>
+<script>
+[
+ {a: 1, m11: 2},
+ {b: 0, m12: -1},
+ {c: Infinity, m21: -Infinity},
+ {d: 0, m22: NaN},
+ {e: 1, m41: 1.00000001},
+ {f: 0, m42: Number.MIN_VALUE},
+ {m13: 1, is2D: true},
+ {m14: 1, is2D: true},
+ {m23: 1, is2D: true},
+ {m24: 1, is2D: true},
+ {m31: 1, is2D: true},
+ {m32: 1, is2D: true},
+ {m33: 0, is2D: true},
+ {m33: -0, is2D: true},
+ {m33: -1, is2D: true},
+ {m34: 1, is2D: true},
+ {m43: 1, is2D: true},
+ {m44: 0, is2D: true},
+].forEach(dict => {
+ test(() => {
+ assert_true('fromMatrix' in DOMMatrix, 'fromMatrix should exist');
+ assert_throws_js(TypeError, () => DOMMatrix.fromMatrix(dict));
+ assert_true('multiply' in DOMMatrix.prototype, 'multiply should exist');
+ assert_throws_js(TypeError, () => new DOMMatrix().multiply(dict));
+ assert_true('multiplySelf' in DOMMatrix.prototype, 'multiplySelf should exist');
+ assert_throws_js(TypeError, () => new DOMMatrix().multiplySelf(dict));
+ assert_true('preMultiplySelf' in DOMMatrix.prototype, 'preMultiplySelf should exist');
+ assert_throws_js(TypeError, () => new DOMMatrix().preMultiplySelf(dict));
+ }, `${format_dict(dict)} (invalid)`);
+});
+
+[
+ [{}, matrix2D({})],
+ [{is2D: undefined}, matrix2D({})], // undefined means the dictionary member is not present
+ [{a: 1, m11: 1}, matrix2D({m11: 1})],
+ [{b: 0, m12: undefined}, matrix2D({m12: 0})],
+ [{c: 0, m21: 0}, matrix2D({m21: 0})],
+ [{c: 0, m21: -0}, matrix2D({m21: -0})],
+ [{c: -0, m21: 0}, matrix2D({m21: 0})],
+ [{c: -0, m21: -0}, matrix2D({m21: -0})],
+ [{d: Infinity, m22: Infinity}, matrix2D({m22: Infinity})],
+ [{e: -Infinity, m41: -Infinity}, matrix2D({m41: -Infinity})],
+ [{f: NaN, m42: NaN}, matrix2D({m42: NaN})],
+ [{f: NaN, m42: NaN, is2D: true}, matrix2D({m42: NaN})],
+ [{f: 0, m42: null}, matrix2D({m42: 0})], // null is converted to 0
+ [{f: -0, m42: null}, matrix2D({m42: 0})], // null is converted to 0
+ [{a: 2}, matrix2D({m11: 2})],
+ [{b: 2}, matrix2D({m12: 2})],
+ [{c: 2}, matrix2D({m21: 2})],
+ [{d: 2}, matrix2D({m22: 2})],
+ [{e: 2}, matrix2D({m41: 2})],
+ [{f: 2}, matrix2D({m42: 2})],
+ [{a: -0, b: -0, c: -0, d: -0, e: -0, f: -0},
+ matrix2D({m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0})],
+ [{a: -0, b: -0, c: -0, d: -0, e: -0, f: -0, is2D: true},
+ matrix2D({m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0})],
+ [{m11:2}, matrix2D({m11: 2})],
+ [{m12:2}, matrix2D({m12: 2})],
+ [{m21:2}, matrix2D({m21: 2})],
+ [{m22:2}, matrix2D({m22: 2})],
+ [{m41:2}, matrix2D({m41: 2})],
+ [{m42:2}, matrix2D({m42: 2})],
+ [{m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0},
+ matrix2D({m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0})],
+ [{m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0, is2D: true},
+ matrix2D({m11: -0, m12: -0, m21: -0, m22: -0, m41: -0, m42: -0})],
+ [{m13: 0, is2D: true}, matrix2D({m13: 0})],
+ [{m13: -0, is2D: true}, matrix2D({m13: 0})],
+ [{m14: 0, is2D: true}, matrix2D({m14: 0})],
+ [{m14: -0, is2D: true}, matrix2D({m14: 0})],
+ [{m23: 0, is2D: true}, matrix2D({m23: 0})],
+ [{m23: -0, is2D: true}, matrix2D({m23: 0})],
+ [{m24: 0, is2D: true}, matrix2D({m24: 0})],
+ [{m24: -0, is2D: true}, matrix2D({m24: 0})],
+ [{m31: 0, is2D: true}, matrix2D({m31: 0})],
+ [{m31: -0, is2D: true}, matrix2D({m31: 0})],
+ [{m32: 0, is2D: true}, matrix2D({m32: 0})],
+ [{m32: -0, is2D: true}, matrix2D({m32: 0})],
+ [{m33: 1, is2D: true}, matrix2D({m33: 1})],
+ [{m34: 0, is2D: true}, matrix2D({m34: 0})],
+ [{m34: -0, is2D: true}, matrix2D({m34: 0})],
+ [{m43: 0, is2D: true}, matrix2D({m43: 0})],
+ [{m43: -0, is2D: true}, matrix2D({m43: 0})],
+ [{m44: 1, is2D: true}, matrix2D({m44: 1})],
+ [{is2D: true}, matrix2D({})],
+].forEach(([dict, expected]) => {
+ test(() => {
+ const matrix = DOMMatrix.fromMatrix(dict);
+ checkMatrix(matrix, expected);
+ }, `${format_dict(dict)} (2d)`);
+});
+
+[
+ [{m13: 1, is2D: false}, matrix3D({m13: 1})],
+ [{m14: 1, is2D: false}, matrix3D({m14: 1})],
+ [{m23: 1, is2D: false}, matrix3D({m23: 1})],
+ [{m24: 1, is2D: false}, matrix3D({m24: 1})],
+ [{m31: 1, is2D: false}, matrix3D({m31: 1})],
+ [{m32: 1, is2D: false}, matrix3D({m32: 1})],
+ [{m33: 0, is2D: false}, matrix3D({m33: 0})],
+ [{m33: -0, is2D: false}, matrix3D({m33: -0})],
+ [{m33: -1, is2D: false}, matrix3D({m33: -1})],
+ [{m34: 1, is2D: false}, matrix3D({m34: 1})],
+ [{m43: 1, is2D: false}, matrix3D({m43: 1})],
+ [{m44: 0, is2D: false}, matrix3D({m44: 0})],
+ [{m13: 1}, matrix3D({m13: 1})],
+ [{m14: 1}, matrix3D({m14: 1})],
+ [{m23: 1}, matrix3D({m23: 1})],
+ [{m24: 1}, matrix3D({m24: 1})],
+ [{m31: 1}, matrix3D({m31: 1})],
+ [{m32: 1}, matrix3D({m32: 1})],
+ [{m33: 0}, matrix3D({m33: 0})],
+ [{m34: 1}, matrix3D({m34: 1})],
+ [{m43: 1}, matrix3D({m43: 1})],
+ [{m44: 0}, matrix3D({m44: 0})],
+ [{is2D: false}, matrix3D({})],
+ [{is2D: null}, matrix3D({})], // null is converted to false
+].forEach(([dict, expected]) => {
+ test(() => {
+ const matrix = DOMMatrix.fromMatrix(dict);
+ checkMatrix(matrix, expected);
+ }, `${format_dict(dict)} (3d)`);
+});
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMPoint-001.html b/testing/web-platform/tests/css/geometry/DOMPoint-001.html
new file mode 100644
index 0000000000..945f4674de
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMPoint-001.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Geometry Interfaces: DOMPoint and DOMPointReadOnly interface tests</title>
+ <link rel="author" title="Dirk Schulze" href="mailto:dschulze@adobe.com" />
+ <link rel="help" href="https://www.w3.org/TR/geometry-1/#dictdef-dompointinit">
+ <link rel="help" href="https://www.w3.org/TR/geometry-1/#dom-dompoint-dompoint">
+ <link rel="help" href="https://www.w3.org/TR/geometry-1/#DOMPoint">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <p>Test DOMPoint and DOMPointReadOnly interfaces</p>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ checkDOMPoint(new DOMPoint(), {x:0, y:0, z:0, w:1});
+ },'testConstructor0');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1), {x:1, y:0, z:0, w:1});
+ },'testConstructor1');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1, 2), {x:1, y:2, z:0, w:1});
+ },'testConstructor2');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1, 2, 3), {x:1, y:2, z:3, w:1});
+ },'testConstructor3');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1, 2, 3, 4), {x:1, y:2, z:3, w:4});
+ },'testConstructor4');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1, 2, 3, 4, 5), {x:1, y:2, z:3, w:4});
+ },'testConstructor5');
+ test(function() {
+ checkDOMPoint(new DOMPoint({}), {x:NaN, y:0, z:0, w:1});
+ },'testConstructorDictionary0');
+ test(function() {
+ checkDOMPoint(new DOMPoint({x:1}), {x:NaN, y:0, z:0, w:1});
+ },'testConstructorDictionary1');
+ test(function() {
+ checkDOMPoint(new DOMPoint({x:1, y:2}), {x:NaN, y:0, z:0, w:1});
+ },'testConstructorDictionary2');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1, undefined), {x:1, y:0, z:0, w:1});
+ },'testConstructor2undefined');
+ test(function() {
+ checkDOMPoint(new DOMPoint("a", "b"), {x:NaN, y:NaN, z:0, w:1});
+ },'testConstructorUndefined1');
+ test(function() {
+ checkDOMPoint(new DOMPoint({x:"a", y:"b"}), {x:NaN, y:0, z:0, w:1});
+ },'testConstructorUndefined2');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly(), {x:0, y:0, z:0, w:1});
+ },'DOMPointReadOnly constructor with no values');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly(1, 2, 3, 4), {x:1, y:2, z:3, w:4});
+ },'DOMPointReadOnly constructor with 4 values');
+ test(function() {
+ var p = new DOMPoint(0, 0, 0, 1);
+ p.x = undefined;
+ p.y = undefined;
+ p.z = undefined;
+ p.w = undefined;
+ checkDOMPoint(p, {x:NaN, y:NaN, z:NaN, w:NaN});
+ },'testAttributesUndefined');
+ test(function() {
+ var p = new DOMPoint(0, 0, 0, 1);
+ p.x = NaN;
+ p.y = Number.POSITIVE_INFINITY;
+ p.z = Number.NEGATIVE_INFINITY;
+ p.w = Infinity;
+ checkDOMPoint(p, {x:NaN, y:Infinity, z:-Infinity, w:Infinity});
+ },'testAttributesNaNInfinity');
+
+ function checkDOMPoint(p, exp) {
+ assert_equals(p.x, exp.x, "Expected value for x is " + exp.x);
+ assert_equals(p.y, exp.y, "Expected value for y is " + exp.y);
+ assert_equals(p.z, exp.z, "Expected value for z is " + exp.z);
+ assert_equals(p.w, exp.w, "Expected value for w is " + exp.w);
+ }
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/geometry/DOMPoint-002.html b/testing/web-platform/tests/css/geometry/DOMPoint-002.html
new file mode 100644
index 0000000000..96276d86f5
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMPoint-002.html
@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<html><head>
+ <title>Geometry Interfaces: DOMPoint and DOMPointReadOnly interface tests</title>
+ <link href="mailto:hs1217.lee@samsung.com" rel="author" title="Hwanseung Lee">
+ <link href="https://drafts.fxtf.org/geometry-1/#DOMPoint" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <p>Test DOMPoint and DOMPointReadOnly interfaces</p>
+ <div id="log"></div>
+ <script>
+ function getMatrixTransform(matrix, point) {
+ var x = point.x * matrix.m11 + point.y * matrix.m21 + point.z * matrix.m31 + point.w * matrix.m41;
+ var y = point.x * matrix.m12 + point.y * matrix.m22 + point.z * matrix.m32 + point.w * matrix.m42;
+ var w = point.x * matrix.m13 + point.y * matrix.m23 + point.z * matrix.m33 + point.w * matrix.m43;
+ var z = point.x * matrix.m14 + point.y * matrix.m24 + point.z * matrix.m34 + point.w * matrix.m44;
+ return new DOMPoint(x, y, w, z)
+ }
+
+ test(function() {
+ checkDOMPoint(new DOMPoint(), {x:0, y:0, z:0, w:1});
+ },'test DOMPoint Constructor no args');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1), {x:1, y:0, z:0, w:1});
+ },'test DOMPoint Constructor one args');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1, 2), {x:1, y:2, z:0, w:1});
+ },'test DOMPoint Constructor two args');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1, 2, 3), {x:1, y:2, z:3, w:1});
+ },'test DOMPoint Constructor three args');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1, 2, 3, 4), {x:1, y:2, z:3, w:4});
+ },'test DOMPoint Constructor four args');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1, 2, 3, 4, 5), {x:1, y:2, z:3, w:4});
+ },'test DOMPoint Constructor more then four args');
+ test(function() {
+ checkDOMPoint(new DOMPoint(1, undefined), {x:1, y:0, z:0, w:1});
+ },'test DOMPoint Constructor with undefined');
+ test(function() {
+ checkDOMPoint(new DOMPoint("a", "b"), {x:NaN, y:NaN, z:0, w:1});
+ },'test DOMPoint Constructor with string');
+ test(function() {
+ checkDOMPoint(new DOMPoint({}), {x:NaN, y:0, z:0, w:1});
+ },'test DOMPoint Constructor with empty object');
+ test(function() {
+ checkDOMPoint(DOMPoint.fromPoint({}), {x:0, y:0, z:0, w:1});
+ },'test DOMPoint fromPoint with empty object');
+ test(function() {
+ checkDOMPoint(DOMPoint.fromPoint({x:1}), {x:1, y:0, z:0, w:1});
+ },'test DOMPoint fromPoint with x');
+ test(function() {
+ checkDOMPoint(DOMPoint.fromPoint({x:1, y:2}), {x:1, y:2, z:0, w:1});
+ },'test DOMPoint fromPoint with x, y');
+ test(function() {
+ checkDOMPoint(DOMPoint.fromPoint({x:1, y:2, z:3}), {x:1, y:2, z:3, w:1});
+ },'test DOMPoint fromPoint with x, y, z');
+ test(function() {
+ checkDOMPoint(DOMPoint.fromPoint({x:1, y:2, z:3, w:4}), {x:1, y:2, z:3, w:4});
+ },'test DOMPoint fromPoint with x, y, z, w');
+ test(function() {
+ checkDOMPoint(DOMPoint.fromPoint({x:1, y:2, z:3, w:4, v:5}), {x:1, y:2, z:3, w:4});
+ },'test DOMPoint fromPoint with x, y, z, w, v');
+ test(function() {
+ checkDOMPoint(DOMPoint.fromPoint({x:1, z:3}), {x:1, y:0, z:3, w:1});
+ },'test DOMPoint fromPoint with x, z');
+ test(function() {
+ checkDOMPoint(DOMPoint.fromPoint({x:1, y: undefined, z:3}), {x:1, y:0, z:3, w:1});
+ },'test DOMPoint fromPoint with undefined value');
+ test(function() {
+ var point = new DOMPoint(5, 4);
+ var matrix = new DOMMatrix([2, 0, 0, 2, 10, 10]);
+ var result = point.matrixTransform(matrix);
+ var expected = getMatrixTransform(matrix, point);
+ checkDOMPoint(result, expected);
+ },'test DOMPoint matrixTransform');
+ test(function() {
+ var point = new DOMPoint(42, 84);
+ assert_throws_js(TypeError, function() {
+ point.matrixTransform({ is2D: true, m33: 1.0000001 });
+ });
+ },'test DOMPoint matrixTransform with inconsistent input');
+ test(function() {
+ var p = new DOMPoint(0, 0, 0, 1);
+ p.x = undefined;
+ p.y = undefined;
+ p.z = undefined;
+ p.w = undefined;
+ checkDOMPoint(p, {x:NaN, y:NaN, z:NaN, w:NaN});
+ },'test DOMPoint Attributes undefined');
+ test(function() {
+ var p = new DOMPoint(0, 0, 0, 1);
+ p.x = NaN;
+ p.y = Number.POSITIVE_INFINITY;
+ p.z = Number.NEGATIVE_INFINITY;
+ p.w = Infinity;
+ checkDOMPoint(p, {x:NaN, y:Infinity, z:-Infinity, w:Infinity});
+ },'test DOMPoint Attributes NaN Infinity');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly(), {x:0, y:0, z:0, w:1});
+ },'test DOMPointReadOnly Constructor no args');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly(1), {x:1, y:0, z:0, w:1});
+ },'test DOMPointReadOnly Constructor one args');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly(1, 2), {x:1, y:2, z:0, w:1});
+ },'test DOMPointReadOnly Constructor two args');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly(1, 2, 3), {x:1, y:2, z:3, w:1});
+ },'test DOMPointReadOnly Constructor three args');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly(1, 2, 3, 4), {x:1, y:2, z:3, w:4});
+ },'test DOMPointReadOnly Constructor four args');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly(1, 2, 3, 4, 5), {x:1, y:2, z:3, w:4});
+ },'test DOMPointReadOnly Constructor more then four args');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly(1, undefined), {x:1, y:0, z:0, w:1});
+ },'test DOMPointReadOnly Constructor with undefined');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly("a", "b"), {x:NaN, y:NaN, z:0, w:1});
+ },'test DOMPointReadOnly Constructor with string');
+ test(function() {
+ checkDOMPoint(new DOMPointReadOnly({}), {x:NaN, y:0, z:0, w:1});
+ },'test DOMPointReadOnly Constructor with object');
+ test(function() {
+ checkDOMPoint(DOMPointReadOnly.fromPoint({}), {x:0, y:0, z:0, w:1});
+ },'test DOMPointReadOnly fromPoint with empty object');
+ test(function() {
+ checkDOMPoint(DOMPointReadOnly.fromPoint({x:1}), {x:1, y:0, z:0, w:1});
+ },'test DOMPointReadOnly fromPoint with x');
+ test(function() {
+ checkDOMPoint(DOMPointReadOnly.fromPoint({x:1, y:2}), {x:1, y:2, z:0, w:1});
+ },'test DOMPointReadOnly fromPoint with x, y');
+ test(function() {
+ checkDOMPoint(DOMPointReadOnly.fromPoint({x:1, y:2, z:3}), {x:1, y:2, z:3, w:1});
+ },'test DOMPointReadOnly fromPoint with x, y, z');
+ test(function() {
+ checkDOMPoint(DOMPointReadOnly.fromPoint({x:1, y:2, z:3, w:4}), {x:1, y:2, z:3, w:4});
+ },'test DOMPointReadOnly fromPoint with x, y, z, w');
+ test(function() {
+ checkDOMPoint(DOMPointReadOnly.fromPoint({x:1, y:2, z:3, w:4, v:5}), {x:1, y:2, z:3, w:4});
+ },'test DOMPointReadOnly fromPoint with x, y, z, w, v');
+ test(function() {
+ checkDOMPoint(DOMPointReadOnly.fromPoint({x:1, z:3}), {x:1, y:0, z:3, w:1});
+ },'test DOMPointReadOnly fromPoint with x, z');
+ test(function() {
+ checkDOMPoint(DOMPointReadOnly.fromPoint({x:1, y: undefined, z:3}), {x:1, y:0, z:3, w:1});
+ },'test DOMPointReadOnly fromPoint with undefined value');
+ test(function() {
+ var point = new DOMPointReadOnly(5, 4);
+ var matrix = new DOMMatrix([1, 2, 3, 4, 5, 6]);
+ var result = point.matrixTransform(matrix);
+ var expected = getMatrixTransform(matrix, point);
+ checkDOMPoint(result, expected);
+ },'test DOMPointReadOnly matrixTransform');
+ test(function() {
+ var p = new DOMPointReadOnly(0, 0, 0, 1);
+ p.x = undefined;
+ p.y = undefined;
+ p.z = undefined;
+ p.w = undefined;
+ checkDOMPoint(p, {x:0, y:0, z:0, w:1});
+ },'test DOMPointReadOnly Attributes undefined');
+
+ function checkDOMPoint(p, exp) {
+ assert_equals(p.x, exp.x, "x is not matched");
+ assert_equals(p.y, exp.y, "y is not matched");
+ assert_equals(p.z, exp.z, "z is not matched");
+ assert_equals(p.w, exp.w, "w is not matched");
+ }
+ </script>
+
+
+</body></html>
diff --git a/testing/web-platform/tests/css/geometry/DOMQuad-001.html b/testing/web-platform/tests/css/geometry/DOMQuad-001.html
new file mode 100644
index 0000000000..6fa765bbab
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMQuad-001.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Geometry Interfaces: DOMQuad interface tests</title>
+ <link rel="author" title="Dirk Schulze" href="mailto:dschulze@adobe.com" />
+ <link rel="help" href="https://www.w3.org/TR/geometry-1/#dom-domquad-domquad">
+ <link rel="help" href="https://www.w3.org/TR/geometry-1/#dom-domquad-p1">
+ <link rel="help" href="https://www.w3.org/TR/geometry-1/#dom-domquad-p2">
+ <link rel="help" href="https://www.w3.org/TR/geometry-1/#dom-domquad-p3">
+ <link rel="help" href="https://www.w3.org/TR/geometry-1/#dom-domquad-p4">
+ <link rel="help" href="https://www.w3.org/TR/geometry-1/#DOMQuad">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <p>Test DOMQuad interface</p>
+ <div id="log"></div>
+ <script>
+ var initial = {
+ p1: { x: 0, y: 0, z: 0, w: 1 },
+ p2: { x: 0, y: 0, z: 0, w: 1 },
+ p3: { x: 0, y: 0, z: 0, w: 1 },
+ p4: { x: 0, y: 0, z: 0, w: 1 },
+ bounds: { x: 0, y: 0, width: 0, height: 0 }
+ };
+
+ checkDOMQuad(function() { return new DOMQuad(); }, initial, 'testConstructor0');
+
+ test(function() {
+ assert_throws_js(TypeError, function() { new DOMQuad(1); });
+ },'testConstructor1');
+
+ test(function() {
+ assert_throws_js(TypeError, function() { new DOMQuad(1, 2); });
+ },'testConstructor2');
+
+ test(function() {
+ assert_throws_js(TypeError, function() { new DOMQuad(1, 2, 3); });
+ },'testConstructor3');
+
+ test(function() {
+ assert_throws_js(TypeError, function() { new DOMQuad(1, 2, 3, 4); });
+ },'testConstructor4');
+
+ checkDOMQuad(
+ function() { return DOMQuad.fromRect(new DOMRect(10, 20, 100, 200)); },
+ { p1: { x: 10, y: 20, z: 0, w: 1 },
+ p2: { x: 110, y: 20, z: 0, w: 1 },
+ p3: { x: 110, y: 220, z: 0, w: 1 },
+ p4: { x: 10, y: 220, z: 0, w: 1 },
+ bounds: { x: 10, y: 20, width: 100, height: 200 } },
+ 'fromRect() method on DOMQuad');
+
+ checkDOMQuad(
+ function() { return DOMQuad.fromRect(new DOMRect(10, 20, -100, -200)) },
+ { p1: { x: 10, y: 20, z: 0, w: 1 },
+ p2: { x: -90, y: 20, z: 0, w: 1 },
+ p3: { x: -90, y: -180, z: 0, w: 1 },
+ p4: { x: 10, y: -180, z: 0, w: 1 },
+ bounds: { x: -90, y: -180, width: 100, height: 200 } },
+ 'fromRect() method on DOMQuad with negatives');
+
+ checkDOMQuad(
+ function() { return DOMQuad.fromRect(new DOMRect(-Infinity, -Infinity, Infinity, Infinity)) },
+ { p1: { x: -Infinity, y: -Infinity, z: 0, w: 1 },
+ p2: { x: NaN, y: -Infinity, z: 0, w: 1 },
+ p3: { x: NaN, y: NaN, z: 0, w: 1 },
+ p4: { x: -Infinity, y: NaN, z: 0, w: 1 },
+ bounds: { x: NaN, y: NaN, width: NaN, height: NaN } },
+ 'fromRect() method on DOMQuad with Infinity');
+
+ checkDOMQuad(function() { return new DOMQuad(new DOMRect()); }, initial, 'testConstructor8');
+
+ checkDOMQuad(function() { return new DOMQuad({}); }, initial, 'testConstructor9');
+
+ checkDOMQuad(function() { return new DOMQuad({}, {}); }, initial, 'testConstructor10');
+
+ checkDOMQuad(function() { return new DOMQuad({}, {}, {}); }, initial, 'testConstructor11');
+
+ checkDOMQuad(function() { return new DOMQuad({}, {}, {}, {}); }, initial, 'testConstructor12');
+
+ checkDOMQuad(function() { return new DOMQuad(null, undefined, {}, {}); }, initial, 'testConstructor13');
+
+ checkDOMQuad(function() { return new DOMQuad({}, {}, {}, {}, NaN); }, initial, 'testConstructor14');
+
+ test(function() {
+ assert_throws_js(TypeError, function() { new DOMQuad({}, {}, {}, NaN); });
+ },'testConstructor15');
+
+ checkDOMQuad(function() {
+ return new DOMQuad({ y: 10 }, { x: 20 }, { z: 30 }, { x: 20, y: 10, z: 20, w: 10 });
+ },
+ { p1: { x: 0, y: 10, z: 0, w: 1 },
+ p2: { x: 20, y: 0, z: 0, w: 1 },
+ p3: { x: 0, y: 0, z: 30, w: 1 },
+ p4: { x: 20, y: 10, z: 20, w: 10 },
+ bounds: { x: 0, y: 0, width: 20, height: 10 } },
+ 'testConstructor16');
+
+ checkDOMQuad(function() {
+ // p1 to p4 are readonly attributes.
+ var q = new DOMQuad({}, {}, {}, {});
+ q.p1 = new DOMPoint(2, 2);
+ q.p2 = new DOMPoint(2, 2);
+ q.p3 = new DOMPoint(2, 2);
+ q.p4 = new DOMPoint(2, 2);
+ return q;
+ }, initial, 'p1Top4Attributes0');
+
+ checkDOMQuad(function() {
+ var q = new DOMQuad({}, {}, {}, {});
+ q.p1.x = 2;
+ q.p2.x = 2;
+ q.p3.x = 2;
+ q.p4.x = 2;
+ return q;
+ },
+ { p1: { x: 2, y: 0, z: 0, w: 1 },
+ p2: { x: 2, y: 0, z: 0, w: 1 },
+ p3: { x: 2, y: 0, z: 0, w: 1 },
+ p4: { x: 2, y: 0, z: 0, w: 1 },
+ bounds: { x: 2, y: 0, width: 0, height: 0 } },
+ 'p1Top4Attributes1');
+
+ function checkDOMQuad(createQuad, exp, name) {
+ test(function() {
+ var q = createQuad();
+ assert_equals(q.p1.x, exp.p1.x, "Expected value for p1.x is " + exp.p1.x);
+ assert_equals(q.p1.y, exp.p1.y, "Expected value for p1.y is " + exp.p1.y);
+ assert_equals(q.p1.z, exp.p1.z, "Expected value for p1.z is " + exp.p1.z);
+ assert_equals(q.p1.w, exp.p1.w, "Expected value for p1.w is " + exp.p1.w);
+ assert_equals(q.p2.x, exp.p2.x, "Expected value for p2.x is " + exp.p2.x);
+ assert_equals(q.p2.y, exp.p2.y, "Expected value for p2.y is " + exp.p2.y);
+ assert_equals(q.p2.z, exp.p2.z, "Expected value for p2.z is " + exp.p2.z);
+ assert_equals(q.p2.w, exp.p2.w, "Expected value for p2.w is " + exp.p2.w);
+ assert_equals(q.p3.x, exp.p3.x, "Expected value for p3.x is " + exp.p3.x);
+ assert_equals(q.p3.y, exp.p3.y, "Expected value for p3.y is " + exp.p3.y);
+ assert_equals(q.p3.z, exp.p3.z, "Expected value for p3.z is " + exp.p3.z);
+ assert_equals(q.p3.w, exp.p3.w, "Expected value for p3.w is " + exp.p3.w);
+ assert_equals(q.p4.x, exp.p4.x, "Expected value for p4.x is " + exp.p4.x);
+ assert_equals(q.p4.y, exp.p4.y, "Expected value for p4.y is " + exp.p4.y);
+ assert_equals(q.p4.z, exp.p4.z, "Expected value for p4.z is " + exp.p4.z);
+ assert_equals(q.p4.w, exp.p4.w, "Expected value for p4.w is " + exp.p4.w);
+ }, name + ": points");
+
+ test(function() {
+ var q = createQuad();
+ assert_equals(q.getBounds().x, exp.bounds.x, "Expected value for getBounds().x is " + exp.bounds.x);
+ assert_equals(q.getBounds().y, exp.bounds.y, "Expected value for getBounds().y is " + exp.bounds.y);
+ assert_equals(q.getBounds().width, exp.bounds.width, "Expected value for getBounds().width is " + exp.bounds.width);
+ assert_equals(q.getBounds().height, exp.bounds.height, "Expected value for getBounds().height is " + exp.bounds.height);
+ }, name + ": bounds");
+ }
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/geometry/DOMQuad-002.html b/testing/web-platform/tests/css/geometry/DOMQuad-002.html
new file mode 100644
index 0000000000..5734be1f29
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMQuad-002.html
@@ -0,0 +1,173 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Geometry Interfaces: DOMQuad interface tests</title>
+ <link rel="author" title="Hwanseung Lee" href="mailto:hs1217.lee@samsung.com" />
+ <link rel="help" href="https://drafts.fxtf.org/geometry-1/#DOMQuad">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <p>Test DOMQuad interface</p>
+ <div id="log"></div>
+ <script>
+
+ function init() {
+ var initial = {
+ p1: { x: 0, y: 0, z: 0, w: 1 },
+ p2: { x: 0, y: 0, z: 0, w: 1 },
+ p3: { x: 0, y: 0, z: 0, w: 1 },
+ p4: { x: 0, y: 0, z: 0, w: 1 }
+ };
+ return initial;
+ }
+
+ test(function() {
+ checkDOMQuad(new DOMQuad(), init());
+ },'test Constructor no args');
+
+ test(function() {
+ checkDOMQuad(new DOMQuad(new DOMPoint()), init());
+ },'test Constructor with one init DOMPoint arg');
+
+ test(function() {
+ checkDOMQuad(new DOMQuad(new DOMPoint(), new DOMPoint()), init());
+ },'test Constructor with two init DOMPoint args');
+
+ test(function() {
+ checkDOMQuad(new DOMQuad(new DOMPoint(), new DOMPoint(), new DOMPoint()), init());
+ },'test Constructor with three init DOMPoint args');
+
+ test(function() {
+ checkDOMQuad(new DOMQuad(new DOMPoint(), new DOMPoint(), new DOMPoint(), new DOMPoint()), init());
+ },'test Constructor with four init DOMPoint args');
+
+ test(function() {
+ var exp = init();
+ exp.p1 = { x: 1, y: 2, z: 3, w: 4 };
+ checkDOMQuad(new DOMQuad(new DOMPoint(1, 2, 3, 4)), exp);
+ },'test Constructor with one DOMPoint arg');
+
+ test(function() {
+ var exp = init();
+ exp.p1 = { x: 1, y: 2, z: 3, w: 4 };
+ exp.p2 = { x: 5, y: 6, z: 7, w: 8 };
+ checkDOMQuad(new DOMQuad(new DOMPoint(1, 2, 3, 4), new DOMPoint(5, 6, 7, 8)), exp);
+ },'test Constructor with two DOMPoint args');
+
+ test(function() {
+ var exp = init();
+ exp.p1 = { x: 1, y: 2, z: 3, w: 4 };
+ exp.p2 = { x: 5, y: 6, z: 7, w: 8 };
+ exp.p3 = { x: 9, y: 10, z: 11, w: 12 };
+ checkDOMQuad(new DOMQuad(new DOMPoint(1, 2, 3, 4), new DOMPoint(5, 6, 7, 8), new DOMPoint(9, 10, 11, 12)), exp);
+ },'test Constructor with three DOMPoint args');
+
+ test(function() {
+ var exp = init();
+ exp.p1 = { x: 1, y: 2, z: 3, w: 4 };
+ exp.p2 = { x: 5, y: 6, z: 7, w: 8 };
+ exp.p3 = { x: 9, y: 10, z: 11, w: 12 };
+ exp.p4 = { x: 13, y: 14, z: 15, w: 16 };
+ checkDOMQuad(new DOMQuad(new DOMPoint(1, 2, 3, 4), new DOMPoint(5, 6, 7, 8), new DOMPoint(9, 10, 11, 12), new DOMPoint(13, 14, 15, 16)), exp);
+ },'test Constructor with four DOMPoint args');
+
+ test(function() {
+ assert_throws_js(TypeError, function() { new DOMQuad(1, 2, 3, 4); });
+ },'test Constructor with invaild integer args');
+
+ test(function() {
+ assert_throws_js(TypeError, function() { new DOMQuad("1", "2", "3", "4"); });
+ },'test Constructor with invaild string args');
+
+ test(function() {
+ assert_throws_js(TypeError, function() { new DOMQuad({}, {}, {}, NaN); });
+ },'test Constructor with NaN');
+
+ test(function() {
+ var domQuad = DOMQuad.fromRect(new DOMRect(10, 20, 100, 200));
+ var expQuad = init();
+ expQuad.p1 = { x: 10, y: 20, z: 0, w: 1 };
+ expQuad.p2 = { x: 110, y: 20, z: 0, w: 1 };
+ expQuad.p3 = { x: 110, y: 220, z: 0, w: 1 };
+ expQuad.p4 = { x: 10, y: 220, z: 0, w: 1 };
+ checkDOMQuad(domQuad, expQuad);
+ },'test fromRect');
+
+ test(function() {
+ var domQuad = DOMQuad.fromRect(new DOMRect(-Infinity, -Infinity, Infinity, Infinity));
+ var expQuad = init();
+ expQuad.p1 = { x: -Infinity, y: -Infinity, z: 0, w: 1 };
+ expQuad.p2 = { x: NaN, y: -Infinity, z: 0, w: 1 };
+ expQuad.p3 = { x: NaN, y: NaN, z: 0, w: 1 };
+ expQuad.p4 = { x: -Infinity, y: NaN, z: 0, w: 1 };
+ checkDOMQuad(domQuad, expQuad);
+ },'test fromRect with Infinity');
+
+ test(function() {
+ var domQuad = DOMQuad.fromQuad(
+ new DOMQuad(
+ new DOMPoint(1, 2, 3, 4),
+ new DOMPoint(5, 6, 7, 8),
+ new DOMPoint(9, 10, 11, 12),
+ new DOMPoint(13, 14, 15, 16)));
+ var exp = init();
+ exp.p1 = { x: 1, y: 2, z: 3, w: 4 };
+ exp.p2 = { x: 5, y: 6, z: 7, w: 8 };
+ exp.p3 = { x: 9, y: 10, z: 11, w: 12 };
+ exp.p4 = { x: 13, y: 14, z: 15, w: 16 };
+ checkDOMQuad(domQuad, exp);
+ },'test fromQuad');
+
+ test(function() {
+ var domQuad = new DOMQuad();
+ domQuad.p1 = new DOMPoint(1, 2, 3, 4);
+ domQuad.p2 = new DOMPoint(1, 2, 3, 4);
+ domQuad.p3 = new DOMPoint(1, 2, 3, 4);
+ domQuad.p4 = new DOMPoint(1, 2, 3, 4);
+ checkDOMQuad(domQuad, init());
+ },'test p1, p2, p3, p4 are readonly');
+
+ test(function() {
+ var domQuad = DOMQuad.fromQuad(
+ new DOMQuad(
+ new DOMPoint(10, 20, 0, 1),
+ new DOMPoint(110, 20, 0, 1),
+ new DOMPoint(110, 220, 0, 1),
+ new DOMPoint(10, 220, 10, 1)));
+ var expBound = new DOMRect(10, 20, 100, 200);
+ checkDOMRect(domQuad.getBounds(), expBound);
+ },'test getBounds');
+
+ function checkDOMQuad(actual, exp) {
+ assert_equals(actual.p1.x, exp.p1.x, "p1.x is not matched");
+ assert_equals(actual.p1.y, exp.p1.y, "p1.y is not matched");
+ assert_equals(actual.p1.z, exp.p1.z, "p1.z is not matched");
+ assert_equals(actual.p1.w, exp.p1.w, "p1.w is not matched");
+ assert_equals(actual.p2.x, exp.p2.x, "p2.x is not matched");
+ assert_equals(actual.p2.y, exp.p2.y, "p2.y is not matched");
+ assert_equals(actual.p2.z, exp.p2.z, "p2.z is not matched");
+ assert_equals(actual.p2.w, exp.p2.w, "p2.w is not matched");
+ assert_equals(actual.p3.x, exp.p3.x, "p3.x is not matched");
+ assert_equals(actual.p3.y, exp.p3.y, "p3.y is not matched");
+ assert_equals(actual.p3.z, exp.p3.z, "p3.z is not matched");
+ assert_equals(actual.p3.w, exp.p3.w, "p3.w is not matched");
+ assert_equals(actual.p4.x, exp.p4.x, "p4.x is not matched");
+ assert_equals(actual.p4.y, exp.p4.y, "p4.y is not matched");
+ assert_equals(actual.p4.z, exp.p4.z, "p4.z is not matched");
+ assert_equals(actual.p4.w, exp.p4.w, "p4.w is not matched");
+ }
+
+ function checkDOMRect(actual, exp) {
+ assert_equals(actual.x, exp.x, "x is not matched");
+ assert_equals(actual.y, exp.y, "y is not matched");
+ assert_equals(actual.width, exp.width, "width is not matched");
+ assert_equals(actual.height, exp.height, "height is not matched");
+ assert_equals(actual.top, exp.top, "top is not matched");
+ assert_equals(actual.left, exp.left, "left is not matched");
+ assert_equals(actual.bottom, exp.bottom, "bottom is not matched");
+ assert_equals(actual.right, exp.right, "right is not matched");
+ }
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/geometry/DOMQuad-nan.html b/testing/web-platform/tests/css/geometry/DOMQuad-nan.html
new file mode 100644
index 0000000000..8d93d5ecfa
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMQuad-nan.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>DOMRect's handling of NaN in top/bottom/left/right</title>
+<link rel=help href="https://drafts.fxtf.org/geometry/#dom-domrectreadonly-domrect-top">
+<link rel=help href="https://drafts.fxtf.org/geometry/#dom-domrectreadonly-domrect-bottom">
+<link rel=help href="https://drafts.fxtf.org/geometry/#dom-domrectreadonly-domrect-left">
+<link rel=help href="https://drafts.fxtf.org/geometry/#dom-domrectreadonly-domrect-right">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+"use strict";
+
+for (const i of [1, 2, 3, 4]) {
+ for (const comp of ["x", "y"]) {
+ test(() => {
+ const args = [{ x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 }];
+ args[i - 1][comp] = NaN;
+ const quad = new DOMQuad(...args);
+ const bounds = quad.getBounds();
+ if (comp === "x") {
+ assert_equals(bounds.x, NaN, "x coordinate");
+ assert_equals(bounds.y, 0, "y coordinate");
+ assert_equals(bounds.width, NaN, "width");
+ assert_equals(bounds.height, 0, "height");
+ } else {
+ assert_equals(bounds.x, 0, "x coordinate");
+ assert_equals(bounds.y, NaN, "y coordinate");
+ assert_equals(bounds.width, 0, "width");
+ assert_equals(bounds.height, NaN, "height");
+ }
+ }, `Setting DOMQuad's p${i}.${comp} to NaN`);
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMRect-001.html b/testing/web-platform/tests/css/geometry/DOMRect-001.html
new file mode 100644
index 0000000000..3055d8d26b
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMRect-001.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Geometry Interfaces: DOMRect and DOMRectReadOnly interface tests</title>
+ <link rel="author" title="Dirk Schulze" href="mailto:dschulze@adobe.com" />
+ <link rel="help" href="https://www.w3.org/TR/geometry-1/#DOMRect">
+ <link rel="help" href="http://www.w3.org/TR/geometry-1/#dom-domrectreadonly-domrect-x">
+ <link rel="help" href="http://www.w3.org/TR/geometry-1/#dom-domrectreadonly-domrect-y">
+ <link rel="help" href="http://www.w3.org/TR/geometry-1/#dom-domrectreadonly-domrect-width">
+ <link rel="help" href="http://www.w3.org/TR/geometry-1/#dom-domrectreadonly-domrect-height">
+ <link rel="help" href="http://www.w3.org/TR/geometry-1/#dom-domrectreadonly-domrect-top">
+ <link rel="help" href="http://www.w3.org/TR/geometry-1/#dom-domrectreadonly-domrect-left">
+ <link rel="help" href="http://www.w3.org/TR/geometry-1/#dom-domrectreadonly-domrect-right">
+ <link rel="help" href="http://www.w3.org/TR/geometry-1/#dom-domrectreadonly-domrect-bottom">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <p>Test DOMRect and DOMRectReadOnly interfaces</p>
+ <div id="log"></div>
+ <script>
+ testConstructor(DOMRect);
+ testConstructor(DOMRectReadOnly);
+ test(function() {
+ var r = new DOMRect();
+ r.top = 5;
+ assert_equals(r.top, 0, "Expected value for top is 0");
+ r.right = 5;
+ assert_equals(r.right, 0, "Expected value for right is 0");
+ r.bottom = 5;
+ assert_equals(r.bottom, 0, "Expected value for bottom is 0");
+ r.left = 5;
+ assert_equals(r.left, 0, "Expected value for left is 0");
+ },'testSetReadOnlyAttributes');
+ test(function() {
+ var r = new DOMRect();
+ r.x = 5;
+ assert_equals(r.x, 5, "Expected value for x is 5");
+ assert_equals(r.left, 5, "Expected value for left is 5");
+ assert_equals(r.right, 5, "Expected value for right is 5");
+ r.y = 5;
+ assert_equals(r.y, 5, "Expected value for y is 5");
+ assert_equals(r.top, 5, "Expected value for top is 5");
+ assert_equals(r.bottom, 5, "Expected value for bottom is 5");
+ r.width = 5;
+ assert_equals(r.width, 5, "Expected value for width is 5");
+ assert_equals(r.left, 5, "Expected value for left is 5");
+ assert_equals(r.right, 10, "Expected value for right is 10");
+ r.height = 5;
+ assert_equals(r.height, 5, "Expected value for height is 5");
+ assert_equals(r.top, 5, "Expected value for top is 5");
+ assert_equals(r.bottom, 10, "Expected value for bottom is 10");
+ },'testSetAttributes');
+ test(function() {
+ var r = new DOMRectReadOnly();
+ r.top = 5;
+ assert_equals(r.top, 0, "Expected value for top is 0");
+ assert_equals(r.y, 0, "Expected value for y is 0");
+ assert_equals(r.bottom, 0, "Expected value for bottom is 0");
+ r.right = 5;
+ assert_equals(r.right, 0, "Expected value for right is 0");
+ assert_equals(r.x, 0, "Expected value for x is 0");
+ assert_equals(r.left, 0, "Expected value for left is 0");
+ r.bottom = 5;
+ assert_equals(r.bottom, 0, "Expected value for bottom is 0");
+ assert_equals(r.y, 0, "Expected value for y is 0");
+ assert_equals(r.top, 0, "Expected value for top is 0");
+ r.left = 5;
+ assert_equals(r.left, 0, "Expected value for left is 0");
+ assert_equals(r.x, 0, "Expected value for x is 0");
+ assert_equals(r.right, 0, "Expected value for right is 0");
+ },'testReadOnlySetReadOnlyAttributes');
+ test(function() {
+ var r = new DOMRectReadOnly();
+ r.x = 0;
+ assert_equals(r.x, 0, "Expected value for x is 0");
+ assert_equals(r.left, 0, "Expected value for left is 0");
+ assert_equals(r.right, 0, "Expected value for right is 0");
+ r.y = 0;
+ assert_equals(r.y, 0, "Expected value for y is 0");
+ assert_equals(r.top, 0, "Expected value for top is 0");
+ assert_equals(r.bottom, 0, "Expected value for bottom is 0");
+ r.width = 0;
+ assert_equals(r.width, 0, "Expected value for width is 0");
+ assert_equals(r.x, 0, "Expected value for x is 0");
+ assert_equals(r.right, 0, "Expected value for right is 0");
+ r.height = 0;
+ assert_equals(r.height, 0, "Expected value for height is 0");
+ assert_equals(r.y, 0, "Expected value for y is 0");
+ assert_equals(r.bottom, 0, "Expected value for bottom is 0");
+ },'testReadOnlySetAttributes');
+
+ function testConstructor(constructor) {
+ var prefix = constructor === DOMRect ? 'testConstructor' : 'testReadOnlyConstructor';
+ test(function() {
+ checkDOMRect(new constructor(),
+ { x: 0, y: 0, width: 0, height: 0, top: 0, right: 0, bottom: 0, left: 0 });
+ }, prefix + '0');
+ test(function() {
+ checkDOMRect(new constructor(1),
+ { x: 1, y: 0, width: 0, height: 0, top: 0, right: 1, bottom: 0, left: 1 });
+ }, prefix + '1');
+ test(function() {
+ checkDOMRect(new constructor(1, 2),
+ { x: 1, y: 2, width: 0, height: 0, top: 2, right: 1, bottom: 2, left: 1 });
+ }, prefix + '2');
+ test(function() {
+ checkDOMRect(new constructor(1, 2, 3),
+ { x: 1, y: 2, width: 3, height: 0, top: 2, right: 4, bottom: 2, left: 1 });
+ }, prefix + '3');
+ test(function() {
+ checkDOMRect(new constructor(1, 2, 3, 4),
+ { x: 1, y: 2, width: 3, height: 4, top: 2, right: 4, bottom: 6, left: 1 });
+ }, prefix + '4');
+ test(function() {
+ checkDOMRect(new constructor(1, 2, 3, 4, 5),
+ { x: 1, y: 2, width: 3, height: 4, top: 2, right: 4, bottom: 6, left: 1 });
+ }, prefix + '5');
+ test(function() {
+ checkDOMRect(new constructor(2, 2, -4, 4),
+ { x: 2, y: 2, width: -4, height: 4, top: 2, right: 2, bottom: 6, left: -2 });
+ }, prefix + 'NegativeWidth');
+ test(function() {
+ checkDOMRect(new constructor(2, 2, 4, -4),
+ { x: 2, y: 2, width: 4, height: -4, top: -2, right: 6, bottom: 2, left: 2 });
+ }, prefix + 'NegativeHeight');
+ test(function() {
+ checkDOMRect(new constructor(2, 2, -4, -4),
+ { x: 2, y: 2, width: -4, height: -4, top: -2, right: 2, bottom: 2, left: -2 });
+ }, prefix + 'NegativeWidthHeight');
+ test(function() {
+ checkDOMRect(new constructor(0, 0, undefined, 4),
+ { x: 0, y: 0, width: 0, height: 4, top: 0, right: 0, bottom: 4, left: 0 });
+ }, prefix + 'Undefined1');
+ test(function() {
+ checkDOMRect(new constructor(NaN, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, null),
+ { x: NaN, y: -Infinity, width: Infinity, height: 0, top: -Infinity, right: NaN, bottom: -Infinity, left: NaN });
+ }, prefix + 'Undefined2');
+ test(function() {
+ checkDOMRect(new constructor("1", "2", "3", "4"),
+ { x: 1, y: 2, width: 3, height: 4, top: 2, right: 4, bottom: 6, left: 1 });
+ }, prefix + 'String1');
+ test(function() {
+ checkDOMRect(new constructor("a", "b", "c", "d"),
+ { x: NaN, y: NaN, width: NaN, height: NaN, top: NaN, right: NaN, bottom: NaN, left: NaN });
+ }, prefix + 'String2');
+ }
+
+ function checkDOMRect(r, exp) {
+ assert_equals(r.x, exp.x, "Expected value for x is " + exp.x);
+ assert_equals(r.y, exp.y, "Expected value for y is " + exp.y);
+ assert_equals(r.width, exp.width, "Expected value for width is " + exp.width);
+ assert_equals(r.height, exp.height, "Expected value for height is " + exp.height);
+ assert_equals(r.top, exp.top, "Expected value for top is " + exp.top);
+ assert_equals(r.left, exp.left, "Expected value for left is " + exp.left);
+ assert_equals(r.bottom, exp.bottom, "Expected value for bottom is " + exp.bottom);
+ assert_equals(r.right, exp.right, "Expected value for right is " + exp.right);
+ }
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/geometry/DOMRect-002.html b/testing/web-platform/tests/css/geometry/DOMRect-002.html
new file mode 100644
index 0000000000..a5f0f88428
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMRect-002.html
@@ -0,0 +1,171 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Geometry Interfaces: DOMRect and DOMRectReadOnly interface tests</title>
+ <link rel="author" title="Hwanseung Lee" href="mailto:hs1217.lee@samsung.com" />
+ <link rel="help" href="https://drafts.fxtf.org/geometry-1/#DOMRect">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script>
+ testConstructor("DOMRect");
+ testConstructor("DOMRectReadOnly");
+ test(function() {
+ var r = new DOMRect();
+ r.top = 5;
+ assert_equals(r.top, 0, "top");
+ r.right = 5;
+ assert_equals(r.right, 0, "right");
+ r.bottom = 5;
+ assert_equals(r.bottom, 0, "bottom");
+ r.left = 5;
+ assert_equals(r.left, 0, "left");
+ }, 'DOMRect: set top/right/bottom/left');
+
+ test(function() {
+ var r = new DOMRect();
+ r.x = 5;
+ assert_equals(r.x, 5, "Expected value for x is 5");
+ assert_equals(r.left, 5, "Expected value for left is 5");
+ assert_equals(r.right, 5, "Expected value for right is 5");
+ r.y = 5;
+ assert_equals(r.y, 5, "Expected value for y is 5");
+ assert_equals(r.top, 5, "Expected value for top is 5");
+ assert_equals(r.bottom, 5, "Expected value for bottom is 5");
+ r.width = 5;
+ assert_equals(r.width, 5, "Expected value for width is 5");
+ assert_equals(r.left, 5, "Expected value for left is 5");
+ assert_equals(r.right, 10, "Expected value for right is 10");
+ r.height = 5;
+ assert_equals(r.height, 5, "Expected value for height is 5");
+ assert_equals(r.top, 5, "Expected value for top is 5");
+ assert_equals(r.bottom, 10, "Expected value for bottom is 10");
+ }, 'DOMRect: set x/y/width/height');
+
+ test(function() {
+ var r = new DOMRectReadOnly();
+ r.top = 5;
+ assert_equals(r.top, 0, "top after setting top");
+ assert_equals(r.y, 0, "y after setting top");
+ assert_equals(r.bottom, 0, "bottom after setting top");
+ r.right = 5;
+ assert_equals(r.right, 0, "right after setting right");
+ assert_equals(r.x, 0, "x after setting right");
+ assert_equals(r.left, 0, "left after setting right");
+ r.bottom = 5;
+ assert_equals(r.bottom, 0, "bottom after setting bottom");
+ assert_equals(r.y, 0, "y after setting bottom");
+ assert_equals(r.top, 0, "top after setting bottom");
+ r.left = 5;
+ assert_equals(r.left, 0, "left after setting left");
+ assert_equals(r.x, 0, "x after setting left");
+ assert_equals(r.right, 0, "right after setting left");
+ }, 'DOMRectReadOnly: set top/right/bottom/left');
+
+ test(function() {
+ var r = new DOMRectReadOnly();
+ r.x = 5;
+ assert_equals(r.x, 0, "x after setting x");
+ assert_equals(r.left, 0, "left after setting x");
+ assert_equals(r.right, 0, "right after setting x");
+ r.y = 5;
+ assert_equals(r.y, 0, "y after setting y");
+ assert_equals(r.top, 0, "top after setting y");
+ assert_equals(r.bottom, 0, "bottom after setting y");
+ r.width = 5;
+ assert_equals(r.width, 0, "width after setting width");
+ assert_equals(r.x, 0, "x after setting width");
+ assert_equals(r.right, 0, "right after setting width");
+ r.height = 5;
+ assert_equals(r.height, 0, "height after setting height");
+ assert_equals(r.y, 0, "y after setting height");
+ assert_equals(r.bottom, 0, "bottom after setting height");
+ }, 'DOMRectReadOnly: set x/y/width/height');
+
+ test(function() {
+ var actual = DOMRect.fromRect({x: 1, y: 2, width: 3, height: 4});
+ var expected = new DOMRect(1, 2, 3, 4);
+ checkDOMRect(actual, expected);
+ assert_true(actual instanceof DOMRectReadOnly, "actual instanceof DOMRectReadOnly");
+ assert_true(actual instanceof DOMRect, "actual instanceof DOMRect");
+ }, 'DOMRect.fromRect');
+
+ test(function() {
+ var actual = DOMRectReadOnly.fromRect({x: 1, y: 2, width: 3, height: 4});
+ var expected = new DOMRectReadOnly(1, 2, 3, 4);
+ checkDOMRect(actual, expected);
+ assert_true(actual instanceof DOMRectReadOnly, "actual instanceof DOMRectReadOnly");
+ assert_false(actual instanceof DOMRect, "actual instanceof DOMRect");
+ }, 'DOMRectReadOnly.fromRect');
+
+ function testConstructor(constructorString) {
+ var constructor = self[constructorString];
+ test(function() {
+ checkDOMRect(new constructor(),
+ { x: 0, y: 0, width: 0, height: 0, top: 0, right: 0, bottom: 0, left: 0 });
+ }, constructorString + ' constructor without parameter');
+ test(function() {
+ checkDOMRect(new constructor(1),
+ { x: 1, y: 0, width: 0, height: 0, top: 0, right: 1, bottom: 0, left: 1 });
+ }, constructorString + ' constructor with one parameter');
+ test(function() {
+ checkDOMRect(new constructor(1, 2),
+ { x: 1, y: 2, width: 0, height: 0, top: 2, right: 1, bottom: 2, left: 1 });
+ }, constructorString + ' constructor with two parameters');
+ test(function() {
+ checkDOMRect(new constructor(1, 2, 3),
+ { x: 1, y: 2, width: 3, height: 0, top: 2, right: 4, bottom: 2, left: 1 });
+ }, constructorString + ' constructor with three parameters');
+ test(function() {
+ checkDOMRect(new constructor(1, 2, 3, 4),
+ { x: 1, y: 2, width: 3, height: 4, top: 2, right: 4, bottom: 6, left: 1 });
+ }, constructorString + ' constructor with four parameters');
+ test(function() {
+ checkDOMRect(new constructor(1, 2, 3, 4, 5),
+ { x: 1, y: 2, width: 3, height: 4, top: 2, right: 4, bottom: 6, left: 1 });
+ }, constructorString + ' constructor with five parameters');
+ test(function() {
+ checkDOMRect(new constructor(2, 2, -4, 4),
+ { x: 2, y: 2, width: -4, height: 4, top: 2, right: 2, bottom: 6, left: -2 });
+ }, constructorString + ' constructor with negative width');
+ test(function() {
+ checkDOMRect(new constructor(2, 2, 4, -4),
+ { x: 2, y: 2, width: 4, height: -4, top: -2, right: 6, bottom: 2, left: 2 });
+ }, constructorString + ' constructor with negative height');
+ test(function() {
+ checkDOMRect(new constructor(2, 2, -4, -4),
+ { x: 2, y: 2, width: -4, height: -4, top: -2, right: 2, bottom: 2, left: -2 });
+ }, constructorString + ' constructor with negative width and height');
+ test(function() {
+ checkDOMRect(new constructor(0, 0, undefined, 4),
+ { x: 0, y: 0, width: 0, height: 4, top: 0, right: 0, bottom: 4, left: 0 });
+ }, constructorString + ' constructor with undefined');
+ test(function() {
+ checkDOMRect(new constructor(NaN, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, null),
+ { x: NaN, y: -Infinity, width: Infinity, height: 0, top: -Infinity, right: NaN, bottom: -Infinity, left: NaN });
+ }, constructorString + ' constructor with NaN and infinity and null');
+ test(function() {
+ checkDOMRect(new constructor("1", "2", "3", "4"),
+ { x: 1, y: 2, width: 3, height: 4, top: 2, right: 4, bottom: 6, left: 1 });
+ }, constructorString + ' constructor with number string');
+ test(function() {
+ checkDOMRect(new constructor("a", "b", "c", "d"),
+ { x: NaN, y: NaN, width: NaN, height: NaN, top: NaN, right: NaN, bottom: NaN, left: NaN });
+ }, constructorString + ' constructor with character string');
+ }
+
+ function checkDOMRect(r, exp) {
+ assert_equals(r.x, exp.x, "x");
+ assert_equals(r.y, exp.y, "y");
+ assert_equals(r.width, exp.width, "width");
+ assert_equals(r.height, exp.height, "height");
+ assert_equals(r.top, exp.top, "top");
+ assert_equals(r.left, exp.left, "left");
+ assert_equals(r.bottom, exp.bottom, "bottom");
+ assert_equals(r.right, exp.right, "right");
+ }
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/geometry/DOMRect-nan.html b/testing/web-platform/tests/css/geometry/DOMRect-nan.html
new file mode 100644
index 0000000000..4a7cde5d33
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMRect-nan.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>DOMQuad's handling of NaN in getBounds()</title>
+<link rel=help href="https://drafts.fxtf.org/geometry/#dom-domquad-getbounds">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+"use strict";
+
+const testCases = [
+ {
+ name: "x coordinate is NaN",
+ idx: 0,
+ exp: {
+ x: NaN,
+ y: 0,
+ width: 0,
+ height: 0,
+ top: 0,
+ bottom: 0,
+ left: NaN,
+ right: NaN
+ }
+ },
+ {
+ name: "y coordinate is NaN",
+ idx: 1,
+ exp: {
+ x: 0,
+ y: NaN,
+ width: 0,
+ height: 0,
+ top: NaN,
+ bottom: NaN,
+ left: 0,
+ right: 0
+ }
+ },
+ {
+ name: "width is NaN",
+ idx: 2,
+ exp: {
+ x: 0,
+ y: 0,
+ width: NaN,
+ height: 0,
+ top: 0,
+ bottom: 0,
+ left: NaN,
+ right: NaN
+ }
+ },
+ {
+ name: "height is NaN",
+ idx: 3,
+ exp: {
+ x: 0,
+ y: 0,
+ width: 0,
+ height: NaN,
+ top: NaN,
+ bottom: NaN,
+ left: 0,
+ right: 0
+ }
+ },
+];
+
+for (const Rect of [DOMRect, DOMRectReadOnly]) {
+ for (const testCase of testCases) {
+ test(() => {
+ const args = [0, 0, 0, 0];
+ args[testCase.idx] = NaN;
+ const rect = new Rect(...args);
+ assert_object_equals(rect.toJSON(), testCase.exp);
+ }, `${Rect.name}'s ${testCase.name}`);
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/css/geometry/DOMRectList.html b/testing/web-platform/tests/css/geometry/DOMRectList.html
new file mode 100644
index 0000000000..e389c33fa6
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/DOMRectList.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>Geometry interfaces: DOMRectList</title>
+<link rel="help" href="https://drafts.fxtf.org/geometry-1/#DOMRectList">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=x>x</div>
+<script>
+setup(() => {
+ window.domRectList = document.getElementById('x').getClientRects();
+});
+
+test(() => {
+ assert_true('DOMRectList' in window);
+}, 'DOMRectList is exposed');
+
+test(() => {
+ assert_false(domRectList instanceof Array);
+}, 'DOMRectList is not [LegacyArrayClass]');
+
+test(() => {
+ assert_equals(domRectList.length, 1);
+}, 'DOMRectList length');
+
+test(() => {
+ assert_equals(domRectList[-1], undefined, 'domRectList[-1]');
+ assert_class_string(domRectList[0], 'DOMRect', 'domRectList[0]');
+ assert_equals(domRectList[1], undefined, 'domRectList[1]');
+}, 'DOMRectList indexed getter');
+
+test(() => {
+ assert_equals(domRectList.item(-1), null, 'domRectList.item(-1)');
+ assert_class_string(domRectList.item(0), 'DOMRect', 'domRectList.item(0)');
+ assert_equals(domRectList.item(1), null, 'domRectList.item(1)');
+ assert_equals(domRectList.item(0), domRectList[0], 'domRectList.item(0) should equal domRectList[0]');
+}, 'DOMRectList item()');
+</script>
diff --git a/testing/web-platform/tests/css/geometry/META.yml b/testing/web-platform/tests/css/geometry/META.yml
new file mode 100644
index 0000000000..98a2ae9860
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/META.yml
@@ -0,0 +1,4 @@
+spec: https://drafts.fxtf.org/geometry/
+suggested_reviewers:
+ - peterjoel
+ - dirkschulze
diff --git a/testing/web-platform/tests/css/geometry/WebKitCSSMatrix.html b/testing/web-platform/tests/css/geometry/WebKitCSSMatrix.html
new file mode 100644
index 0000000000..7c28a5c7fb
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/WebKitCSSMatrix.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Geometry Interfaces: WebKitCSSMatrix</title>
+<link rel="help" href="https://drafts.fxtf.org/geometry/#DOMMatrix">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(() => {
+ assert_true('WebKitCSSMatrix' in self, 'WebKitCSSMatrix should exist');
+ assert_true('DOMMatrix' in self, 'DOMMatrix should exist');
+ assert_equals(WebKitCSSMatrix, DOMMatrix, 'interface object');
+ assert_equals(WebKitCSSMatrix.prototype, DOMMatrix.prototype, 'prototype');
+}, 'Equivalence test');
+
+['WebKitCSSMatrix', 'DOMMatrix'].forEach(interf => {
+ test(() => {
+ const desc = Object.getOwnPropertyDescriptor(self, interf);
+ assert_equals(desc.value, self[interf], 'value');
+ assert_true(desc.writable, 'writable');
+ assert_true(desc.configurable, 'configurable');
+ assert_false(desc.enumerable, 'enumerable');
+ assert_equals(desc.get, undefined, 'get');
+ assert_equals(desc.set, undefined, 'set');
+ }, `Property descriptor for ${interf}`);
+});
+</script>
diff --git a/testing/web-platform/tests/css/geometry/WebKitCSSMatrix.worker.js b/testing/web-platform/tests/css/geometry/WebKitCSSMatrix.worker.js
new file mode 100644
index 0000000000..71e2ecd395
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/WebKitCSSMatrix.worker.js
@@ -0,0 +1,9 @@
+// https://drafts.fxtf.org/geometry/#DOMMatrix
+
+importScripts('/resources/testharness.js');
+
+test(() => {
+ assert_false('WebKitCSSMatrix' in self);
+}, 'WebKitCSSMatrix in worker');
+
+done();
diff --git a/testing/web-platform/tests/css/geometry/historical.html b/testing/web-platform/tests/css/geometry/historical.html
new file mode 100644
index 0000000000..ddc3c777a0
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/historical.html
@@ -0,0 +1,91 @@
+<!doctype html>
+<title>Historical Geometry APIs</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<link rel=help href="https://drafts.fxtf.org/geometry/#changes">
+<script>
+// Removed members
+[
+ // https://github.com/w3c/fxtf-drafts/commit/99e3212469026b2f2f50926a41912d110a1741b7
+ ['DOMMatrix', 'scaleNonUniformSelf'],
+ // https://github.com/w3c/fxtf-drafts/commit/86da3dc961d442f9d8dc7ab59065a9804e109286
+ ['DOMMatrix', 'multiplyBy'],
+ ['DOMMatrix', 'preMultiplyBy'],
+ ['DOMMatrix', 'translateBy'],
+ ['DOMMatrix', 'scaleBy'],
+ ['DOMMatrix', 'scale3dBy'],
+ ['DOMMatrix', 'scaleNonUniformBy'],
+ ['DOMMatrix', 'rotateBy'],
+ ['DOMMatrix', 'rotateFromVectorBy'],
+ ['DOMMatrix', 'rotateAxisAngleBy'],
+ ['DOMMatrix', 'skewXBy'],
+ ['DOMMatrix', 'skewYBy'],
+ // https://github.com/w3c/fxtf-drafts/commit/555a8c0beb1b7b809ccebd861a0352df31530b56
+ ['DOMQuad', 'bounds'],
+].forEach(([interf, member]) => {
+ test(() => {
+ assert_true(interf in self, `${interf} should exist`);
+ assert_false(member in self[interf].prototype, 'on prototype');
+ const instance = new self[interf]();
+ assert_false(member in instance, 'on instance');
+ }, `${interf} ${member} must be nuked`);
+});
+
+// Removed static methods
+// https://github.com/w3c/fxtf-drafts/commit/3c43462bcc857bb830f8af04532cdf33c5a634aa
+['DOMMatrix', 'DOMMatrixReadOnly'].forEach(interf => {
+ test(() => {
+ assert_true(interf in self, `${interf} should exist`);
+ assert_false('fromString' in self[interf], 'on interface object');
+ }, `${interf} fromString static member must be nuked`);
+});
+
+// Optional arguments
+[
+ // https://github.com/w3c/fxtf-drafts/commit/99e3212469026b2f2f50926a41912d110a1741b7
+ ['DOMMatrixReadOnly', 'scale'],
+ ['DOMMatrix', 'scaleSelf'],
+ // https://github.com/w3c/fxtf-drafts/commit/8493a9c3d94da91ead5db6e05b51319494f5855f
+ ['DOMMatrixReadOnly', 'translate'],
+ ['DOMMatrixReadOnly', 'scale3d'],
+ ['DOMMatrixReadOnly', 'rotateFromVector'],
+ ['DOMMatrixReadOnly', 'rotateAxisAngle'],
+ ['DOMMatrixReadOnly', 'skewX'],
+ ['DOMMatrixReadOnly', 'skewY'],
+ ['DOMMatrix', 'translateSelf'],
+ ['DOMMatrix', 'scale3dSelf'],
+ ['DOMMatrix', 'rotateFromVectorSelf'],
+ ['DOMMatrix', 'rotateAxisAngleSelf'],
+ ['DOMMatrix', 'skewXSelf'],
+ ['DOMMatrix', 'skewYSelf'],
+ // https://github.com/w3c/fxtf-drafts/commit/62b9cb9d5be4982d2a9cbf314e3a59efb8a68dd6
+ ['DOMPointReadOnly', 'matrixTransform'],
+ ['DOMMatrixReadOnly', 'multiply'],
+ ['DOMMatrix', 'multiplySelf'],
+ ['DOMMatrix', 'preMultiplySelf'],
+].forEach(([interf, member]) => {
+ test(() => {
+ assert_equals(self[interf].prototype[member].length, 0, 'on prototype');
+ const instance = new self[interf]();
+ assert_equals(instance[member].length, 0, 'on instance');
+ }, `${interf} ${member} number of required arguments`);
+});
+
+// Renamed interfaces
+[
+ // https://github.com/w3c/fxtf-drafts/commit/9031c94c8536cec7f7007c18d7be037a793e5ed5
+ 'CSSMatrix',
+ // https://github.com/w3c/csswg-drafts/commit/8d01810fe403bc935c24ee5a29101cac9b958c8c
+ 'DOMMatrixImmutable',
+ // https://github.com/w3c/csswg-drafts/commit/6e05c3ee01528daba6dc0776f342beae577cefa9
+ 'ClientRect',
+ 'ClientRectList',
+ // Non-standard
+ 'WebKitPoint',
+ 'MSCSSMatrix',
+].forEach(interf => {
+ test(() => {
+ assert_false(interf in self);
+ }, `${interf} must be nuked`);
+});
+</script>
diff --git a/testing/web-platform/tests/css/geometry/idlharness.any.js b/testing/web-platform/tests/css/geometry/idlharness.any.js
new file mode 100644
index 0000000000..5c9170b8a6
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/idlharness.any.js
@@ -0,0 +1,32 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://drafts.fxtf.org/geometry/#DOMPoint
+// https://drafts.fxtf.org/geometry/#DOMRect
+// https://drafts.fxtf.org/geometry/#DOMQuad
+// https://drafts.fxtf.org/geometry/#DOMMatrix
+
+"use strict";
+
+idl_test(
+ ["geometry"],
+ [],
+ idlArray => {
+ const domRectListList = [];
+ if ("document" in self) {
+ domRectListList.push(document.getElementById('log').getClientRects());
+ }
+ idlArray.add_objects({
+ DOMPointReadOnly: ["new DOMPointReadOnly()"],
+ DOMPoint: ["new DOMPoint()"],
+ DOMRectReadOnly: ["new DOMRectReadOnly()"],
+ DOMRect: ["new DOMRect()"],
+ DOMRectList: domRectListList,
+ DOMQuad: ["new DOMQuad()"],
+ DOMMatrixReadOnly: ["new DOMMatrixReadOnly()", "DOMMatrixReadOnly.fromMatrix({is2D: false})"],
+ DOMMatrix: ["new DOMMatrix()", "DOMMatrix.fromMatrix({is2D: false})"]
+ });
+ idlArray.prevent_multiple_testing("DOMMatrixReadOnly");
+ idlArray.prevent_multiple_testing("DOMMatrix");
+ }
+);
diff --git a/testing/web-platform/tests/css/geometry/spec-examples.html b/testing/web-platform/tests/css/geometry/spec-examples.html
new file mode 100644
index 0000000000..61efa2a89b
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/spec-examples.html
@@ -0,0 +1,92 @@
+<!doctype html>
+<title>Geometry APIs spec examples</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<link rel=help href="https://drafts.fxtf.org/geometry/">
+<script>
+test(() => {
+ var point = new DOMPoint(5, 4);
+ var matrix = new DOMMatrix([2, 0, 0, 2, 10, 10]);
+ var transformedPoint = point.matrixTransform(matrix);
+ // The point variable is set to a new DOMPoint object with x coordinate initialized to 5 and y
+ // coordinate initialized to 4.
+ assert_equals(point.x, 5, 'point.x');
+ assert_equals(point.y, 4, 'point.y');
+ assert_equals(point.z, 0, 'point.z');
+ assert_equals(point.w, 1, 'point.w');
+ // This new DOMPoint is now scaled and the translated by matrix. This resulting transformedPoint
+ // has the x coordinate 20 and y coordinate 18.
+ assert_equals(transformedPoint.x, 20, 'transformedPoint.x');
+ assert_equals(transformedPoint.y, 18, 'transformedPoint.x');
+ assert_equals(transformedPoint.z, 0, 'transformedPoint.z');
+ assert_equals(transformedPoint.w, 1, 'transformedPoint.w');
+}, 'matrixTransform');
+
+test(() => {
+ var point = new DOMPoint(2, 0);
+ var quad1 = new DOMQuad(point, {x: 12, y: 0}, {x: 12, y: 10}, {x: 2, y: 10});
+ // The attribute values of the resulting DOMQuad quad1 above are also equivalent to the attribute
+ // values of the following DOMQuad quad2:
+ var rect = new DOMRect(2, 0, 10, 10);
+ var quad2 = DOMQuad.fromRect(rect);
+ for (var p of ['p1', 'p2', 'p3', 'p4']) {
+ for (var attr of ['x', 'y', 'z', 'w']) {
+ assert_equals(quad2[p][attr], quad1[p][attr], `${p}.${attr}`);
+ }
+ }
+}, 'DOMQuad');
+
+test(() => {
+ var quad = new DOMQuad({x: 40, y: 25}, {x: 180, y: 8}, {x: 210, y: 150}, {x: 10, y: 180});
+ // <circle cx="40" cy="25" r="3" fill="rgb(204, 51, 51)"/>
+ assert_equals(quad.p1.x, 40, 'p1.x');
+ assert_equals(quad.p1.y, 25, 'p1.y');
+ // <circle cx="180" cy="8" r="3" fill="rgb(204, 51, 51)"/>
+ assert_equals(quad.p2.x, 180, 'p2.x');
+ assert_equals(quad.p2.y, 8, 'p2.y');
+ // <circle cx="210" cy="150" r="3" fill="rgb(204, 51, 51)"/>
+ assert_equals(quad.p3.x, 210, 'p3.x');
+ assert_equals(quad.p3.y, 150, 'p3.y');
+ // <circle cx="10" cy="180" r="3" fill="rgb(204, 51, 51)"/>
+ assert_equals(quad.p4.x, 10, 'p4.x');
+ assert_equals(quad.p4.y, 180, 'p4.y');
+ var bounds = quad.getBounds();
+ // <rect x="10" y="8" width="200" height="172" fill="none" stroke="black" stroke-dasharray="3 2"/>
+ assert_equals(bounds.x, 10, 'bounds.x');
+ assert_equals(bounds.y, 8, 'bounds.x');
+ assert_equals(bounds.width, 200, 'bounds.width');
+ assert_equals(bounds.height, 172, 'bounds.height');
+}, 'DOMQuad irregular');
+
+test(() => {
+ // In this example, a matrix is created and several 2D transformation methods are called:
+ var matrix = new DOMMatrix();
+ matrix.scaleSelf(2);
+ matrix.translateSelf(20,20);
+ assert_equals(matrix.toString(), "matrix(2, 0, 0, 2, 40, 40)");
+}, 'DOMMatrix 2D transformation');
+
+test(() => {
+ // In the following example, a matrix is created and several 3D transformation methods are called:
+ var matrix = new DOMMatrix();
+ matrix.scale3dSelf(2);
+ assert_equals(matrix.toString(), "matrix3d(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1)");
+}, 'DOMMatrix 3D transformation');
+
+test(() => {
+ // This example will throw an exception because there are non-finite values in the matrix.
+ var matrix = new DOMMatrix([NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN]);
+ assert_throws_dom("InvalidStateError", () => { var string = matrix + " Batman!"; });
+}, 'DOMMatrix NaN');
+
+test(() => {
+ var matrix = new DOMMatrix();
+ matrix.translateSelf(20, 20);
+ matrix.scaleSelf(2);
+ matrix.translateSelf(-20, -20);
+ // is equivalent to:
+ var matrix2 = new DOMMatrix();
+ matrix2.translateSelf(20, 20).scaleSelf(2).translateSelf(-20, -20);
+ assert_equals(matrix.toString(), matrix2.toString());
+}, 'DOMMatrix mutable');
+</script>
diff --git a/testing/web-platform/tests/css/geometry/structured-serialization.html b/testing/web-platform/tests/css/geometry/structured-serialization.html
new file mode 100644
index 0000000000..5c3e5dd93b
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/structured-serialization.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<title>Geometry Interfaces: Serialize and deserialize</title>
+<link rel="help" href="https://drafts.fxtf.org/geometry/#structured-serialization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function clone(obj) {
+ return new Promise((resolve, reject) => {
+ const channel = new MessageChannel();
+ channel.port2.onmessage = e => resolve(e.data);
+ channel.port1.postMessage(obj);
+ });
+}
+function defineThrowingGetters(object, attrs) {
+ for (let attr of attrs) {
+ Object.defineProperty(object, attr, {
+ get: () => assert_unreached(`getter for ${attr}`)
+ });
+ }
+}
+
+[
+ ["DOMPointReadOnly", "x", "y", "z", "w"],
+ ["DOMPoint", "x", "y", "z", "w"],
+ ["DOMRectReadOnly", "x", "y", "width", "height"],
+ ["DOMRect", "x", "y", "width", "height"],
+ ["DOMQuad", "p1", "p2", "p3", "p4"],
+ ["DOMMatrixReadOnly", "a", "b", "c", "d", "e", "f", "m11", "m12", "m13", "m14", "m21", "m22", "m23", "m24", "m31", "m32", "m33", "m34", "m41", "m42", "m43", "m44", "is2D"],
+ ["DOMMatrix", "a", "b", "c", "d", "e", "f", "m11", "m12", "m13", "m14", "m21", "m22", "m23", "m24", "m31", "m32", "m33", "m34", "m41", "m42", "m43", "m44", "is2D"],
+].forEach(([constr, ...attrs]) => {
+ const prefix = `${constr} clone:`;
+
+ promise_test(t => {
+ const object = new self[constr]();
+ return clone(object).then(other => {
+ assert_not_equals(object, other);
+ assert_class_string(other, constr);
+ for (let attr of attrs) {
+ if (constr === "DOMQuad") {
+ assert_not_equals(other[attr], object[attr], attr);
+ assert_class_string(other[attr], "DOMPoint", attr);
+ assert_equals(other[attr].x, object.p1.x, `${attr}.x`);
+ assert_equals(other[attr].y, object.p1.y, `${attr}.y`);
+ assert_equals(other[attr].z, object.p1.z, `${attr}.z`);
+ assert_equals(other[attr].w, object.p1.w, `${attr}.w`);
+ } else {
+ assert_equals(other[attr], object[attr], attr);
+ }
+ }
+ t.done();
+ });
+ }, `${prefix} basic`);
+
+ promise_test(t => {
+ const object = new self[constr]();
+ object.foo = "bar";
+ return clone(object).then(other => {
+ assert_false("foo" in other, 'foo should not exist in other');
+ t.done();
+ });
+ }, `${prefix} custom property`);
+
+ promise_test(t => {
+ const object = new self[constr]();
+ // The custom throwing getter on object should not be copied to other.
+ defineThrowingGetters(object, attrs);
+ return clone(object).then(other => {
+ for (let attr of attrs) {
+ // This should call the standard getter, and therefore not throw.
+ // If this were to call the throwing getter defined on object, the test would fail.
+ other[attr];
+ }
+ t.done();
+ });
+ }, `${prefix} throwing getters`);
+
+ // More specific tests for each type
+ switch(constr) {
+ case "DOMPointReadOnly":
+ case "DOMPoint":
+ case "DOMRectReadOnly":
+ case "DOMRect":
+ promise_test(t => {
+ const object = new self[constr](1, -0, Infinity, NaN);
+ return clone(object).then(other => {
+ for (let attr of attrs) {
+ assert_equals(other[attr], object[attr], attr);
+ }
+ t.done();
+ });
+ }, `${prefix} non-initial values`);
+ break;
+ case "DOMQuad":
+ promise_test(t => {
+ const object = new self[constr]({x:1, y:2, z:3, w:4},
+ {x:-0, y:-0, z:-0, w:-0},
+ {x:Infinity, y:Infinity, z:Infinity, w:Infinity},
+ {x:NaN, y:NaN, z:NaN, w:NaN});
+ return clone(object).then(other => {
+ for (let attr of attrs) {
+ assert_equals(other[attr].x, object[attr].x, `${attr}.x`);
+ assert_equals(other[attr].y, object[attr].y, `${attr}.y`);
+ assert_equals(other[attr].z, object[attr].z, `${attr}.z`);
+ assert_equals(other[attr].w, object[attr].w, `${attr}.w`);
+ }
+ t.done();
+ });
+ }, `${prefix} non-initial values`);
+ break;
+ case "DOMMatrixReadOnly":
+ case "DOMMatrix":
+ promise_test(t => {
+ const object = new self[constr]([1, -0, Infinity, NaN, 5, 6]);
+ object.m13 = -0;
+ object.m14 = -0;
+ object.m23 = -0;
+ object.m24 = -0;
+ object.m31 = -0;
+ object.m32 = -0;
+ object.m34 = -0;
+ object.m43 = -0;
+ assert_true(object.is2D, 'is2D after setting m13 etc to -0');
+ return clone(object).then(other => {
+ for (let attr of attrs) {
+ if (attr === 'm13' ||
+ attr === 'm14' ||
+ attr === 'm23' ||
+ attr === 'm24' ||
+ attr === 'm31' ||
+ attr === 'm32' ||
+ attr === 'm34' ||
+ attr === 'm43') {
+ assert_equals(other[attr], 0, attr);
+ } else {
+ assert_equals(other[attr], object[attr], attr);
+ }
+ }
+ t.done();
+ });
+ }, `${prefix} non-initial values (2d)`);
+
+ promise_test(t => {
+ const object = new self[constr]([11, -0, Infinity, NaN,
+ 21, 22, 23, 24,
+ 31, 32, 33, 34,
+ 41, 42, 43, 44]);
+ return clone(object).then(other => {
+ for (let attr of attrs) {
+ assert_equals(other[attr], object[attr], attr);
+ }
+ t.done();
+ });
+ }, `${prefix} non-initial values (3d)`);
+ break;
+ default:
+ throw new Error(`Test bug: ${constr} has no test for non-initial values`);
+ }
+});
+
+promise_test((t) => {
+ const object = document.getElementById('log').getClientRects();
+ return promise_rejects_dom(t, "DataCloneError", clone(object));
+}, 'DOMRectList clone');0
+</script>
diff --git a/testing/web-platform/tests/css/geometry/support/dommatrix-test-util.js b/testing/web-platform/tests/css/geometry/support/dommatrix-test-util.js
new file mode 100644
index 0000000000..40c336ea8c
--- /dev/null
+++ b/testing/web-platform/tests/css/geometry/support/dommatrix-test-util.js
@@ -0,0 +1,85 @@
+// This formats dict as a string suitable as test name.
+// format_value() is provided by testharness.js,
+// which also preserves sign for -0.
+function format_dict(dict) {
+ const props = [];
+ for (let prop in dict) {
+ props.push(`${prop}: ${format_value(dict[prop])}`);
+ }
+ return `{${props.join(', ')}}`;
+}
+
+// Create a normal JS object with the expected properties
+// from a dict with only m11..m44 specified (not a..f).
+function matrix3D(dict) {
+ const matrix = {m11: 1, m12: 0, m13: 0, m14: 0,
+ m21: 0, m22: 1, m23: 0, m24: 0,
+ m31: 0, m32: 0, m33: 1, m34: 0,
+ m41: 0, m42: 0, m43: 0, m44: 1}
+ matrix.is2D = false;
+ for (let member in dict) {
+ matrix[member] = dict[member];
+ }
+ matrix.a = matrix.m11;
+ matrix.b = matrix.m12;
+ matrix.c = matrix.m21;
+ matrix.d = matrix.m22;
+ matrix.e = matrix.m41;
+ matrix.f = matrix.m42;
+ return matrix;
+}
+
+function matrix2D(dict) {
+ const matrix = matrix3D(dict);
+ matrix.is2D = true;
+ return matrix;
+}
+
+function checkMatrix(actual, expected, { epsilon = Number.MIN_VALUE } = {}) {
+ for (let member in expected) {
+ if (epsilon && typeof expected[member] === "number") {
+ assert_approx_equals(actual[member], expected[member], epsilon, member);
+ } else {
+ assert_equals(actual[member], expected[member], member);
+ }
+ }
+}
+
+// checkMatrix and checkDOMMatrix should probably be merged...
+function checkDOMMatrix(m, exp, is2D) {
+ if (is2D === undefined) {
+ is2D = exp.is2D;
+ }
+ assert_equals(m.m11, exp.m11, "Expected value for m11 is " + exp.m11);
+ assert_equals(m.m12, exp.m12, "Expected value for m12 is " + exp.m12);
+ assert_equals(m.m13, exp.m13, "Expected value for m13 is " + exp.m13);
+ assert_equals(m.m14, exp.m14, "Expected value for m14 is " + exp.m14);
+ assert_equals(m.m21, exp.m21, "Expected value for m21 is " + exp.m21);
+ assert_equals(m.m22, exp.m22, "Expected value for m22 is " + exp.m22);
+ assert_equals(m.m23, exp.m23, "Expected value for m23 is " + exp.m23);
+ assert_equals(m.m24, exp.m24, "Expected value for m24 is " + exp.m24);
+ assert_equals(m.m31, exp.m31, "Expected value for m31 is " + exp.m31);
+ assert_equals(m.m32, exp.m32, "Expected value for m32 is " + exp.m32);
+ assert_equals(m.m33, exp.m33, "Expected value for m33 is " + exp.m33);
+ assert_equals(m.m34, exp.m34, "Expected value for m34 is " + exp.m34);
+ assert_equals(m.m41, exp.m41, "Expected value for m41 is " + exp.m41);
+ assert_equals(m.m42, exp.m42, "Expected value for m42 is " + exp.m42);
+ assert_equals(m.m43, exp.m43, "Expected value for m43 is " + exp.m43);
+ assert_equals(m.m44, exp.m44, "Expected value for m44 is " + exp.m44);
+ assert_equals(m.is2D, is2D, "Expected value for is2D is " + is2D);
+ assert_equals(m.isIdentity, exp.isIdentity, "Expected value for isIdentity is " + exp.isIdentity);
+}
+
+
+function identity() {
+ return new DOMMatrix(
+ [1, 0, 0, 0,
+ 0, 1, 0 ,0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1]);
+}
+
+function update(matrix, f) {
+ f(matrix);
+ return matrix;
+}