summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-paint-api
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/css/css-paint-api')
-rw-r--r--testing/web-platform/tests/css/css-paint-api/META.yml5
-rw-r--r--testing/web-platform/tests/css/css-paint-api/background-image-alpha-ref.html40
-rw-r--r--testing/web-platform/tests/css/css-paint-api/background-image-alpha.https.html54
-rw-r--r--testing/web-platform/tests/css/css-paint-api/background-image-multiple-ref.html16
-rw-r--r--testing/web-platform/tests/css/css-paint-api/background-image-multiple.https.html34
-rw-r--r--testing/web-platform/tests/css/css-paint-api/background-image-tiled-ref.html32
-rw-r--r--testing/web-platform/tests/css/css-paint-api/background-image-tiled.https.html45
-rw-r--r--testing/web-platform/tests/css/css-paint-api/background-repeat-x-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/background-repeat-x.https.html32
-rw-r--r--testing/web-platform/tests/css/css-paint-api/color-custom-property-animation-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/color-custom-property-animation.https.html64
-rw-r--r--testing/web-platform/tests/css/css-paint-api/column-count-crash.https.html39
-rw-r--r--testing/web-platform/tests/css/css-paint-api/custom-property-animation-on-main-thread.https.html58
-rw-r--r--testing/web-platform/tests/css/css-paint-api/dynamic-import-ref.html10
-rw-r--r--testing/web-platform/tests/css/css-paint-api/dynamic-import.https.html37
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-background-image-001-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-background-image-001.https.html34
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-background-image-002-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-background-image-002.https.html34
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-001-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-001.https.html36
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-002-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-002.https.html35
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-003-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-003.https.html35
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-border-image-001-ref.html22
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-border-image-001.https.html40
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-border-image-002-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-border-image-002.https.html40
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-border-image-003-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-border-image-003.https.html40
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-border-image-004-ref.html22
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-border-image-004.https.html41
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-border-image-005-ref.html18
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-border-image-005.https.html37
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-with-float-size-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/geometry-with-float-size.https.html35
-rw-r--r--testing/web-platform/tests/css/css-paint-api/hidpi/canvas-reset-ref.html26
-rw-r--r--testing/web-platform/tests/css/css-paint-api/hidpi/canvas-reset.https.html44
-rw-r--r--testing/web-platform/tests/css/css-paint-api/hidpi/canvas-transform-ref.html23
-rw-r--r--testing/web-platform/tests/css/css-paint-api/hidpi/canvas-transform.https.html43
-rw-r--r--testing/web-platform/tests/css/css-paint-api/hidpi/device-pixel-ratio-ref.html24
-rw-r--r--testing/web-platform/tests/css/css-paint-api/hidpi/device-pixel-ratio.https.html40
-rw-r--r--testing/web-platform/tests/css/css-paint-api/idlharness.html17
-rw-r--r--testing/web-platform/tests/css/css-paint-api/invalid-image-constructor-error-ref.html10
-rw-r--r--testing/web-platform/tests/css/css-paint-api/invalid-image-constructor-error.https.html41
-rw-r--r--testing/web-platform/tests/css/css-paint-api/invalid-image-paint-error-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/invalid-image-paint-error.https.html37
-rw-r--r--testing/web-platform/tests/css/css-paint-api/invalid-image-pending-script-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/invalid-image-pending-script.https.html33
-rw-r--r--testing/web-platform/tests/css/css-paint-api/no-op-animation-ref.html16
-rw-r--r--testing/web-platform/tests/css/css-paint-api/no-op-animation.https.html50
-rw-r--r--testing/web-platform/tests/css/css-paint-api/non-registered-property-value.https.html36
-rw-r--r--testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-half-opaque-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-half-opaque.https.html65
-rw-r--r--testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-ref.html14
-rw-r--r--testing/web-platform/tests/css/css-paint-api/one-custom-property-animation.https.html68
-rw-r--r--testing/web-platform/tests/css/css-paint-api/overdraw-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/overdraw.https.html31
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint-arguments-ref.html40
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint-arguments.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint-function-arguments-ref.html39
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint-function-arguments-var.https.html56
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint-function-arguments.https.html50
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint-function-this-value.https.html43
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-canvasFilter-ref.html22
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-canvasFilter.tentative.https.html39
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-composite-ref.html50
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-composite.https.html75
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-conicGradient-ref.html18
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-conicGradient.https.html35
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-filter-ref.html61
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-filter.https.html108
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-gradient-ref.html25
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-gradient.https.html42
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-image-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-image.https.html31
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-paths-ref.html33
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-paths.https.html50
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-rects-ref.html19
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-rects.https.html37
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-reset-ref.html22
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-reset.https.html39
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-roundRect-ref.html14
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-roundRect.https.html33
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-shadows-ref.html24
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-shadows.https.html41
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-transform-ref.html23
-rw-r--r--testing/web-platform/tests/css/css-paint-api/paint2d-transform.https.html40
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-001.https.html48
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-002.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-003.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-004.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-005.https.html46
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-006.https.html45
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-007.https.html48
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-008.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-009.https.html47
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-010.https.html47
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-011.https.html45
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-012.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-013.https.html44
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-014.https.html46
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-015.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-016.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-017.https.html47
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-018-ref.html16
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-018.https.html68
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-019.https.html47
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-020.https.html46
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-021.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-022.https.html47
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parse-input-arguments-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/parsing/paint-function-valid.https.html47
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-001.https.html25
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-002.https.html25
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-003.https.html25
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-004.https.html25
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-005.https.html35
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-006.https.html25
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-007.https.html25
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-008.https.html25
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-009.https.html25
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-010.https.html33
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-invalidation-001.https.html48
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-invalidation-002.https.html51
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-stylemap.https.html56
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-001.https.html27
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-002.https.html31
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-003.https.html28
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-004.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-005.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-006.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-007.https.html40
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-008.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-009.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-010.https.html41
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-011.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-012.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-013.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-014.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-015.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-016.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-017.https.html29
-rw-r--r--testing/web-platform/tests/css/css-paint-api/registered-property-value-018.https.html49
-rw-r--r--testing/web-platform/tests/css/css-paint-api/resources/html5.pngbin0 -> 1302 bytes
-rw-r--r--testing/web-platform/tests/css/css-paint-api/resources/imported-module.mjs2
-rw-r--r--testing/web-platform/tests/css/css-paint-api/resources/utils.js58
-rw-r--r--testing/web-platform/tests/css/css-paint-api/roundrect-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-paint-api/roundrect.https.html31
-rw-r--r--testing/web-platform/tests/css/css-paint-api/setTransform-001.https.html38
-rw-r--r--testing/web-platform/tests/css/css-paint-api/setTransform-002.https.html35
-rw-r--r--testing/web-platform/tests/css/css-paint-api/setTransform-003.https.html36
-rw-r--r--testing/web-platform/tests/css/css-paint-api/setTransform-004.https.html36
-rw-r--r--testing/web-platform/tests/css/css-paint-api/setTransform-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-paint-api/style-background-image-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/style-background-image.https.html62
-rw-r--r--testing/web-platform/tests/css/css-paint-api/style-before-pseudo-ref.html33
-rw-r--r--testing/web-platform/tests/css/css-paint-api/style-before-pseudo.https.html64
-rw-r--r--testing/web-platform/tests/css/css-paint-api/style-first-letter-pseudo-ref.html30
-rw-r--r--testing/web-platform/tests/css/css-paint-api/style-first-letter-pseudo.https.html58
-rw-r--r--testing/web-platform/tests/css/css-paint-api/top-level-await-ref.html10
-rw-r--r--testing/web-platform/tests/css/css-paint-api/top-level-await.https.html34
-rw-r--r--testing/web-platform/tests/css/css-paint-api/two-custom-property-animation-ref.html14
-rw-r--r--testing/web-platform/tests/css/css-paint-api/two-custom-property-animation.https.html82
-rw-r--r--testing/web-platform/tests/css/css-paint-api/two-element-custom-property-animation-ref.html14
-rw-r--r--testing/web-platform/tests/css/css-paint-api/two-element-custom-property-animation.https.html92
-rw-r--r--testing/web-platform/tests/css/css-paint-api/two-element-one-custom-property-animation-ref.html14
-rw-r--r--testing/web-platform/tests/css/css-paint-api/two-element-one-custom-property-animation.https.html79
-rw-r--r--testing/web-platform/tests/css/css-paint-api/valid-image-after-load-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/valid-image-after-load.https.html38
-rw-r--r--testing/web-platform/tests/css/css-paint-api/valid-image-before-load-ref.html12
-rw-r--r--testing/web-platform/tests/css/css-paint-api/valid-image-before-load.https.html39
173 files changed, 6025 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-paint-api/META.yml b/testing/web-platform/tests/css/css-paint-api/META.yml
new file mode 100644
index 0000000000..082a0977fa
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/META.yml
@@ -0,0 +1,5 @@
+spec: https://drafts.css-houdini.org/css-paint-api/
+suggested_reviewers:
+ - bfgeek
+ - grorg
+ - shans
diff --git a/testing/web-platform/tests/css/css-paint-api/background-image-alpha-ref.html b/testing/web-platform/tests/css/css-paint-api/background-image-alpha-ref.html
new file mode 100644
index 0000000000..532b1bd7e3
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/background-image-alpha-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+#background {
+ background-color: yellow;
+ display: inline-block;
+}
+
+.container {
+ font-size: 0px;
+}
+</style>
+</head>
+<body>
+
+<div id="background">
+ <div class="container">
+ <canvas id ="opaque" width="100" height="100"></canvas>
+ </div>
+ <div class="container">
+ <canvas id ="nonopaque" width="100" height="100"></canvas>
+ </div>
+</div>
+
+<script>
+function drawCanvas(canvasID, hasAlpha) {
+ var canvas = document.getElementById(canvasID);
+ var context = canvas.getContext("2d", {alpha: hasAlpha});
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ context.fillStyle = 'blue';
+ context.fillRect(20, 20, 60, 60);
+};
+
+drawCanvas('opaque', false);
+drawCanvas('nonopaque', true);
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/background-image-alpha.https.html b/testing/web-platform/tests/css/css-paint-api/background-image-alpha.https.html
new file mode 100644
index 0000000000..c8fdc85257
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/background-image-alpha.https.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="background-image-alpha-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-opaque {
+ background-image: paint(opaque);
+}
+
+#canvas-nonopaque {
+ background-image: paint(nonOpaque);
+}
+
+#background {
+ background-color: yellow;
+ display: inline-block;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="background">
+ <div id="canvas-opaque" class="container"></div>
+ <div id="canvas-nonopaque" class="container"></div>
+</div>
+
+<script id="code" type="text/worklet">
+registerPaint('opaque', class {
+ static get contextOptions() { return {alpha: false}; }
+ paint(ctx, geom) {
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(20, 20, 60, 60);
+ }
+});
+
+registerPaint('nonOpaque', class {
+ static get contextOptions() { return {alpha: true}; }
+ paint(ctx, geom) {
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(20, 20, 60, 60);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/background-image-multiple-ref.html b/testing/web-platform/tests/css/css-paint-api/background-image-multiple-ref.html
new file mode 100644
index 0000000000..536258be74
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/background-image-multiple-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+var colors = ['red', 'green', 'blue'];
+for (var i = 2; i >= 0; i--) {
+ ctx.fillStyle = colors[i];
+ ctx.fillRect(i * 20, i * 20, 40, 40);
+}
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/background-image-multiple.https.html b/testing/web-platform/tests/css/css-paint-api/background-image-multiple.https.html
new file mode 100644
index 0000000000..51c928d2a6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/background-image-multiple.https.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="background-image-multiple-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(n0), paint(n1), paint(n2);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+var colors = ['red', 'green', 'blue'];
+
+for (let i = 0; i < 3; i++) {
+ registerPaint('n' + i, class {
+ paint(ctx, geom) {
+ ctx.fillStyle = colors[i];
+ ctx.fillRect(i * 20, i * 20, 40, 40);
+ }
+ });
+}
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/background-image-tiled-ref.html b/testing/web-platform/tests/css/css-paint-api/background-image-tiled-ref.html
new file mode 100644
index 0000000000..fe12f16382
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/background-image-tiled-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="one" width="100" height="100"></canvas>
+<canvas id ="two" width="100" height="100"></canvas>
+<script>
+function drawCircle(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.beginPath();
+ ctx.rect(0, 0, geom.width, geom.height);
+ ctx.fill();
+}
+
+var ctx1 = document.getElementById('one').getContext('2d');
+drawCircle(ctx1, {width: 50, height: 50});
+ctx1.translate(50, 0);
+drawCircle(ctx1, {width: 50, height: 50});
+ctx1.resetTransform();
+ctx1.translate(0, 50);
+drawCircle(ctx1, {width: 100, height: 50});
+
+var ctx2 = document.getElementById('two').getContext('2d');
+for (var i = 0; i < 5; i++) {
+ drawCircle(ctx2, {width: 50, height: 20});
+ ctx2.translate(0, 20);
+}
+ctx2.resetTransform();
+ctx2.translate(50, 25);
+drawCircle(ctx2, {width: 50, height: 50});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/background-image-tiled.https.html b/testing/web-platform/tests/css/css-paint-api/background-image-tiled.https.html
new file mode 100644
index 0000000000..11647c9228
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/background-image-tiled.https.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="background-image-tiled-ref.html">
+<style>
+ div {
+ display: inline-block;
+ width: 100px;
+ height: 100px;
+ }
+
+ #one {
+ background:
+ paint(ellipse) top left/50% 50% repeat-x,
+ paint(ellipse) bottom left/100% 50% no-repeat;
+ }
+
+ #two {
+ background:
+ paint(ellipse) top left/50% 20% repeat-y,
+ paint(ellipse) center right/50% 50% no-repeat;
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="one"></div>
+<div id="two"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('ellipse', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.beginPath();
+ ctx.rect(0, 0, geom.width, geom.height);
+ ctx.fill();
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/background-repeat-x-ref.html b/testing/web-platform/tests/css/css-paint-api/background-repeat-x-ref.html
new file mode 100644
index 0000000000..3df0c5417d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/background-repeat-x-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="200" height="200"></canvas>
+<script>
+var ctx = document.getElementById('canvas').getContext('2d');
+ctx.fillStyle = 'green';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillRect(100, 0, 50, 50);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/background-repeat-x.https.html b/testing/web-platform/tests/css/css-paint-api/background-repeat-x.https.html
new file mode 100644
index 0000000000..2eccfd2a7d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/background-repeat-x.https.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="background-repeat-x-ref.html">
+<style>
+.container {
+ width: 200px;
+ height: 200px;
+}
+#foo {
+ background: paint(foo) top left/50% 50% repeat-x;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="foo" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 50, 50);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/color-custom-property-animation-ref.html b/testing/web-platform/tests/css/css-paint-api/color-custom-property-animation-ref.html
new file mode 100644
index 0000000000..d66536456e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/color-custom-property-animation-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'rgb(100, 100, 0)';
+context.fillRect(0, 0, 100, 100);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/color-custom-property-animation.https.html b/testing/web-platform/tests/css/css-paint-api/color-custom-property-animation.https.html
new file mode 100644
index 0000000000..729af95ceb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/color-custom-property-animation.https.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="color-custom-property-animation-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+.animate {
+ background-image: paint(geometry);
+ /* Use a long animation that start at 50% progress where the slope of the
+ selected timing function is zero. By setting up the animation in this way,
+ we accommodate lengthy delays in running the test without a potential drift
+ in the animated property value. This is important for avoiding flakes,
+ especially on debug builds. The screenshots are taken as soon as the
+ animation is ready, thus the long animation duration has no bearing on
+ the actual duration of the test. */
+ animation: expand 1000000s cubic-bezier(0,1,1,0) -500000s;
+ will-change: transform;
+}
+@keyframes expand {
+ 0% { --foo: rgb(200, 0, 0); }
+ 100% { --foo: rgb(0, 200, 0); }
+}
+
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--foo']; }
+ paint(ctx, geom, properties) {
+ ctx.fillStyle = properties.get('--foo').toString();
+ ctx.fillRect(0, 0, 100, 100);
+ }
+});
+</script>
+
+<script>
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<color>',
+ initialValue: 'rgb(0, 0, 0)',
+ inherits: false
+});
+</script>
+
+<script>
+var blob = new Blob([document.getElementById('code').textContent],
+ {type: 'text/javascript'});
+CSS.paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+ document.getElementById('canvas-geometry').classList.add('animate');
+ // Wait for the animation to start before completing the test.
+ document.getAnimations()[0].ready.then(() => {
+ takeScreenshot();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/column-count-crash.https.html b/testing/web-platform/tests/css/css-paint-api/column-count-crash.https.html
new file mode 100644
index 0000000000..8e774499b8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/column-count-crash.https.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html class="test-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<style>
+#output {
+ width: 100px;
+ height: 100px;
+}
+body {
+ -webkit-mask-box-image-source: url(resources/dot.png);
+ column-count: 3;
+}
+.test-wait {
+ column-count: 600;
+}
+</style>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('green', class {
+ paint(ctx, geom) {}
+});
+</script>
+
+<script>
+// Regression test for crbug.com/1095163, the test passes as long as it doesn't
+// crash.
+var el = document.getElementById('output');
+el.style.backgroundImage = 'paint(green)';
+
+var blob = new Blob([document.getElementById('code').textContent],
+ {type: 'text/javascript'});
+CSS.paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+ document.documentElement.classList.remove("test-wait");
+});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/custom-property-animation-on-main-thread.https.html b/testing/web-platform/tests/css/css-paint-api/custom-property-animation-on-main-thread.https.html
new file mode 100644
index 0000000000..13ccf3fc27
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/custom-property-animation-on-main-thread.https.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="one-custom-property-animation-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+ animation: expand 5s;
+}
+@keyframes expand {
+ 0% { --foo: 0; }
+ 0.01% { --foo: 50; }
+ 99% { --foo: 50; }
+ 100% { --foo: 100; }
+}
+
+#canvas-geometry {
+ background-color: blue;
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--foo']; }
+ paint(ctx, geom, properties) {
+ let fooValue = parseFloat(properties.get('--foo').toString());
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, fooValue, fooValue);
+ }
+});
+</script>
+
+<script>
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<number>',
+ initialValue: '0',
+ inherits: false
+});
+</script>
+
+<script>
+// The test is designed to make sure that when the custom property animation is
+// running on the compositor thread, we are getting the right value.
+// The "importWorkletAndTerminateTestAfterAsyncPaint" has the logic to rAF
+// two frames before taking a screenshot. So the animation is designed to
+// be stable after two frames. That is, the 0.01% of 5s is much less than
+// two frames, and thus after two frames, the value of --foo should be stable.
+importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/dynamic-import-ref.html b/testing/web-platform/tests/css/css-paint-api/dynamic-import-ref.html
new file mode 100644
index 0000000000..6c598aee39
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/dynamic-import-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<canvas id ="output" width="100" height="100" style="background: blue;"></canvas>
+<script>
+"use strict";
+const canvas = document.getElementById('output');
+const ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'green';
+ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/css/css-paint-api/dynamic-import.https.html b/testing/web-platform/tests/css/css-paint-api/dynamic-import.https.html
new file mode 100644
index 0000000000..62957fcd4b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/dynamic-import.https.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://html.spec.whatwg.org/#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability)">
+<link rel="match" href="dynamic-import-ref.html">
+<style>
+#output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(rects);
+ background-color: blue;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('rects', class {
+ async paint(ctx, geom) {
+ ctx.fillStyle = 'red';
+ try {
+ await import('./resources/imported-module.mjs');
+ } catch (e) {
+ if (e.constructor === TypeError) {
+ ctx.fillStyle = 'green';
+ }
+ }
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+"use strict";
+importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-background-image-001-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-001-ref.html
new file mode 100644
index 0000000000..3e7db50548
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-001-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 100);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-background-image-001.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-001.https.html
new file mode 100644
index 0000000000..50d75a5470
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-001.https.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-background-image-001-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-background-image-002-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-002-ref.html
new file mode 100644
index 0000000000..b03fcd02ec
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-002-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="200" height="200"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 200, 200);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-background-image-002.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-002.https.html
new file mode 100644
index 0000000000..06be523c32
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-002.https.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-background-image-002-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 200px;
+ height: 200px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-001-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-001-ref.html
new file mode 100644
index 0000000000..ce7988ffd0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-001-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="100" height="50"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 50);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-001.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-001.https.html
new file mode 100644
index 0000000000..dbb4c385ee
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-001.https.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-background-image-tiled-001-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 100px;
+ height: 100px;
+ background: paint(geometry) top left/50% 50% repeat-x;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.rect(0, 0, geom.width, geom.height);
+ ctx.fill();
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-002-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-002-ref.html
new file mode 100644
index 0000000000..3b3b2bc30e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-002-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="50" height="20" style="position:relative; top:40px; left:50px"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 50, 20);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-002.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-002.https.html
new file mode 100644
index 0000000000..6f865175ce
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-002.https.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-background-image-tiled-002-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 100px;
+ height: 100px;
+ background: paint(geometry) center right/50% 20% no-repeat;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-003-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-003-ref.html
new file mode 100644
index 0000000000..a21a990f98
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-003-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="60" height="80" style="position:relative; top:10px; left:20px"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 60, 80);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-003.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-003.https.html
new file mode 100644
index 0000000000..a3792caafb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-background-image-tiled-003.https.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-background-image-tiled-003-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 100px;
+ height: 100px;
+ background: paint(geometry) center center/60px 80px no-repeat;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-border-image-001-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-001-ref.html
new file mode 100644
index 0000000000..d305050294
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-001-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="200" height="200" style="position:relative; top:10px; left:10px"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+// The test geometry-border-image1.html has a paint canvas with width=200 and
+// height=200, as well as a border-width=10 and border-image-slice: fill. All of
+// them combined meaning that it draws to the (200+10*2)*(200+10*2) area, but
+// stretch it to fit into the 200*200 area.
+// So in this reftest, we create a 200*200 canvas. We draw to a 220*220 area
+// and scale it to fit the 200*200 canvas.
+context.scale(200/220, 200/220);
+context.fillStyle = 'green';
+context.fillRect(0, 0, 220, 220);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-border-image-001.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-001.https.html
new file mode 100644
index 0000000000..76813eab30
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-001.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-border-image-001-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 200px;
+ height: 200px;
+}
+
+#canvas-geometry {
+ border: solid 0;
+ border-image: paint(geometry);
+ border-image-slice: 0 fill;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (geom.width == 220 && geom.height == 220)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ document.getElementById('canvas-geometry').style.borderWidth = '10px';
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-border-image-002-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-002-ref.html
new file mode 100644
index 0000000000..050c6a9c35
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-002-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="90" height="90" style="position:relative; left:-20px; top:-20px"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 90, 90);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-border-image-002.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-002.https.html
new file mode 100644
index 0000000000..4c686b9c11
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-002.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-border-image-002-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 50px;
+ height: 50px;
+}
+
+#canvas-geometry {
+ border: solid 0;
+ border-image: paint(geometry);
+ border-image-slice: 0 fill;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (geom.width == 90 && geom.height == 90)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ document.getElementById('canvas-geometry').style.borderImageOutset = '20px';
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-border-image-003-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-003-ref.html
new file mode 100644
index 0000000000..ef14f7728b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-003-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="80" height="120" style="position:relative; left:-10px; top:-10px"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 80, 120);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-border-image-003.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-003.https.html
new file mode 100644
index 0000000000..ce343df291
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-003.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-border-image-003-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 60px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ border: solid 0;
+ border-image: paint(geometry);
+ border-image-slice: 0 fill;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (geom.width == 80 && geom.height == 120)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ document.getElementById('canvas-geometry').style.borderImageOutset = '10px';
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-border-image-004-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-004-ref.html
new file mode 100644
index 0000000000..764b6e57c5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-004-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="120" height="120"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+// The test geometry-border-image4.html has a 100*100 paint canvas, it specifies
+// border-width=10 and border-image-outset=10, which means that it is drawing to
+// a 140*140 area. However, because the test has "border-image-slice: 0 fill",
+// together with the border-width=10, makes it draw to a 120*120 area.
+// In this ref html, we draw to a 140*140 area, but scale it to fit the 120*120
+// canvas.
+context.scale(120/140, 120/140);
+context.fillStyle = 'green';
+context.fillRect(0, 0, 140, 140);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-border-image-004.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-004.https.html
new file mode 100644
index 0000000000..8dd80c7171
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-004.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-border-image-004-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ border: solid 0;
+ border-image: paint(geometry);
+ border-image-slice: 0 fill;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (geom.width == 140 && geom.height == 140)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ document.getElementById('canvas-geometry').style.borderWidth = '10px';
+ document.getElementById('canvas-geometry').style.borderImageOutset = '10px';
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-border-image-005-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-005-ref.html
new file mode 100644
index 0000000000..16d2304113
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-005-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="308" height="308"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = "green";
+context.fillRect(0, 0, 290, 18);
+context.fillRect(0, 0, 18, 290);
+context.fillRect(0, 254, 290, 36);
+context.fillRect(254, 0, 36, 290);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-border-image-005.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-005.https.html
new file mode 100644
index 0000000000..efdd7fdf1b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-border-image-005.https.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-border-image-005-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 200px;
+ height: 200px;
+ border: 36px solid orange;
+ border-image: paint(foo) /* source */
+ 1 / /* slice */
+ 36px 36px 36px 36px / /* width */
+ 18px 18px 18px 18px /* outset */
+ round;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="target" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+ paint(ctx, geom) {
+ // Both geom.width and height are 200 + 36 *3 = 308px;
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-with-float-size-ref.html b/testing/web-platform/tests/css/css-paint-api/geometry-with-float-size-ref.html
new file mode 100644
index 0000000000..c24a9d7bc0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-with-float-size-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100.5" height="200.5px"></canvas>
+</body>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext('2d');
+context.fillStyle = 'green';
+context.fillRect(0, 0, 50, 50);
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/geometry-with-float-size.https.html b/testing/web-platform/tests/css/css-paint-api/geometry-with-float-size.https.html
new file mode 100644
index 0000000000..8cd90c8431
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/geometry-with-float-size.https.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-with-float-size-ref.html">
+<style>
+.container {
+ width: 100.5px;
+ height: 200.5px;
+}
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (geom.width == 101 && geom.height == 201)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, 50, 50);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-reset-ref.html b/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-reset-ref.html
new file mode 100644
index 0000000000..24cab5da54
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-reset-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var ctx = canvas.getContext("2d");
+
+// Adjust the canvas to get highdpi rendering.
+canvas.style.width = '270px';
+canvas.style.height = '275px';
+canvas.width = 270 * devicePixelRatio;
+canvas.height = 275 * devicePixelRatio;
+ctx.scale(devicePixelRatio, devicePixelRatio);
+
+var fillW = 250;
+var fillH = 50;
+ctx.beginPath();
+ctx.rect(0, 0, fillW, fillH);
+ctx.closePath();
+ctx.clip();
+ctx.fillStyle = 'green';
+ctx.fillRect(0, 0, fillW, fillH);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-reset.https.html b/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-reset.https.html
new file mode 100644
index 0000000000..d8073d6452
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-reset.https.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="canvas-reset-ref.html">
+<style>
+.container {
+ width: 270px;
+ height: 275px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ // Set some transform then reset the canvas.
+ ctx.translate(20, 30);
+ ctx.scale(1.5, 2.5);
+ ctx.reset();
+
+ var fillW = 250;
+ var fillH = 50;
+ ctx.beginPath();
+ ctx.rect(0, 0, fillW, fillH);
+ ctx.closePath();
+ ctx.clip();
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, fillW, fillH);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-transform-ref.html b/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-transform-ref.html
new file mode 100644
index 0000000000..d3e4e0913f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-transform-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="540" height="550"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+// In the test page, the paint worklet canvas has a size of width of 270 CSS
+// pixels, and height of 275. To divided by 2 is to match the canvas size.
+canvas.style.width = (canvas.width / 2) + 'px';
+canvas.style.height = (canvas.height / 2) + 'px';
+var ctx = canvas.getContext("2d");
+var fillW = 250;
+var fillH = 50;
+ctx.setTransform(2 * devicePixelRatio, 0, 0, 2 * devicePixelRatio, 0, 200);
+ctx.beginPath();
+ctx.rect(0, 0, fillW, fillH);
+ctx.closePath();
+ctx.clip();
+ctx.fillStyle = 'green';
+ctx.fillRect(0, 0, fillW, fillH);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-transform.https.html b/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-transform.https.html
new file mode 100644
index 0000000000..6dc57abaf7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/hidpi/canvas-transform.https.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="canvas-transform-ref.html">
+<style>
+.container {
+ width: 270px;
+ height: 275px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+// Regression test for crbug.com/970783. The canvas transform matrix should
+// account for the devicePixelRatio, such that the clip bounds can be
+// properly computed when applying clips.
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ var fillW = 250;
+ var fillH = 50;
+ ctx.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 100);
+ ctx.beginPath();
+ ctx.rect(0, 0, fillW, fillH);
+ ctx.closePath();
+ ctx.clip();
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, fillW, fillH);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/hidpi/device-pixel-ratio-ref.html b/testing/web-platform/tests/css/css-paint-api/hidpi/device-pixel-ratio-ref.html
new file mode 100644
index 0000000000..205cf8963b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/hidpi/device-pixel-ratio-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+canvas {width: 150px; height: 150px; }
+</style>
+<body>
+<p>This test ensures that the PaintWorkletGlobalScope.devicePixelRatio returns
+the correct value, which should be identical as window.devicePixelRatio. To
+manually test, open both this file and "device-pixel-ratio-ref.html" with a
+browser, and you should see two idential green rectangles.</p>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+canvas.width = 150 * window.devicePixelRatio;
+canvas.height = 150 * window.devicePixelRatio;
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+var draw_width = Math.floor(canvas.width / window.devicePixelRatio);
+var draw_height = Math.floor(canvas.height / window.devicePixelRatio);
+context.fillRect(0, 0, draw_width, draw_height);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/hidpi/device-pixel-ratio.https.html b/testing/web-platform/tests/css/css-paint-api/hidpi/device-pixel-ratio.https.html
new file mode 100644
index 0000000000..f9516e5ccf
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/hidpi/device-pixel-ratio.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="device-pixel-ratio-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 150px;
+ height: 150px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<p>This test ensures that the PaintWorkletGlobalScope.devicePixelRatio returns
+the correct value, which should be identical as window.devicePixelRatio. To
+manually test, open both this file and "device-pixel-ratio-ref.html" with a
+browser, and you should see two idential green rectangles.</p>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ var draw_width = Math.floor(geom.width / devicePixelRatio);
+ var draw_height = Math.floor(geom.height / devicePixelRatio);
+ ctx.fillRect(0, 0, draw_width, draw_height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/idlharness.html b/testing/web-platform/tests/css/css-paint-api/idlharness.html
new file mode 100644
index 0000000000..3c4aa98d61
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/idlharness.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS Painting API IDL tests</title>
+<meta name="timeout" content="long">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script>
+ "use strict";
+
+ idl_test(
+ ["css-paint-api"],
+ ["cssom", "html"]
+ // No objects in Window global
+ );
+</script>
diff --git a/testing/web-platform/tests/css/css-paint-api/invalid-image-constructor-error-ref.html b/testing/web-platform/tests/css/css-paint-api/invalid-image-constructor-error-ref.html
new file mode 100644
index 0000000000..5e4c5662af
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/invalid-image-constructor-error-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<canvas id="canvas" width="100" height="100"></canvas>
+<script>
+ var canvas = document.getElementById("canvas");
+ var ctx = canvas.getContext('2d');
+ ctx.fillStyle = 'green';
+ ctx.fillRect(50, 50, 50, 50);
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/invalid-image-constructor-error.https.html b/testing/web-platform/tests/css/css-paint-api/invalid-image-constructor-error.https.html
new file mode 100644
index 0000000000..8facde43f5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/invalid-image-constructor-error.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="invalid-image-constructor-error-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(errorIndicator), paint(successIndicator);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('errorIndicator', class {
+ constructor() { throw Error('failed!'); }
+ // The paint function should not be executed because an error has been
+ // thrown.
+ paint(ctx, geom) {
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, 50, 50);
+ }
+});
+
+registerPaint('successIndicator', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(50, 50, 50, 50);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/invalid-image-paint-error-ref.html b/testing/web-platform/tests/css/css-paint-api/invalid-image-paint-error-ref.html
new file mode 100644
index 0000000000..67f5751283
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/invalid-image-paint-error-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 100);
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-paint-api/invalid-image-paint-error.https.html b/testing/web-platform/tests/css/css-paint-api/invalid-image-paint-error.https.html
new file mode 100644
index 0000000000..17c283e35c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/invalid-image-paint-error.https.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="invalid-image-paint-error-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(errorIndicator), paint(successIndicator);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('errorIndicator', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ throw Error('failed!');
+ }
+});
+registerPaint('successIndicator', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/invalid-image-pending-script-ref.html b/testing/web-platform/tests/css/css-paint-api/invalid-image-pending-script-ref.html
new file mode 100644
index 0000000000..67f5751283
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/invalid-image-pending-script-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 100);
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-paint-api/invalid-image-pending-script.https.html b/testing/web-platform/tests/css/css-paint-api/invalid-image-pending-script.https.html
new file mode 100644
index 0000000000..20a61eff41
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/invalid-image-pending-script.https.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="invalid-image-pending-script-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(invalid), paint(successIndicator);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+// This is testing that even though there is no paint function registered for
+// 'invalid', it won't cause any error, and the other painter (successIndicator)
+// will paint as usual.
+registerPaint('successIndicator', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/no-op-animation-ref.html b/testing/web-platform/tests/css/css-paint-api/no-op-animation-ref.html
new file mode 100644
index 0000000000..19c8e56def
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/no-op-animation-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<body "lightyellow" contenteditable="true"="0">
+<div>=</div>
+
+<script>
+function edit() {
+ document.execCommand("selectAll");
+ document.execCommand("InsertHTML",false,"<pre></pre>");
+ document.execCommand("InsertHTML",false,"<div>i</div>");
+ document.execCommand("indent");
+ document.execCommand("selectAll");
+}
+edit();
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/no-op-animation.https.html b/testing/web-platform/tests/css/css-paint-api/no-op-animation.https.html
new file mode 100644
index 0000000000..5898555844
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/no-op-animation.https.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="no-op-animation-ref.html">
+<style>
+#container {
+}
+.animate {
+ background-image: paint(foo);
+ animation: anim 1s;
+}
+@keyframes anim {
+ 0% { --foo: rgb(200, 0, 0); }
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<body "lightyellow" contenteditable="true"="0">
+<div id="container">=</div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+ static get inputProperties() { return ['--foo']; }
+ paint() {}
+});
+</script>
+
+<script>
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<color>',
+ initialValue: 'rgb(0, 0, 0)',
+ inherits: false
+});
+var code = document.getElementById('code').textContent;
+var blob = new Blob([code], {type: 'text/javascript'});
+CSS.paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+ document.getElementById('container').classList.add('animate');
+ edit();
+});
+function edit() {
+ document.execCommand("selectAll");
+ document.execCommand("InsertHTML",false,"<pre></pre>");
+ document.execCommand("InsertHTML",false,"<div>i</div>");
+ document.execCommand("indent");
+ document.execCommand("selectAll");
+ takeScreenshot();
+}
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/non-registered-property-value.https.html b/testing/web-platform/tests/css/css-paint-api/non-registered-property-value.https.html
new file mode 100644
index 0000000000..774cb4eb2d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/non-registered-property-value.https.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ --foo:100;
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--foo']; }
+ paint(ctx, geom, properties) {
+ let fooValue = parseFloat(properties.get('--foo').toString());
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, fooValue, fooValue);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-half-opaque-ref.html b/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-half-opaque-ref.html
new file mode 100644
index 0000000000..34cbff442d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-half-opaque-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="500" height="500"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'rgba(75, 125, 0, 0.8)';
+context.fillRect(0, 0, 500, 500);
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-half-opaque.https.html b/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-half-opaque.https.html
new file mode 100644
index 0000000000..57c70872c7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-half-opaque.https.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="one-custom-property-animation-half-opaque-ref.html">
+<style>
+.container {
+ width: 500px;
+ height: 500px;
+}
+@keyframes expand {
+ 0% { --foo: rgba(0, 200, 0, 1); }
+ 100% { --foo: rgba(200, 0, 0, 0.6); }
+}
+.animate {
+ background-image: paint(geometry);
+ /* Use a long animation that start at 50% progress where the slope of the
+ selected timing function is zero. By setting up the animation in this way,
+ we accommodate lengthy delays in running the test without a potential drift
+ in the animated property value. This is important for avoiding flakes,
+ especially on debug builds. The screenshots are taken as soon as the
+ animation is ready, thus the long animation duration has no bearing on
+ the actual duration of the test. */
+ animation: expand 1000000s cubic-bezier(0,1,1,0) -500000s;
+ will-change: transform;
+}
+</style>
+
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--foo']; }
+ paint(ctx, geom, properties) {
+ ctx.fillStyle = properties.get('--foo').toString();
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<color>',
+ initialValue: 'rgb(0, 0, 0)',
+ inherits: false
+});
+</script>
+
+<script>
+var blob = new Blob([document.getElementById('code').textContent],
+ {type: 'text/javascript'});
+CSS.paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+ document.getElementById('canvas-geometry').classList.add('animate');
+ const animations = document.getAnimations();
+ // Wait for the animation to start before completing the test.
+ document.getAnimations()[0].ready.then(() => {
+ takeScreenshot();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-ref.html b/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-ref.html
new file mode 100644
index 0000000000..c221aa0e89
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'blue';
+context.fillRect(0, 0, 100, 100);
+context.fillStyle = 'green';
+context.fillRect(0, 0, 50, 50);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation.https.html b/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation.https.html
new file mode 100644
index 0000000000..25b1cef188
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/one-custom-property-animation.https.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="one-custom-property-animation-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+@keyframes expand {
+ 0% { --foo: 0; }
+ 100% { --foo: 100; }
+}
+.animate {
+ background-image: paint(geometry);
+ /* Use a long animation that start at 50% progress where the slope of the
+ selected timing function is zero. By setting up the animation in this way,
+ we accommodate lengthy delays in running the test without a potential drift
+ in the animated property value. This is important for avoiding flakes,
+ especially on debug builds. The screenshots are taken as soon as the
+ animation is ready, thus the long animation duration has no bearing on
+ the actual duration of the test. */
+ animation: expand 1000000s cubic-bezier(0,1,1,0) -500000s;
+}
+
+#canvas-geometry {
+ background-color: blue;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--foo']; }
+ paint(ctx, geom, properties) {
+ let fooValue = parseFloat(properties.get('--foo').toString());
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, fooValue, fooValue);
+ }
+});
+</script>
+
+<script>
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<number>',
+ initialValue: '0',
+ inherits: false
+});
+</script>
+
+<script>
+var blob = new Blob([document.getElementById('code').textContent],
+ {type: 'text/javascript'});
+CSS.paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+ document.getElementById('canvas-geometry').classList.add('animate');
+ const animations = document.getAnimations();
+ // Wait for the animation to start before completing the test.
+ document.getAnimations()[0].ready.then(() => {
+ takeScreenshot();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/overdraw-ref.html b/testing/web-platform/tests/css/css-paint-api/overdraw-ref.html
new file mode 100644
index 0000000000..67f5751283
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/overdraw-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 100);
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-paint-api/overdraw.https.html b/testing/web-platform/tests/css/css-paint-api/overdraw.https.html
new file mode 100644
index 0000000000..8d3dc72f93
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/overdraw.https.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="overdraw-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(green);
+ background-color: red;
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('green', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(-10, -10, geom.width + 20, geom.height + 20);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint-arguments-ref.html b/testing/web-platform/tests/css/css-paint-api/paint-arguments-ref.html
new file mode 100644
index 0000000000..3675fc10e7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint-arguments-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+#background {
+ background-color: yellow;
+ display: inline-block;
+}
+
+.container {
+ font-size: 0px;
+}
+</style>
+</head>
+<body>
+
+<div id="background">
+ <div class="container">
+ <canvas id ="box-green" width="100" height="100"></canvas>
+ </div>
+ <div class="container">
+ <canvas id ="box-red" width="100" height="100"></canvas>
+ </div>
+</div>
+
+<script>
+function drawCanvas(canvasID, color) {
+ var canvas = document.getElementById(canvasID);
+ var context = canvas.getContext("2d", {alpha: true});
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ context.fillStyle = color;
+ context.fillRect(20, 20, 60, 60);
+};
+
+drawCanvas('box-green', 'green');
+drawCanvas('box-red', 'red');
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint-arguments.https.html b/testing/web-platform/tests/css/css-paint-api/paint-arguments.https.html
new file mode 100644
index 0000000000..c08069c2e3
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint-arguments.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-box-green {
+ background-image: paint(box, green);
+}
+
+#canvas-box-red {
+ background-image: paint(box, red);
+}
+
+#background {
+ background-color: yellow;
+ display: inline-block;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+
+<div id="background">
+ <div id="canvas-box-green" class="container"></div>
+ <div id="canvas-box-red" class="container"></div>
+</div>
+
+<script id="code" type="text/worklet">
+registerPaint('box', class {
+ static get contextOptions() { return {alpha: true}; }
+ static get inputArguments() { return ['<color>']; }
+ paint(ctx, geom, properties, args) {
+ ctx.fillStyle = args[0].toString();
+ ctx.fillRect(20, 20, 60, 60);
+ }
+});
+
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint-function-arguments-ref.html b/testing/web-platform/tests/css/css-paint-api/paint-function-arguments-ref.html
new file mode 100644
index 0000000000..764c8f3c78
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint-function-arguments-ref.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+#background {
+ background-color: yellow;
+ display: inline-block;
+}
+
+.container {
+ font-size: 0px;
+}
+</style>
+</head>
+<body>
+
+<div id="background">
+ <div class="container">
+ <canvas id ="box-1" width="200" height="200"></canvas>
+ </div>
+ <div class="container">
+ <canvas id ="box-2" width="200" height="200"></canvas>
+ </div>
+</div>
+
+<script>
+function drawCanvas(canvasID, color, width) {
+ var canvas = document.getElementById(canvasID);
+ var context = canvas.getContext("2d", {alpha: true});
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ context.fillStyle = color;
+ context.fillRect(40, 40, width, width);
+};
+
+drawCanvas('box-1', 'rgb(50, 100, 150)', '50');
+drawCanvas('box-2', 'rgb(150, 100, 50)', '100');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint-function-arguments-var.https.html b/testing/web-platform/tests/css/css-paint-api/paint-function-arguments-var.https.html
new file mode 100644
index 0000000000..e06231cb1d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint-function-arguments-var.https.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint-function-arguments-ref.html">
+<style>
+:root {
+ --color1:rgb(50, 100, 150);
+ --color2:rgb(150, 100, 50);
+ --length1:50px;
+}
+
+.container {
+ width: 200px;
+ height: 200px;
+}
+
+#canvas-box-1 {
+ background-image: paint(box, var(--color1), var(--length1));
+}
+
+#canvas-box-2 {
+ background-image: paint(box, var(--color2), 100px);
+}
+
+#background {
+ background-color: yellow;
+ display: inline-block;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+
+<div id="background">
+ <div id="canvas-box-1" class="container"></div>
+ <div id="canvas-box-2" class="container"></div>
+</div>
+
+<script id="code" type="text/worklet">
+registerPaint('box', class {
+ static get contextOptions() { return {alpha: true}; }
+ static get inputArguments() { return ['<color>', '<length>']; }
+ paint(ctx, geom, properties, args) {
+ ctx.fillStyle = args[0].toString();
+ let size = parseInt(args[1].toString());
+ ctx.fillRect(40, 40, size, size);
+ }
+});
+
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint-function-arguments.https.html b/testing/web-platform/tests/css/css-paint-api/paint-function-arguments.https.html
new file mode 100644
index 0000000000..c613bd159f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint-function-arguments.https.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint-function-arguments-ref.html">
+<style>
+.container {
+ width: 200px;
+ height: 200px;
+}
+
+#canvas-box-1 {
+ background-image: paint(box, rgb(50, 100, 150), 50px);
+}
+
+#canvas-box-2 {
+ background-image: paint(box, rgb(150, 100, 50), 100px);
+}
+
+#background {
+ background-color: yellow;
+ display: inline-block;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+
+<div id="background">
+ <div id="canvas-box-1" class="container"></div>
+ <div id="canvas-box-2" class="container"></div>
+</div>
+
+<script id="code" type="text/worklet">
+registerPaint('box', class {
+ static get contextOptions() { return {alpha: true}; }
+ static get inputArguments() { return ['<color>', '<length>']; }
+ paint(ctx, geom, properties, args) {
+ ctx.fillStyle = args[0].toString();
+ let size = parseInt(args[1].toString());
+ ctx.fillRect(40, 40, size, size);
+ }
+});
+
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint-function-this-value.https.html b/testing/web-platform/tests/css/css-paint-api/paint-function-this-value.https.html
new file mode 100644
index 0000000000..216913899a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint-function-this-value.https.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Paint callback is invoked with `this` value of `paintInstance`</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api-1/#invoke-a-paint-callback">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+let paintInstance;
+
+registerPaint('geometry', class {
+ constructor() {
+ paintInstance = this;
+ }
+ paint(ctx, geom) {
+ if (this === paintInstance)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-canvasFilter-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-canvasFilter-ref.html
new file mode 100644
index 0000000000..e8231c254c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-canvasFilter-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="output" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.filter = new CanvasFilter([
+ {filter: "gaussianBlur", stdDeviation: 10},
+ {filter: "colorMatrix", type: "hueRotate", values: 90}
+]);
+
+ctx.fillStyle = "cyan";
+ctx.fillRect(40, 0, 70, 70);
+ctx.fillStyle = "magenta";
+ctx.fillRect(40, 40, 70, 70);
+ctx.fillStyle = "yellow";
+ctx.fillRect(0, 40, 70, 70);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-canvasFilter.tentative.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-canvasFilter.tentative.https.html
new file mode 100644
index 0000000000..a4d50712be
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-canvasFilter.tentative.https.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-canvasFilter-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(rects);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('rects', class {
+ paint(ctx, geom) {
+ ctx.filter = new CanvasFilter([
+ {filter: "gaussianBlur", stdDeviation: 10},
+ {filter: "colorMatrix", type: "hueRotate", values: 90}
+ ]);
+
+ ctx.fillStyle = "cyan";
+ ctx.fillRect(40, 0, 70, 70);
+ ctx.fillStyle = "magenta";
+ ctx.fillRect(40, 40, 70, 70);
+ ctx.fillStyle = "yellow";
+ ctx.fillRect(0, 40, 70, 70);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-composite-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-composite-ref.html
new file mode 100644
index 0000000000..3b75d52698
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-composite-ref.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+ canvas { display: inline-block; }
+</style>
+</head>
+<body>
+<canvas id="source-over" width="80" height="80"></canvas>
+<canvas id="source-in" width="80" height="80"></canvas>
+<canvas id="source-out" width="80" height="80"></canvas>
+<canvas id="source-atop" width="80" height="80"></canvas>
+<br>
+<canvas id="destination-over" width="80" height="80"></canvas>
+<canvas id="destination-in" width="80" height="80"></canvas>
+<canvas id="destination-out" width="80" height="80"></canvas>
+<canvas id="destination-atop" width="80" height="80"></canvas>
+<br>
+<canvas id="lighter" width="80" height="80"></canvas>
+<canvas id="xor" width="80" height="80"></canvas>
+<script>
+var compositeOps = [
+ 'source-over',
+ 'source-in',
+ 'source-out',
+ 'source-atop',
+ 'destination-over',
+ 'destination-in',
+ 'destination-out',
+ 'destination-atop',
+ 'lighter',
+ 'xor'
+];
+
+for (var i = 0; i < compositeOps.length; i++) {
+ var op = compositeOps[i];
+ var ctx = document.getElementById(op).getContext('2d');
+ ctx.fillStyle = 'red';
+ ctx.fillRect(5, 5, 40, 40);
+
+ ctx.globalCompositeOperation = op;
+
+ ctx.fillStyle = 'deepskyblue';
+ ctx.beginPath();
+ ctx.arc(45,45,20,0,Math.PI*2,true);
+ ctx.fill();
+}
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-composite.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-composite.https.html
new file mode 100644
index 0000000000..d654ba49aa
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-composite.https.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-composite-ref.html">
+<style>
+ div {
+ display: inline-block;
+ width: 80px;
+ height: 80px;
+ }
+ #source-over { background-image: paint(source-over); }
+ #source-in { background-image: paint(source-in); }
+ #source-out { background-image: paint(source-out); }
+ #source-atop { background-image: paint(source-atop); }
+ #destination-over { background-image: paint(destination-over); }
+ #destination-in { background-image: paint(destination-in); }
+ #destination-out { background-image: paint(destination-out); }
+ #destination-atop { background-image: paint(destination-atop); }
+ #lighter { background-image: paint(lighter); }
+ #xor { background-image: paint(xor); }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="source-over"></div>
+<div id="source-in"></div>
+<div id="source-out"></div>
+<div id="source-atop"></div>
+<br>
+<div id="destination-over"></div>
+<div id="destination-in"></div>
+<div id="destination-out"></div>
+<div id="destination-atop"></div>
+<br>
+<div id="lighter"></div>
+<div id="xor"></div>
+
+<script id="code" type="text/worklet">
+var compositeOps = [
+ 'source-over',
+ 'source-in',
+ 'source-out',
+ 'source-atop',
+ 'destination-over',
+ 'destination-in',
+ 'destination-out',
+ 'destination-atop',
+ 'lighter',
+ 'xor'
+];
+
+function doPaint(ctx, op) {
+ ctx.fillStyle = 'red';
+ ctx.fillRect(5, 5, 40, 40);
+
+ ctx.globalCompositeOperation = op;
+
+ ctx.fillStyle = 'deepskyblue';
+ ctx.beginPath();
+ ctx.arc(45,45,20,0,Math.PI*2,true);
+ ctx.fill();
+}
+
+for (var i = 0; i < compositeOps.length; i++) {
+ let op = compositeOps[i];
+ registerPaint(op, class { paint(ctx, geom) { doPaint(ctx, op); } });
+}
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-conicGradient-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-conicGradient-ref.html
new file mode 100644
index 0000000000..9042906b07
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-conicGradient-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="output" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+const g = ctx.createConicGradient(3*Math.PI/2, 30, 30);
+g.addColorStop(0, "#f0f");
+g.addColorStop(0.25, "#0ff");
+g.addColorStop(0.50, "#ff0");
+g.addColorStop(0.75, "#f0f");
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 100);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-conicGradient.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-conicGradient.https.html
new file mode 100644
index 0000000000..07584c0897
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-conicGradient.https.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-conicGradient-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(rects);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('rects', class {
+ paint(ctx, geom) {
+ const g = ctx.createConicGradient(3*Math.PI/2, 30, 30);
+ g.addColorStop(0, "#f0f");
+ g.addColorStop(0.25, "#0ff");
+ g.addColorStop(0.50, "#ff0");
+ g.addColorStop(0.75, "#f0f");
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 100);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-filter-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-filter-ref.html
new file mode 100644
index 0000000000..2e4b979ad8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-filter-ref.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+ canvas { display: inline-block; }
+</style>
+</head>
+<body>
+<canvas id='output0' width='100' height='100'></canvas>
+<canvas id='output1' width='100' height='100'></canvas>
+<canvas id='output2' width='100' height='100'></canvas>
+<canvas id='output3' width='100' height='100'></canvas>
+<canvas id='output4' width='100' height='100'></canvas>
+<br>
+<canvas id='output5' width='100' height='100'></canvas>
+<canvas id='output6' width='100' height='100'></canvas>
+<canvas id='output7' width='100' height='100'></canvas>
+<canvas id='output8' width='100' height='100'></canvas>
+<canvas id='output9' width='100' height='100'></canvas>
+<br>
+<canvas id='output10' width='100' height='100'></canvas>
+<canvas id='output11' width='100' height='100'></canvas>
+<canvas id='output12' width='100' height='100'></canvas>
+<canvas id='output13' width='100' height='100'></canvas>
+<canvas id='output14' width='100' height='100'></canvas>
+
+<script>
+var paint = function(id, filter) {
+ var c = document.getElementById(id);
+ var ctx = c.getContext('2d');
+ ctx.filter = filter;
+ ctx.fillStyle = '#A00';
+ ctx.fillRect(0, 0, 15, 15);
+ ctx.fillStyle = '#0A0';
+ ctx.fillRect(15, 0, 15, 15);
+ ctx.fillStyle = '#00A';
+ ctx.fillRect(0, 15, 15, 15);
+ ctx.fillStyle = "#AA0";
+ ctx.fillRect(15, 15, 15, 15);
+ return ctx;
+};
+
+paint('output0', "none");
+paint('output1', "blur(10px)");
+paint('output2', "blur(0px)");
+paint('output3', "blur(16px)");
+paint('output4', "blur(0px)");
+paint('output5', "brightness(40%)");
+paint('output6', "contrast(20%)");
+paint('output7', "drop-shadow(0 0 5px green)");
+paint('output8', "grayscale(100%)");
+paint('output9', "invert(100%)");
+paint('output10', "opacity(50%)");
+paint('output11', "saturate(20%)");
+paint('output12', "sepia(100%)");
+paint('output13', "sepia(1) hue-rotate(200deg)");
+paint('output14', "url(#url)");
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-filter.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-filter.https.html
new file mode 100644
index 0000000000..a53fff986c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-filter.https.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-filter-ref.html">
+<style>
+ div {
+ display: inline-block;
+ width: 100px;
+ height: 100px;
+ }
+ #filter-none { background-image: paint(filter-none); }
+ #filter-blur-10px { background-image: paint(filter-blur-10px); }
+ #filter-blur-50vh { background-image: paint(filter-blur-50vh); }
+ #filter-blur-1em { background-image: paint(filter-blur-1em); }
+ #filter-blur-2percent { background-image: paint(filter-blur-2percent); }
+ #filter-brightness { background-image: paint(filter-brightness); }
+ #filter-contrast { background-image: paint(filter-contrast); }
+ #filter-drop-shadow { background-image: paint(filter-drop-shadow); }
+ #filter-grayscale { background-image: paint(filter-grayscale); }
+ #filter-invert { background-image: paint(filter-invert); }
+ #filter-opacity { background-image: paint(filter-opacity); }
+ #filter-saturate { background-image: paint(filter-saturate); }
+ #filter-sepia { background-image: paint(filter-sepia); }
+ #filter-hue-rotate { background-image: paint(filter-hue-rotate); }
+ #filter-url { background-image: paint(filter-url); }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="filter-none"></div>
+<div id="filter-blur-10px"></div>
+<div id="filter-blur-50vh"></div>
+<div id="filter-blur-1em"></div>
+<div id="filter-blur-2percent"></div>
+<br>
+<div id="filter-brightness"></div>
+<div id="filter-contrast"></div>
+<div id="filter-drop-shadow"></div>
+<div id="filter-grayscale"></div>
+<div id="filter-invert"></div>
+<br>
+<div id="filter-opacity"></div>
+<div id="filter-saturate"></div>
+<div id="filter-sepia"></div>
+<div id="filter-hue-rotate"></div>
+<div id="filter-url"></div>
+
+<script id="code" type="text/worklet">
+var paintNames = [
+ 'filter-none',
+ 'filter-blur-10px',
+ 'filter-blur-50vh',
+ 'filter-blur-1em',
+ 'filter-blur-2percent',
+ 'filter-brightness',
+ 'filter-contrast',
+ 'filter-drop-shadow',
+ 'filter-grayscale',
+ 'filter-invert',
+ 'filter-opacity',
+ 'filter-saturate',
+ 'filter-sepia',
+ 'filter-hue-rotate',
+ 'filter-url'
+];
+
+var filterOps = [
+ 'none',
+ 'blur(10px)',
+ 'blur(50vh)',
+ 'blur(1em)',
+ 'blur(2%)',
+ 'brightness(40%)',
+ 'contrast(20%)',
+ 'drop-shadow(0 0 5px green)',
+ 'grayscale(100%)',
+ 'invert(100%)',
+ 'opacity(50%)',
+ 'saturate(20%)',
+ 'sepia(100%)',
+ 'sepia(1) hue-rotate(200deg)',
+ 'url(#url)'
+];
+
+function doPaint(ctx, op) {
+ ctx.filter = op;
+ ctx.fillStyle = '#A00';
+ ctx.fillRect(0, 0, 15, 15);
+ ctx.fillStyle = '#0A0';
+ ctx.fillRect(15, 0, 15, 15);
+ ctx.fillStyle = '#00A';
+ ctx.fillRect(0, 15, 15, 15);
+ ctx.fillStyle = "#AA0";
+ ctx.fillRect(15, 15, 15, 15);
+};
+
+for (var i = 0; i < filterOps.length; i++) {
+ let op = filterOps[i];
+ registerPaint(paintNames[i], class { paint(ctx, geom) { doPaint(ctx, op); } });
+}
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-gradient-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-gradient-ref.html
new file mode 100644
index 0000000000..f3644a92fd
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-gradient-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="200" height="100"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+var linearGradient = ctx.createLinearGradient(0, 0, 100, 100);
+linearGradient.addColorStop(0, 'blue');
+linearGradient.addColorStop(0.5, 'red');
+linearGradient.addColorStop(1, 'white');
+ctx.fillStyle = linearGradient;
+ctx.fillRect(0, 0, 100, 100);
+
+var radialGradient = ctx.createRadialGradient(150, 50, 0, 150, 50, 50);
+radialGradient.addColorStop(0, 'blue');
+radialGradient.addColorStop(0.5, 'red');
+radialGradient.addColorStop(1, 'white');
+ctx.fillStyle = radialGradient;
+ctx.fillRect(100, 0, 100, 100);
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-gradient.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-gradient.https.html
new file mode 100644
index 0000000000..f99b7cb901
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-gradient.https.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta name=fuzzy content="0-5;3000-4000">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-gradient-ref.html">
+<style>
+ #output {
+ width: 200px;
+ height: 100px;
+ background-image: paint(gradients);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('gradients', class {
+ paint(ctx, geom) {
+ var linearGradient = ctx.createLinearGradient(0, 0, 100, 100);
+ linearGradient.addColorStop(0, 'blue');
+ linearGradient.addColorStop(0.5, 'red');
+ linearGradient.addColorStop(1, 'white');
+ ctx.fillStyle = linearGradient;
+ ctx.fillRect(0, 0, 100, 100);
+
+ var radialGradient = ctx.createRadialGradient(150, 50, 0, 150, 50, 50);
+ radialGradient.addColorStop(0, 'blue');
+ radialGradient.addColorStop(0.5, 'red');
+ radialGradient.addColorStop(1, 'white');
+ ctx.fillStyle = radialGradient;
+ ctx.fillRect(100, 0, 100, 100);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-image-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-image-ref.html
new file mode 100644
index 0000000000..90c62e5421
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-image-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<style>
+div {
+ width: 300px;
+ height: 300px;
+ background-image: url("./resources/html5.png");
+ background-repeat: no-repeat;
+ background-color: green;
+}
+</style>
+<body>
+<div></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-image.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-image.https.html
new file mode 100644
index 0000000000..71074df796
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-image.https.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-image-ref.html">
+<style>
+#output {
+ width: 300px;
+ height: 300px;
+ background-image: paint(image);
+ border-image: url("./resources/html5.png");
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+ registerPaint('image', class {
+ static get inputProperties() { return [ 'border-image-source' ]; };
+ paint(ctx, geom, styleMap) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ ctx.drawImage(styleMap.get('border-image-source'), 0, 0);
+ }
+ });
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-paths-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-paths-ref.html
new file mode 100644
index 0000000000..313a71e190
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-paths-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="300" height="400"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.beginPath();
+ctx.lineWidth = '10';
+ctx.strokeStyle = 'green';
+ctx.moveTo(15, 15);
+ctx.lineTo(135, 15);
+ctx.lineTo(70, 170);
+ctx.closePath();
+ctx.stroke();
+
+var path1 = new Path2D();
+path1.moveTo(250, 25);
+path1.bezierCurveTo(110, 150, 110, 300, 200, 200);
+ctx.strokeStyle = 'purple';
+ctx.setLineDash([ 10, 5 ]);
+ctx.stroke(path1);
+
+ctx.fillStyle = 'red';
+ctx.beginPath()
+ctx.arc(75, 325, 50, 0, Math.PI * 2, true);
+ctx.arc(75, 325, 20, 0, Math.PI * 2, true);
+ctx.fill('evenodd');
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-paths.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-paths.https.html
new file mode 100644
index 0000000000..ae29930dc6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-paths.https.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-paths-ref.html">
+<style>
+ #output {
+ width: 300px;
+ height: 400px;
+ background-image: paint(paths);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('paths', class {
+ paint(ctx, geom) {
+ ctx.beginPath();
+ ctx.lineWidth = '10';
+ ctx.strokeStyle = 'green';
+ ctx.moveTo(15, 15);
+ ctx.lineTo(135, 15);
+ ctx.lineTo(70, 170);
+ ctx.closePath();
+ ctx.stroke();
+
+ var path1 = new Path2D();
+ path1.moveTo(250, 25);
+ path1.bezierCurveTo(110, 150, 110, 300, 200, 200);
+ ctx.strokeStyle = 'purple';
+ ctx.setLineDash([ 10, 5 ]);
+ ctx.stroke(path1);
+
+ ctx.fillStyle = 'red';
+ ctx.beginPath()
+ ctx.arc(75, 325, 50, 0, Math.PI * 2, true);
+ ctx.arc(75, 325, 20, 0, Math.PI * 2, true);
+ ctx.fill('evenodd');
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-rects-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-rects-ref.html
new file mode 100644
index 0000000000..fae2de7b7a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-rects-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="100" height="100" style="background: blue;"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'green';
+ctx.fillRect(0, 0, 100, 100);
+
+ctx.clearRect(40, 40, 20, 20);
+
+ctx.strokeStyle = 'red';
+ctx.lineWidth = 4;
+ctx.strokeRect(20, 20, 60, 60);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-rects.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-rects.https.html
new file mode 100644
index 0000000000..9279aa2a87
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-rects.https.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-rects-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(rects);
+ background-color: blue;
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('rects', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+
+ ctx.clearRect(40, 40, 20, 20);
+
+ ctx.strokeStyle = 'red';
+ ctx.lineWidth = 4;
+ ctx.strokeRect(20, 20, 60, 60);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-reset-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-reset-ref.html
new file mode 100644
index 0000000000..9ee3bdbce1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-reset-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="output" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'yellow';
+ctx.fillRect(10, 10, 50, 50);
+ctx.fillStyle = 'magenta';
+ctx.fillRect(20, 20, 50, 50);
+ctx.strokeStyle = 'cyan';
+ctx.moveTo(40, 0);
+ctx.reset();
+ctx.lineWidth = 10;
+ctx.lineTo(0, 40);
+ctx.stroke();
+ctx.fillRect(30, 30, 20, 20);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-reset.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-reset.https.html
new file mode 100644
index 0000000000..2d5158effb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-reset.https.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-reset-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(rects);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('rects', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(10, 10, 50, 50);
+ ctx.fillStyle = 'magenta';
+ ctx.fillRect(20, 20, 50, 50);
+ ctx.strokeStyle = 'cyan';
+ ctx.moveTo(40, 0);
+ ctx.reset();
+ ctx.lineWidth = 10;
+ ctx.lineTo(0, 40);
+ ctx.stroke();
+ ctx.fillRect(30, 30, 20, 20);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-roundRect-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-roundRect-ref.html
new file mode 100644
index 0000000000..71e9031f4b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-roundRect-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="100" height="100" style="background: blue;"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'green';
+ctx.roundRect(10, 10, 80, 80, [20, 40, 10]);
+ctx.fill();
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-roundRect.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-roundRect.https.html
new file mode 100644
index 0000000000..7849354e87
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-roundRect.https.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-roundRect-ref.html">
+<meta name="fuzzy" content="maxDifference=0-128;totalPixels=0-200">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(rects);
+ background-color: blue;
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('rects', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.roundRect(10, 10, 80, 80, [20, 40, 10]);
+ ctx.fill();
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-shadows-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-shadows-ref.html
new file mode 100644
index 0000000000..94aea6ff80
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-shadows-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="200" height="100"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.shadowColor = 'black';
+ctx.shadowOffsetY = 10;
+ctx.shadowOffsetX = 10;
+ctx.fillStyle = 'green'
+ctx.fillRect(10, 10, 50, 50);
+
+ctx.shadowColor = 'blue';
+ctx.shadowBlur = 10;
+ctx.shadowOffsetX = 5;
+ctx.shadowOffsetY = 5;
+ctx.fillStyle = 'green';
+ctx.fillRect(110, 10, 50, 50);
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-shadows.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-shadows.https.html
new file mode 100644
index 0000000000..124819fa3a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-shadows.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-shadows-ref.html">
+<style>
+ #output {
+ width: 200px;
+ height: 100px;
+ background-image: paint(shadows);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('shadows', class {
+ paint(ctx, geom) {
+ ctx.shadowColor = 'black';
+ ctx.shadowOffsetY = 10;
+ ctx.shadowOffsetX = 10;
+ ctx.fillStyle = 'green'
+ ctx.fillRect(10, 10, 50, 50);
+
+ ctx.shadowColor = 'blue';
+ ctx.shadowBlur = 10;
+ ctx.shadowOffsetX = 5;
+ ctx.shadowOffsetY = 5;
+ ctx.fillStyle = 'green';
+ ctx.fillRect(110, 10, 50, 50);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-transform-ref.html b/testing/web-platform/tests/css/css-paint-api/paint2d-transform-ref.html
new file mode 100644
index 0000000000..08893127a6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-transform-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="200" height="200"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'green';
+ctx.transform(1, 0.5, 0, 1, 20, 20);
+ctx.fillRect(0, 0, 50, 50);
+
+ctx.resetTransform();
+
+ctx.fillStyle = 'blue';
+ctx.translate(150, 60);
+ctx.rotate(60 * Math.PI / 180);
+ctx.scale(1.5, 1);
+ctx.fillRect(0, 0, 50, 50);
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/paint2d-transform.https.html b/testing/web-platform/tests/css/css-paint-api/paint2d-transform.https.html
new file mode 100644
index 0000000000..b264d1da5f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/paint2d-transform.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="paint2d-transform-ref.html">
+<style>
+ #output {
+ width: 200px;
+ height: 200px;
+ background-image: paint(transform);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('transform', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.transform(1, 0.5, 0, 1, 20, 20);
+ ctx.fillRect(0, 0, 50, 50);
+
+ ctx.resetTransform();
+
+ ctx.fillStyle = 'blue';
+ ctx.translate(150, 60);
+ ctx.rotate(60 * Math.PI / 180);
+ ctx.scale(1.5, 1);
+ ctx.fillRect(0, 0, 50, 50);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-001.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-001.https.html
new file mode 100644
index 0000000000..d18259e4d7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-001.https.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo', class {
+ static get inputArguments() {
+ throw Error('failed!');
+ }
+ });
+} catch(ex) {
+ if (ex.name == 'Error' && ex.message == 'failed!')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-002.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-002.https.html
new file mode 100644
index 0000000000..c5975586e9
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-002.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo1', class {
+ static get inputArguments() {
+ return 'non sense stuff';
+ }
+ });
+} catch(ex) {
+ // 'inputArguments' property is a string, not a sequence.
+ if (ex.name == 'TypeError')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-003.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-003.https.html
new file mode 100644
index 0000000000..4d5daa7073
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-003.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo2', class {
+ static get inputArguments() {
+ return ['<non-sense-type>'];
+ }
+ });
+} catch(ex) {
+ // 'non-sense-type' is not a proper name of CSS properties.
+ if (ex.name == 'TypeError')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-004.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-004.https.html
new file mode 100644
index 0000000000..bd1e5651af
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-004.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo3', class {
+ static get inputArguments() {
+ return ['<length>'];
+ }
+ paint() { }
+ });
+ testsPassed = true;
+} catch(ex) {
+ testsPassed = false;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-005.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-005.https.html
new file mode 100644
index 0000000000..16744ec355
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-005.https.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo', class { paint() { } });
+ registerPaint('foo', class { paint() { } });
+} catch(ex) {
+ // 'foo' gets registered twice.
+ if (ex.name == 'InvalidModificationError')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-006.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-006.https.html
new file mode 100644
index 0000000000..2fbbec7705
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-006.https.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('', class { });
+} catch(ex) {
+ // The empty string is not a valid name.
+ if (ex.name == 'TypeError')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-007.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-007.https.html
new file mode 100644
index 0000000000..1fc435fc7b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-007.https.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo3', class {
+ static get inputProperties() {
+ throw Error('failed!');
+ }
+ });
+} catch(ex) {
+ if (ex.name == 'Error' && ex.message == 'failed!')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-008.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-008.https.html
new file mode 100644
index 0000000000..9543d2d884
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-008.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo4', class {
+ static get inputProperties() {
+ return 42;
+ }
+ });
+} catch(ex) {
+ // 'inputProperties' property is 42, not a sequence<DOMString>.
+ if (ex.name == 'TypeError')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-009.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-009.https.html
new file mode 100644
index 0000000000..41e8411a4a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-009.https.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ var a = function() { };
+ a.prototype = undefined;
+ registerPaint('foo5', a);
+} catch(ex) {
+ // The prototype object is undefined, not an object.
+ if (ex.name == 'TypeError')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-010.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-010.https.html
new file mode 100644
index 0000000000..44bbab5b7f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-010.https.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ var b = function() { };
+ b.prototype = 42;
+ registerPaint('foo6', b);
+} catch(ex) {
+ // The prototype object is 42, not an object.
+ if (ex.name == 'TypeError')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-011.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-011.https.html
new file mode 100644
index 0000000000..09f8b02747
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-011.https.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo7', class { });
+} catch(ex) {
+ // 'paint' property doesn't exist on the prototype chain.
+ if (ex.name == 'TypeError')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-012.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-012.https.html
new file mode 100644
index 0000000000..4a05b6fcf1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-012.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo8', class {
+ get paint() {
+ return 42;
+ }
+ });
+} catch(ex) {
+ // 'paint' property's value is 42, not a function.
+ if (ex.name == 'TypeError')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-013.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-013.https.html
new file mode 100644
index 0000000000..ef8bf905c2
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-013.https.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo9', class { paint() { } });
+ testsPassed = true;
+} catch(ex) {
+ testsPassed = false;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-014.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-014.https.html
new file mode 100644
index 0000000000..715dab8dc7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-014.https.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ var c = function() { };
+ c.prototype.paint = function() { };
+ registerPaint('foo10', c);
+ testsPassed = true;
+} catch(ex) {
+ testsPassed = false;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-015.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-015.https.html
new file mode 100644
index 0000000000..4c8cfebca4
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-015.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo11', class {
+ static get inputProperties() {
+ return ['-webkit-border-radius'];
+ }
+ paint() { }
+ });
+ testsPassed = true;
+} catch(ex) {
+ testsPassed = false;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-016.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-016.https.html
new file mode 100644
index 0000000000..aa5eda8aae
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-016.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo12', class {
+ static get contextOptions() {
+ return 42;
+ }
+ });
+} catch(ex) {
+ // 'contextOptions' property is 42, not a dictionary.
+ if (ex.name == 'TypeError')
+ testsPassed = true;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-017.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-017.https.html
new file mode 100644
index 0000000000..2ba8d996c6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-017.https.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo13', class {
+ static get contextOptions() { return {alpha: true}; }
+ paint() { }
+ });
+ testsPassed = true;
+} catch(ex) {
+ testsPassed = false;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-018-ref.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-018-ref.html
new file mode 100644
index 0000000000..55b841fc64
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-018-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This test result should show a green rect. The registerPaint('failureIndicator')
+will be called twice and the inputArguments will return two different strings,
+which will throw an exception and the paint function with 'failureIndicator'
+should never be called. In other words, there should be no red painted in the result.</p>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green'
+context.fillRect(50, 50, 50, 50);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-018.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-018.https.html
new file mode 100644
index 0000000000..1554cc6445
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-018.https.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-018-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(failureIndicator), paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<p>This test result should show a green rect. The registerPaint('failureIndicator')
+will be called twice and the inputArguments will return two different strings,
+which will throw an exception and the paint function with 'failureIndicator'
+should never be called. In other words, there should be no red painted in the result.</p>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+function generateRandString(length) {
+ var text = "";
+ var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ for (var i = 0; i < length; i++)
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
+ return text;
+}
+
+try {
+ registerPaint('failureIndicator', class {
+ static get inputArguments() {
+ // This test is testing the case where an exception should be thrown
+ // when two paint definitions with different properties are registered
+ // to the same paint worklet. In order to do that, we randomly generate
+ // the input properties here. We make the string length 100 to make sure
+ // that it is veryyyyyyyyyyyy unlikely that two strings will be the same
+ // when running this test.
+ var current_str = generateRandString(100);
+ return [current_str];
+ }
+ // The paint function here should never be called because the inputArguments
+ // will generate two different properties, and that should throw an
+ // exception.
+ paint(ctx, geom) {
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, 50, 50);
+ }
+ });
+} catch(ex) {
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(50, 50, 50, 50);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-019.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-019.https.html
new file mode 100644
index 0000000000..d0a628561d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-019.https.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo', class {
+ static get contextOptions() { return {alpha: 42}; }
+ paint() {}
+ });
+ testsPassed = true;
+} catch(ex) {
+ testsPassed = false;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-020.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-020.https.html
new file mode 100644
index 0000000000..7797eb45fe
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-020.https.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo', class {
+ paint() {}
+ });
+ testsPassed = true;
+} catch(ex) {
+ testsPassed = false;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-021.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-021.https.html
new file mode 100644
index 0000000000..22d6d5adbd
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-021.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo', class {
+ // Setting anything other than alpha should not throw exception, and
+ // the alpha value should fall back to default, which is true.
+ static get contextOptions() { return {bogus: true}; }
+ paint() {}
+ });
+ testsPassed = true;
+} catch(ex) {
+ testsPassed = false;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-022.https.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-022.https.html
new file mode 100644
index 0000000000..9434807039
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-022.https.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+var testsPassed = false;
+try {
+ registerPaint('foo', class {
+ static get contextOptions() { return null; }
+ paint() {}
+ });
+ testsPassed = true;
+} catch(ex) {
+ testsPassed = false;
+}
+
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (testsPassed)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-ref.html b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-ref.html
new file mode 100644
index 0000000000..862212092a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parse-input-arguments-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 100);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/parsing/paint-function-valid.https.html b/testing/web-platform/tests/css/css-paint-api/parsing/paint-function-valid.https.html
new file mode 100644
index 0000000000..187bd9e94c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/parsing/paint-function-valid.https.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset=UTF-8>
+<title>CSS Painting API Level 1: parsing paint() with valid values</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/#paint-notation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+
+<body>
+
+<!--
+
+This test registers the paint function it uses. However, for access
+to specified and computed values, this doesn't appear to be required
+by the specification. However, it does appear to be required by the
+current implementation in Chromium. See https://crbug.com/1344490 .
+
+-->
+
+<script id="code" type="text/worklet">
+
+registerPaint('mypaint', class {
+ paint(ctx, size, properties, args) { }
+});
+
+</script>
+
+<script>
+
+setup({ explicit_done: true });
+
+let worklet_code = document.getElementById('code').textContent;
+importWorklet(CSS.paintWorklet, worklet_code).then(() => {
+ test_valid_value("background-image", "paint(mypaint)");
+ test_valid_value("background-image", "paint( mypaint )", "paint(mypaint)");
+ test_valid_value("background-image", "paint(mypaint ", "paint(mypaint)");
+ test_valid_value("background-image", "paint( mypaint", "paint(mypaint)");
+ test_valid_value("background-image", "paint(mypaint, blue)");
+ test_valid_value("background-image", "paint(mypaint, {})");
+ test_valid_value("background-image", "paint(mypaint, [])");
+ test_valid_value("background-image", "paint(mypaint, ())");
+
+ done();
+});
+
+</script>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-001.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-001.https.html
new file mode 100644
index 0000000000..5aaed62542
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-001.https.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Interpolated &lt;angle&gt; values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ registerAndInterpolateProperty({
+ on: target, from: '100deg', to: '200deg',
+ name: '--prop', syntax: '<angle>'
+ });
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 150deg]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-002.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-002.https.html
new file mode 100644
index 0000000000..80b2c9339d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-002.https.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Interpolated &lt;color&gt; values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ registerAndInterpolateProperty({
+ on: target, from: 'rgb(128, 100, 200)', to: 'red',
+ name: '--prop', syntax: '<color>'
+ });
+
+ expectWorkletValue(target, '--prop', '[CSSStyleValue rgb(192, 50, 100)]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-003.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-003.https.html
new file mode 100644
index 0000000000..683ed403fb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-003.https.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Interpolated &lt;integer&gt; values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ registerAndInterpolateProperty({
+ on: target, from: '32', to: '64',
+ name: '--prop', syntax: '<integer>'
+ });
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 48]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-004.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-004.https.html
new file mode 100644
index 0000000000..9602e902ec
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-004.https.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Interpolated &lt;length-percentage&gt; values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ registerAndInterpolateProperty({
+ on: target, from: '10px', to: '20%',
+ name: '--prop', syntax: '<length-percentage>'
+ });
+
+ expectWorkletValue(target, '--prop', '[CSSMathSum calc(10% + 5px)]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-005.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-005.https.html
new file mode 100644
index 0000000000..35d6ccbf3d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-005.https.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Interpolated &lt;length&gt; values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ target.style.setProperty('font-size', '10px');
+
+ registerAndInterpolateProperty({
+ on: target, from: '10px', to: '20px',
+ name: '--prop-1', syntax: '<length>'
+ });
+
+ registerAndInterpolateProperty({
+ on: target, from: '100px', to: '20em',
+ name: '--prop-2', syntax: '<length>'
+ });
+
+ expectWorkletValues(target, {
+ '--prop-1': '[CSSUnitValue 15px]',
+ '--prop-2': '[CSSUnitValue 150px]'
+ });
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-006.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-006.https.html
new file mode 100644
index 0000000000..a8cfdead0f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-006.https.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Interpolated &lt;number&gt; values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ registerAndInterpolateProperty({
+ on: target, from: '8.5', to: '16.5',
+ name: '--prop', syntax: '<number>'
+ });
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 12.5]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-007.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-007.https.html
new file mode 100644
index 0000000000..77b80b51e6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-007.https.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Interpolated &lt;percentage&gt; values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ registerAndInterpolateProperty({
+ on: target, from: '40%', to: '60%',
+ name: '--prop', syntax: '<percentage>'
+ });
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 50%]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-008.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-008.https.html
new file mode 100644
index 0000000000..1ec166614e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-008.https.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Interpolated &lt;resolution&gt; values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ registerAndInterpolateProperty({
+ on: target, from: '100dppx', to: '900dppx',
+ name: '--prop', syntax: '<resolution>'
+ });
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 500dppx]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-009.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-009.https.html
new file mode 100644
index 0000000000..e7a5e37c64
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-009.https.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Interpolated &lt;time&gt; values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ registerAndInterpolateProperty({
+ on: target, from: '42s', to: '62s',
+ name: '--prop', syntax: '<time>'
+ });
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 52s]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-010.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-010.https.html
new file mode 100644
index 0000000000..ee3a0f1b32
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-interpolation-010.https.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Interpolated list values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ registerAndInterpolateProperty({
+ on: target, from: '10px 20px', to: '20px 30px',
+ name: '--prop-1', syntax: '<length>+'
+ });
+
+ registerAndInterpolateProperty({
+ on: target, from: '10px', to: '20px',
+ name: '--prop-2', syntax: '<length>+'
+ });
+
+ expectWorkletValues(target, {
+ '--prop-1': ['[CSSUnitValue 15px]', '[CSSUnitValue 25px]'],
+ '--prop-2': '[CSSUnitValue 15px]'
+ });
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-invalidation-001.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-invalidation-001.https.html
new file mode 100644
index 0000000000..408ba49743
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-invalidation-001.https.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Registering a property causes invalidation for initial value</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<style>
+#target {
+ background: paint(geometry);
+ width: 100px;
+ height: 100px;
+}
+</style>
+<div id="target"></div>
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--color']; }
+ paint(ctx, geom, styleMap) {
+ ctx.fillStyle = styleMap.get('--color').toString();
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ async function test() {
+ getComputedStyle(target);
+ let code = document.getElementById('code').textContent;
+ await importWorklet(CSS.paintWorklet, code);
+ await workletPainted();
+ CSS.registerProperty({
+ name: '--color',
+ syntax: '<color>',
+ initialValue: 'green',
+ inherits: false
+ });
+ await workletPainted();
+ takeScreenshot();
+ }
+
+ test();
+</script>
+</body>
+</html>
+
+
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-invalidation-002.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-invalidation-002.https.html
new file mode 100644
index 0000000000..b65bcd5a6e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-invalidation-002.https.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Registering a property causes invalidation for applied value</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<style>
+#target {
+ background: paint(geometry);
+ width: 100px;
+ height: 100px;
+ --length: 100px;
+}
+</style>
+<div id="target"></div>
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--length']; }
+ paint(ctx, geom, styleMap) {
+ let value = styleMap.get('--length');
+ let pass = value.value === 100 && value.unit === 'px';
+ ctx.fillStyle = pass ? 'green' : 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ async function test() {
+ getComputedStyle(target);
+ let code = document.getElementById('code').textContent;
+ await importWorklet(CSS.paintWorklet, code);
+ await workletPainted();
+ CSS.registerProperty({
+ name: '--length',
+ syntax: '<length>',
+ initialValue: '0px',
+ inherits: false
+ });
+ await workletPainted();
+ takeScreenshot();
+ }
+
+ test();
+</script>
+</body>
+</html>
+
+
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-stylemap.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-stylemap.https.html
new file mode 100644
index 0000000000..3dec98d910
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-stylemap.https.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Test styleMap functions</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<style>
+ #target {
+ width: 100px;
+ height: 100px;
+ background: paint(style-map);
+ }
+</style>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<length>+',
+ initialValue: '10px 10px 10px 10px',
+ inherits: false
+ });
+
+ const worklet = `
+ registerPaint('style-map', class {
+ static get inputProperties() { return ['--prop']; }
+ paint(ctx, geom, styleMap) {
+ let serialize = (v) => '[' + v.constructor.name + ' ' + v.toString() + ']';
+ let expected = '[CSSUnitValue 10px]';
+ let isExpected = x => serialize(x) === expected;
+
+ let pass = true;
+
+ pass &= styleMap.has('--prop');
+ pass &= isExpected(styleMap.get('--prop'));
+ pass &= styleMap.getAll('--prop').length == 4;
+ pass &= styleMap.getAll('--prop').every(isExpected);
+ pass &= Array.from(styleMap).filter(e => e[0] == '--prop')[0][1].length == 4;
+ pass &= Array.from(styleMap).filter(e => e[0] == '--prop')[0][1].every(isExpected);
+
+ ctx.fillStyle = pass ? 'green' : 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+ });`
+
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, worklet);
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-001.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-001.https.html
new file mode 100644
index 0000000000..970e1f3e5e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-001.https.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Initial values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<length>',
+ initialValue: '42px',
+ inherits: false
+ });
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 42px]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-002.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-002.https.html
new file mode 100644
index 0000000000..6019151b10
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-002.https.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Inherited values reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="outer">
+ <div id="target"></div>
+</div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<length>',
+ initialValue: '0px',
+ inherits: true
+ });
+
+ outer.style.setProperty('--prop', '13px');
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 13px]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-003.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-003.https.html
new file mode 100644
index 0000000000..b9c3bf3fd9
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-003.https.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of *-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '*',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', 'if(){}');
+
+ expectWorkletValue(target, '--prop', '[CSSUnparsedValue if(){}]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-004.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-004.https.html
new file mode 100644
index 0000000000..e04be69f80
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-004.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;angle&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<angle>',
+ initialValue: '0deg',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', '100deg');
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 100deg]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-005.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-005.https.html
new file mode 100644
index 0000000000..bfecd0c56b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-005.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;color&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<color>',
+ initialValue: 'black',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', 'rgb(1, 2, 3)');
+
+ expectWorkletValue(target, '--prop', '[CSSStyleValue rgb(1, 2, 3)]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-006.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-006.https.html
new file mode 100644
index 0000000000..7176b67d4b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-006.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;custom-ident&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<custom-ident>',
+ initialValue: 'none',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', 'foo');
+
+ expectWorkletValue(target, '--prop', '[CSSKeywordValue foo]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-007.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-007.https.html
new file mode 100644
index 0000000000..309fe969b6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-007.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;image&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop-1',
+ syntax: '<image> | none',
+ initialValue: 'none',
+ inherits: false
+ });
+
+ CSS.registerProperty({
+ name: '--prop-2',
+ syntax: '<image> | none',
+ initialValue: 'none',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop-1', 'url("http://a/")');
+ target.style.setProperty('--prop-2', 'linear-gradient(red, red)');
+
+ expectWorkletValues(target, {
+ '--prop-1': ['[CSSImageValue url("http://a/")]'],
+ '--prop-2': ['[CSSStyleValue linear-gradient(red, red)]'],
+ });
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-008.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-008.https.html
new file mode 100644
index 0000000000..db72408d77
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-008.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;integer&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<integer>',
+ initialValue: '0',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', '5');
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 5]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-009.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-009.https.html
new file mode 100644
index 0000000000..a2c2e9a8cd
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-009.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;length-percentage&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop-1',
+ syntax: '<length-percentage>',
+ initialValue: '0',
+ inherits: false
+ });
+
+ CSS.registerProperty({
+ name: '--prop-2',
+ syntax: '<length-percentage>',
+ initialValue: '0',
+ inherits: false
+ });
+
+ CSS.registerProperty({
+ name: '--prop-3',
+ syntax: '<length-percentage>',
+ initialValue: '0',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop-1', '10%');
+ target.style.setProperty('--prop-2', '10px');
+ target.style.setProperty('--prop-3', 'calc(10% + 10px)');
+
+ expectWorkletValues(target, {
+ '--prop-1': ['[CSSUnitValue 10%]'],
+ '--prop-2': ['[CSSUnitValue 10px]'],
+ '--prop-3': ['[CSSMathSum calc(10% + 10px)]'],
+ });
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-010.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-010.https.html
new file mode 100644
index 0000000000..332a22a1b9
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-010.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;length&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop-1',
+ syntax: '<length>',
+ initialValue: '0',
+ inherits: false
+ });
+
+ CSS.registerProperty({
+ name: '--prop-2',
+ syntax: '<length>',
+ initialValue: '0',
+ inherits: false
+ });
+
+ target.style.setProperty('font-size', '20px');
+ target.style.setProperty('--prop-1', '100px');
+ target.style.setProperty('--prop-2', '10em');
+
+ expectWorkletValues(target, {
+ '--prop-1': ['[CSSUnitValue 100px]'],
+ '--prop-2': ['[CSSUnitValue 200px]']
+ });
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-011.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-011.https.html
new file mode 100644
index 0000000000..a596a5d55f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-011.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;number&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<number>',
+ initialValue: '0',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', '2.5');
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 2.5]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-012.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-012.https.html
new file mode 100644
index 0000000000..80c1e6ed37
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-012.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;percentage&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<percentage>',
+ initialValue: '0%',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', '33%');
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 33%]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-013.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-013.https.html
new file mode 100644
index 0000000000..7af03929d8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-013.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;resolution&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<resolution>',
+ initialValue: '0dppx',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', '300dppx');
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 300dppx]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-014.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-014.https.html
new file mode 100644
index 0000000000..0ca1eca13e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-014.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;time&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<time>',
+ initialValue: '0s',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', '10s');
+
+ expectWorkletValue(target, '--prop', '[CSSUnitValue 10s]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-015.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-015.https.html
new file mode 100644
index 0000000000..d7ba26b852
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-015.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of &lt;url&gt;-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: '<url> | none',
+ initialValue: 'none',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', 'url("http://a/")');
+
+ expectWorkletValue(target, '--prop', '[CSSStyleValue url("http://a/")]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-016.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-016.https.html
new file mode 100644
index 0000000000..609f00f6d0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-016.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of ident-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: 'foo | bar | none',
+ initialValue: 'none',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', 'bar');
+
+ expectWorkletValue(target, '--prop', '[CSSKeywordValue bar]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-017.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-017.https.html
new file mode 100644
index 0000000000..609f00f6d0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-017.https.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of ident-properties reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop',
+ syntax: 'foo | bar | none',
+ initialValue: 'none',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop', 'bar');
+
+ expectWorkletValue(target, '--prop', '[CSSKeywordValue bar]');
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/registered-property-value-018.https.html b/testing/web-platform/tests/css/css-paint-api/registered-property-value-018.https.html
new file mode 100644
index 0000000000..1f9876b6b5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-value-018.https.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Values of lists reach worklet</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="parse-input-arguments-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<script src="./resources/utils.js"></script>
+<body>
+<div id="target"></div>
+<script>
+ try {
+ CSS.registerProperty({
+ name: '--prop-1',
+ syntax: '<length>+ | none',
+ initialValue: 'none',
+ inherits: false
+ });
+
+ CSS.registerProperty({
+ name: '--prop-2',
+ syntax: '<length># | none',
+ initialValue: 'none',
+ inherits: false
+ });
+
+ CSS.registerProperty({
+ name: '--prop-3',
+ syntax: '<length># | none',
+ initialValue: 'none',
+ inherits: false
+ });
+
+ target.style.setProperty('--prop-1', '8px 16px');
+ target.style.setProperty('--prop-2', '8px, 16px');
+ target.style.setProperty('--prop-3', '8px');
+
+ expectWorkletValues(target, {
+ '--prop-1': ['[CSSUnitValue 8px]', '[CSSUnitValue 16px]'],
+ '--prop-2': ['[CSSUnitValue 8px]', '[CSSUnitValue 16px]'],
+ '--prop-3': ['[CSSUnitValue 8px]'],
+ });
+ } catch(e) {
+ document.body.textContent = e;
+ takeScreenshot();
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/resources/html5.png b/testing/web-platform/tests/css/css-paint-api/resources/html5.png
new file mode 100644
index 0000000000..e34419263f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/resources/html5.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-paint-api/resources/imported-module.mjs b/testing/web-platform/tests/css/css-paint-api/resources/imported-module.mjs
new file mode 100644
index 0000000000..2a23b33414
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/resources/imported-module.mjs
@@ -0,0 +1,2 @@
+// This doesn't need to contain anything. If it's dynamically import()ed
+// successfully, the test fails.
diff --git a/testing/web-platform/tests/css/css-paint-api/resources/utils.js b/testing/web-platform/tests/css/css-paint-api/resources/utils.js
new file mode 100644
index 0000000000..e968644136
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/resources/utils.js
@@ -0,0 +1,58 @@
+
+// Register a property, and interpolate its value to the halfway point.
+function registerAndInterpolateProperty(options) {
+ CSS.registerProperty({
+ name: options.name,
+ syntax: `${options.syntax} | none`,
+ initialValue: 'none',
+ inherits: false
+ });
+ let animation = options.on.animate([
+ { [options.name]: options.from },
+ { [options.name]: options.to }
+ ], 1000);
+ animation.currentTime = 500;
+ animation.pause();
+}
+
+// Apply a paint worklet to 'target' which verifies that the worklet-side value
+// of a set of properties is what we expect.
+//
+// The 'expected' parameter is an object where each key is the name of a
+// property to check, and each corresponding value is an array with the expected
+// (serialized) values for that property.
+function expectWorkletValues(target, expected) {
+ const workletName = 'registered-property-value';
+
+ // Wrap any single values in an array. This makes it possible to omit the
+ // array if there is only one value.
+ const ensureArray = x => x.constructor === Array ? x : [x];
+ expected = Object.entries(expected).map(([k, v]) => [k, ensureArray(v)])
+ .map(x => ({[x[0]]: x[1]}))
+ .reduce((a, b) => Object.assign(a, b), {});
+
+ target.style.setProperty('width', '100px');
+ target.style.setProperty('height', '100px');
+ target.style.setProperty('background-image', `paint(${workletName})`);
+
+ const worklet = `
+ const expectedData = ${JSON.stringify(expected)};
+ const expectedKeys = Object.keys(expectedData).sort();
+ registerPaint('${workletName}', class {
+ static get inputProperties() { return expectedKeys; }
+ paint(ctx, geom, styleMap) {
+ let serialize = (v) => '[' + v.constructor.name + ' ' + v.toString() + ']';
+ let actual = expectedKeys.map(k => styleMap.getAll(k).map(serialize).join(', ')).join(' | ');
+ let expected = expectedKeys.map(k => expectedData[k].join(', ')).join(' | ');
+ ctx.fillStyle = (actual === expected) ? 'green' : 'red';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+ });`
+
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, worklet);
+}
+
+// Like expectWorkletValues, but can only test a single property.
+function expectWorkletValue(target, property, expected) {
+ expectWorkletValues(target, { [property]: expected });
+}
diff --git a/testing/web-platform/tests/css/css-paint-api/roundrect-ref.html b/testing/web-platform/tests/css/css-paint-api/roundrect-ref.html
new file mode 100644
index 0000000000..b2b188736e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/roundrect-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="output" width="300" height="400"></canvas>
+<script>
+var canvas = document.getElementById('output');
+var ctx = canvas.getContext('2d');
+
+ctx.beginPath();
+ctx.roundRect(10, 10, 100, 100, [20]);
+ctx.fill();
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/css/css-paint-api/roundrect.https.html b/testing/web-platform/tests/css/css-paint-api/roundrect.https.html
new file mode 100644
index 0000000000..7fc2b3fc5b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/roundrect.https.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="roundrect-ref.html">
+<style>
+ #output {
+ width: 300px;
+ height: 400px;
+ background-image: paint(paths);
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('paths', class {
+ paint(ctx, geom) {
+ ctx.beginPath();
+ ctx.roundRect(10, 10, 100, 100, [20]);
+ ctx.fill();
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/setTransform-001.https.html b/testing/web-platform/tests/css/css-paint-api/setTransform-001.https.html
new file mode 100644
index 0000000000..9913d3ba6c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/setTransform-001.https.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>setTransform with DOMMatrix behaves correctly</title>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="setTransform-ref.html">
+<style>
+.container {
+ width: 200px;
+ height: 200px;
+}
+
+#foo {
+ background: paint(foo);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="foo" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ let m = ctx.getTransform();
+ m.a = 2;
+ m.d = 2;
+ ctx.setTransform(m);
+ ctx.fillRect(0, 0, 50, 50);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/setTransform-002.https.html b/testing/web-platform/tests/css/css-paint-api/setTransform-002.https.html
new file mode 100644
index 0000000000..779ebcac7e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/setTransform-002.https.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>setTransform with DOMMatrix behaves correctly</title>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="setTransform-ref.html">
+<style>
+.container {
+ width: 200px;
+ height: 200px;
+}
+
+#foo {
+ background: paint(foo);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="foo" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.setTransform({a: 2, d: 2});
+ ctx.fillRect(0, 0, 50, 50);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/setTransform-003.https.html b/testing/web-platform/tests/css/css-paint-api/setTransform-003.https.html
new file mode 100644
index 0000000000..cbdb525eca
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/setTransform-003.https.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>setTransform with NaN should be ignored</title>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="setTransform-ref.html">
+<style>
+.container {
+ width: 200px;
+ height: 200px;
+}
+
+#foo {
+ background: paint(foo);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="foo" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ // Set to a NaN should be ignored.
+ ctx.setTransform({a: NaN, d:2});
+ ctx.fillRect(0, 0, 100, 100);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/setTransform-004.https.html b/testing/web-platform/tests/css/css-paint-api/setTransform-004.https.html
new file mode 100644
index 0000000000..38a71677ad
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/setTransform-004.https.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>setTransform with Infinity should be ignored</title>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="setTransform-ref.html">
+<style>
+.container {
+ width: 200px;
+ height: 200px;
+}
+
+#foo {
+ background: paint(foo);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="foo" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ // Set to Infinity should be ignored.
+ ctx.setTransform({a: Infinity, d:2});
+ ctx.fillRect(0, 0, 100, 100);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/setTransform-ref.html b/testing/web-platform/tests/css/css-paint-api/setTransform-ref.html
new file mode 100644
index 0000000000..e969ba034a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/setTransform-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="200" height="200"></canvas>
+<script>
+var ctx = document.getElementById('canvas').getContext('2d');
+ctx.fillStyle = 'green';
+let m = ctx.getTransform();
+m.a = 2;
+m.d = 2;
+ctx.setTransform(m);
+ctx.fillRect(0, 0, 50, 50);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/style-background-image-ref.html b/testing/web-platform/tests/css/css-paint-api/style-background-image-ref.html
new file mode 100644
index 0000000000..ac936dd169
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/style-background-image-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100" style="margin-left: 2px"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 100);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/style-background-image.https.html b/testing/web-platform/tests/css/css-paint-api/style-background-image.https.html
new file mode 100644
index 0000000000..c36e50271b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/style-background-image.https.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="style-background-image-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+ margin-left: 2px;
+ --foo:bar;
+}
+
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() {
+ return [
+ '--bar',
+ '--foo',
+ 'empty-cells',
+ 'margin-left',
+ ];
+ }
+ paint(ctx, geom, styleMap) {
+ const properties = [...styleMap.keys()].sort();
+ var serializedStrings = [];
+ for (let i = 0; i < properties.length; i++) {
+ const value = styleMap.get(properties[i]);
+ let serialized;
+ if (value)
+ serialized = properties[i].toString() + ': [' + value.constructor.name + '=' + value.toString() + ']';
+ else
+ serialized = properties[i].toString() + ': [null]';
+ serializedStrings.push(serialized);
+ }
+ ctx.fillStyle = 'green';
+ if (serializedStrings[0] != "--bar: [CSSUnparsedValue=]")
+ ctx.fillStyle = 'red';
+ if (serializedStrings[1] != "--foo: [CSSUnparsedValue=bar]")
+ ctx.fillStyle = 'blue';
+ if (serializedStrings[2] != "empty-cells: [CSSKeywordValue=show]")
+ ctx.fillStyle = 'yellow';
+ if (serializedStrings[3] != "margin-left: [CSSUnitValue=2px]")
+ ctx.fillStyle = 'cyan';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/style-before-pseudo-ref.html b/testing/web-platform/tests/css/css-paint-api/style-before-pseudo-ref.html
new file mode 100644
index 0000000000..823fc257d4
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/style-before-pseudo-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+div {
+ margin-left: 3px;
+}
+div::before {
+ width: 100px;
+ height: 100px;
+ margin-left: 2px;
+ content: 'foo';
+ color: rgba(0, 0, 0, 0);
+}
+canvas{
+ margin-left: 2px;
+ display: block;
+ position: relative;
+ top: -1em;
+}
+</style>
+<body style="font: 10px/1 Ahem;">
+ <div><canvas width="30px" height="10px"></canvas></div>
+<script>
+document.addEventListener('DOMContentLoaded', function() {
+ var canvas = document.querySelector('canvas');
+ var context = canvas.getContext("2d");
+ context.fillStyle = 'green';
+ context.fillRect(0, 0, 30, 10);
+});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/style-before-pseudo.https.html b/testing/web-platform/tests/css/css-paint-api/style-before-pseudo.https.html
new file mode 100644
index 0000000000..cc569a4b8e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/style-before-pseudo.https.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="style-before-pseudo-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+div {
+ margin-left: 3px;
+}
+
+div::before {
+ width: 100px;
+ height: 100px;
+ content: 'foo';
+ color: rgba(0, 0, 0, 0);
+
+ background-image: paint(geometry);
+ margin-left: 2px;
+ --foo:bar;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body style="font: 10px/1 Ahem;">
+<div></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() {
+ return [
+ '--bar',
+ '--foo',
+ 'margin-left',
+ ];
+ }
+ paint(ctx, geom, styleMap) {
+ const properties = [...styleMap.keys()].sort();
+ var serializedStrings = [];
+ for (let i = 0; i < properties.length; i++) {
+ const value = styleMap.get(properties[i]);
+ let serialized;
+ if (value)
+ serialized = properties[i].toString() + ': [' + value.constructor.name + '=' + value.toString() + ']';
+ else
+ serialized = properties[i].toString() + ': [null]';
+ serializedStrings.push(serialized);
+ }
+ ctx.fillStyle = 'green';
+ if (serializedStrings[0] != "--bar: [CSSUnparsedValue=]")
+ ctx.fillStyle = 'red';
+ if (serializedStrings[1] != "--foo: [CSSUnparsedValue=bar]")
+ ctx.fillStyle = 'blue';
+ if (serializedStrings[2] != "margin-left: [CSSUnitValue=2px]")
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/style-first-letter-pseudo-ref.html b/testing/web-platform/tests/css/css-paint-api/style-first-letter-pseudo-ref.html
new file mode 100644
index 0000000000..8f337c5be8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/style-first-letter-pseudo-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+div {
+ color: rgb(0, 255, 0);
+ line-height: 2px;
+}
+
+div::first-letter {
+ color: rgb(255, 0, 0);
+}
+canvas{
+ position: absolute;
+ top: 4px;
+ z-index: -1;
+}
+</style>
+<body style="font: 10px/1 Ahem;">
+<div><canvas width="10px" height="10px"></canvas>ppp</div>
+<script>
+document.addEventListener('DOMContentLoaded', function() {
+ var canvas = document.querySelector('canvas');
+ var context = canvas.getContext("2d");
+ context.fillStyle = 'green';
+ context.fillRect(0, 0, 10, 10);
+});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/style-first-letter-pseudo.https.html b/testing/web-platform/tests/css/css-paint-api/style-first-letter-pseudo.https.html
new file mode 100644
index 0000000000..6789137803
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/style-first-letter-pseudo.https.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="style-first-letter-pseudo-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+div {
+ color: rgb(0, 255, 0);
+ line-height: 1px;
+ height: 10px;
+}
+
+div::first-letter {
+ background-image: paint(geometry);
+ color: rgb(255, 0, 0);
+ line-height: 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body style="font: 10px/1 Ahem;">
+<div>ppp</div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() {
+ return [
+ 'color',
+ 'line-height',
+ ];
+ }
+ paint(ctx, geom, styleMap) {
+ const properties = [...styleMap.keys()].sort();
+ var serializedStrings = [];
+ for (let i = 0; i < properties.length; i++) {
+ const value = styleMap.get(properties[i]);
+ let serialized;
+ if (value)
+ serialized = properties[i].toString() + ': [' + value.constructor.name + '=' + value.toString() + ']';
+ else
+ serialized = properties[i].toString() + ': [null]';
+ serializedStrings.push(serialized);
+ }
+ ctx.fillStyle = 'green';
+ if (serializedStrings[0] != "color: [CSSStyleValue=rgb(255, 0, 0)]")
+ ctx.fillStyle = 'red';
+ if (serializedStrings[1] != "line-height: [CSSUnitValue=2px]")
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/top-level-await-ref.html b/testing/web-platform/tests/css/css-paint-api/top-level-await-ref.html
new file mode 100644
index 0000000000..b135021a0a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/top-level-await-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<canvas id="output" width="100" height="100" style="background: blue;"></canvas>
+<script>
+"use strict";
+const canvas = document.getElementById('output');
+const ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'green';
+ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/css/css-paint-api/top-level-await.https.html b/testing/web-platform/tests/css/css-paint-api/top-level-await.https.html
new file mode 100644
index 0000000000..8a0855cc97
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/top-level-await.https.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://html.spec.whatwg.org/#calling-scripts">
+<link rel="match" href="top-level-await-ref.html">
+<style>
+#output {
+ width: 100px;
+ height: 100px;
+ background-image: paint(rects);
+ background-color: blue;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+// This will cause a syntax error, and the paint processor will never get registered, in browsers
+// without top-level await support.
+await 1;
+
+registerPaint('rects', class {
+ async paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+"use strict";
+importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
diff --git a/testing/web-platform/tests/css/css-paint-api/two-custom-property-animation-ref.html b/testing/web-platform/tests/css/css-paint-api/two-custom-property-animation-ref.html
new file mode 100644
index 0000000000..fa364bde34
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/two-custom-property-animation-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'blue';
+context.fillRect(0, 0, 100, 100);
+context.fillStyle = '#987664';
+context.fillRect(0, 0, 50, 50);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/two-custom-property-animation.https.html b/testing/web-platform/tests/css/css-paint-api/two-custom-property-animation.https.html
new file mode 100644
index 0000000000..6669076e90
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/two-custom-property-animation.https.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="two-custom-property-animation-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+}
+@keyframes expand {
+ 0% { --foo: 0; }
+ 100% { --foo: 100; }
+}
+@keyframes clr {
+ 0% { --bar: 0; }
+ 100% { --bar: 200; }
+}
+.animate {
+ background-image: paint(geometry);
+ /* Use a long animation that start at 50% progress where the slope of the
+ selected timing function is zero. By setting up the animation in this way,
+ we accommodate lengthy delays in running the test without a potential drift
+ in the animated property value. This is important for avoiding flakes,
+ especially on debug builds. The screenshots are taken as soon as the
+ animation is ready, thus the long animation duration has no bearing on
+ the actual duration of the test. */
+ animation: expand 1000000s cubic-bezier(0,1,1,0) -500000s, clr 1000000s cubic-bezier(0,1,1,0) -500000s;
+}
+
+#canvas-geometry {
+ background-color: blue;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--foo', '--bar']; }
+ paint(ctx, geom, properties) {
+ let fooValue = parseFloat(properties.get('--foo').toString());
+ let barValue = parseFloat(properties.get('--bar').toString());
+ let barString = barValue.toString(16);
+ if (barString.length == 1)
+ barString = '0' + barString;
+ ctx.fillStyle = '#9876' + barString;
+ ctx.fillRect(0, 0, fooValue, fooValue);
+ }
+});
+</script>
+
+<script>
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<number>',
+ initialValue: '0',
+ inherits: false
+});
+CSS.registerProperty({
+ name: '--bar',
+ syntax: '<number>',
+ initialValue: '0',
+ inherits: false
+});
+</script>
+
+<script>
+var blob = new Blob([document.getElementById('code').textContent],
+ {type: 'text/javascript'});
+CSS.paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+ document.getElementById('canvas-geometry').classList.add('animate');
+ const animations = document.getAnimations();
+ // Wait for the animation to start before completing the test.
+ document.getAnimations()[0].ready.then(() => {
+ takeScreenshot();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/two-element-custom-property-animation-ref.html b/testing/web-platform/tests/css/css-paint-api/two-element-custom-property-animation-ref.html
new file mode 100644
index 0000000000..37774e086f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/two-element-custom-property-animation-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="200" height="400"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 100);
+context.fillStyle = 'rgb(100, 100, 0)';
+context.fillRect(0, 200, 200, 200);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/two-element-custom-property-animation.https.html b/testing/web-platform/tests/css/css-paint-api/two-element-custom-property-animation.https.html
new file mode 100644
index 0000000000..48b0f201d4
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/two-element-custom-property-animation.https.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="two-element-custom-property-animation-ref.html">
+<style>
+#footainer {
+ width: 200px;
+ height: 200px;
+}
+.fooanimate {
+ background-image: paint(foo);
+ /* Use long animations that start at 50% progress where the slope of the
+ selected timing function is zero. By setting up the animations in this way,
+ we accommodate lengthy delays in running the test without a potential drift
+ in the animated properties values. This is important for avoiding flakes,
+ especially on debug builds. The screenshots are taken as soon as the
+ animations are ready, thus the long animation duration has no bearing on
+ the actual duration of the test. */
+ animation: expand 1000000s cubic-bezier(0,1,1,0) -500000s;
+}
+#bartainer {
+ width: 200px;
+ height: 200px;
+}
+.baranimate {
+ background-image: paint(bar);
+ animation: colorChange 1000000s cubic-bezier(0,1,1,0) -500000s;
+}
+@keyframes expand {
+ 0% { --foo: 0; }
+ 100% { --foo: 200; }
+}
+@keyframes colorChange {
+ 0% { --bar: rgb(200, 0, 0); }
+ 100% { --bar: rgb(0, 200, 0); }
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="footainer"></div>
+<div id="bartainer"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+ static get inputProperties() { return ['--foo']; }
+ paint(ctx, geom, properties) {
+ let fooValue = parseFloat(properties.get('--foo').toString());
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, fooValue, fooValue);
+ }
+});
+
+registerPaint('bar', class {
+ static get inputProperties() { return ['--bar']; }
+ paint(ctx, geom, properties) {
+ ctx.fillStyle = properties.get('--bar').toString();
+ ctx.fillRect(0, 0, 200, 200);
+ }
+});
+</script>
+
+<script type="text/javascript">
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<number>',
+ initialValue: '0',
+ inherits: false
+});
+CSS.registerProperty({
+ name: '--bar',
+ syntax: '<color>',
+ initialValue: 'rgb(0, 0, 0)',
+ inherits: false
+});
+</script>
+
+<script>
+var code = document.getElementById('code').textContent;
+var blob = new Blob([code], {type: 'text/javascript'});
+CSS.paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+ document.getElementById('footainer').classList.add('fooanimate');
+ document.getElementById('bartainer').classList.add('baranimate');
+ const animations = document.getAnimations();
+ // Wait for all animations to start before completing the test.
+ Promise.all([animations[0].ready, animations[1].ready]).then(() => {
+ takeScreenshot();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/two-element-one-custom-property-animation-ref.html b/testing/web-platform/tests/css/css-paint-api/two-element-one-custom-property-animation-ref.html
new file mode 100644
index 0000000000..530d3dc9a1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/two-element-one-custom-property-animation-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="200" height="400"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'rgb(100, 0, 100)';
+context.fillRect(0, 0, 200, 200);
+context.fillStyle = 'rgb(100, 100, 0)';
+context.fillRect(0, 200, 200, 200);
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/two-element-one-custom-property-animation.https.html b/testing/web-platform/tests/css/css-paint-api/two-element-one-custom-property-animation.https.html
new file mode 100644
index 0000000000..1090185409
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/two-element-one-custom-property-animation.https.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="two-element-one-custom-property-animation-ref.html">
+<style>
+#footainer1 {
+ width: 200px;
+ height: 200px;
+}
+.fooanimate1 {
+ background-image: paint(foo);
+ /* Use long animations that start at 50% progress where the slope of the
+ selected timing function is zero. By setting up the animations in this way,
+ we accommodate lengthy delays in running the test without a potential drift
+ in the animated properties values. This is important for avoiding flakes,
+ especially on debug builds. The screenshots are taken as soon as the
+ animations are ready, thus the long animation duration has no bearing on
+ the actual duration of the test. */
+ animation: anim1 1000000s cubic-bezier(0,1,1,0);
+ animation-delay: -500000s;
+}
+#footainer2 {
+ width: 200px;
+ height: 200px;
+}
+.fooanimate2 {
+ background-image: paint(foo);
+ animation: anim2 1000000s cubic-bezier(0,1,1,0);
+ animation-delay: -500000s;
+}
+@keyframes anim1 {
+ 0% { --foo: rgb(200, 0, 0); }
+ 100% { --foo: rgb(0, 0, 200); }
+}
+@keyframes anim2 {
+ 0% { --foo: rgb(200, 0, 0); }
+ 100% { --foo: rgb(0, 200, 0); }
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="footainer1"></div>
+<div id="footainer2"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+ static get inputProperties() { return ['--foo']; }
+ paint(ctx, geom, properties) {
+ ctx.fillStyle = properties.get('--foo').toString();
+ ctx.fillRect(0, 0, 200, 200);
+ }
+});
+</script>
+
+<script type="text/javascript">
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<color>',
+ initialValue: 'rgb(0, 0, 0)',
+ inherits: false
+});
+</script>
+
+<script>
+var code = document.getElementById('code').textContent;
+var blob = new Blob([code], {type: 'text/javascript'});
+CSS.paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+ document.getElementById('footainer1').classList.add('fooanimate1');
+ document.getElementById('footainer2').classList.add('fooanimate2');
+ const animations = document.getAnimations();
+ // Wait for all animations to start before completing the test.
+ Promise.all([animations[0].ready, animations[1].ready]).then(() => {
+ takeScreenshot();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/valid-image-after-load-ref.html b/testing/web-platform/tests/css/css-paint-api/valid-image-after-load-ref.html
new file mode 100644
index 0000000000..67f5751283
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/valid-image-after-load-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 100);
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-paint-api/valid-image-after-load.https.html b/testing/web-platform/tests/css/css-paint-api/valid-image-after-load.https.html
new file mode 100644
index 0000000000..c1bf8e8554
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/valid-image-after-load.https.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="valid-image-after-load-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('green', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+var blob = new Blob([document.getElementById('code').textContent],
+ {type: 'text/javascript'});
+var frame_cnt = 0;
+CSS.paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+ var el = document.getElementById('output');
+ el.style.backgroundImage = 'paint(green)';
+ requestAnimationFrame(function() {
+ takeScreenshot(frame_cnt);
+ });
+});
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-paint-api/valid-image-before-load-ref.html b/testing/web-platform/tests/css/css-paint-api/valid-image-before-load-ref.html
new file mode 100644
index 0000000000..67f5751283
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/valid-image-before-load-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 100);
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-paint-api/valid-image-before-load.https.html b/testing/web-platform/tests/css/css-paint-api/valid-image-before-load.https.html
new file mode 100644
index 0000000000..b58dfa114e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/valid-image-before-load.https.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="valid-image-before-load-ref.html">
+<style>
+ #output {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<body>
+<div id="output"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('green', class {
+ paint(ctx, geom) {
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+var el = document.getElementById('output');
+el.style.backgroundImage = 'paint(green)';
+
+var blob = new Blob([document.getElementById('code').textContent],
+ {type: 'text/javascript'});
+var frame_cnt = 0;
+CSS.paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
+ requestAnimationFrame(function() {
+ takeScreenshot(frame_cnt);
+ });
+});
+</script>
+</body>
+</html>