Check that calling transferToImageBitmap in a layer throws an exception.
+
+
+
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.transferToImageBitmap.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.transferToImageBitmap.worker.js
new file mode 100644
index 0000000000000..073a3e84a486a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.transferToImageBitmap.worker.js
@@ -0,0 +1,29 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.transferToImageBitmap
+// Description:Check that calling transferToImageBitmap in a layer throws an exception.
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("Check that calling transferToImageBitmap in a layer throws an exception.");
+var t_pass = t.done.bind(t);
+var t_fail = t.step_func(function(reason) {
+ throw reason;
+});
+t.step(function() {
+
+ var canvas = new OffscreenCanvas(100, 50);
+ var ctx = canvas.getContext('2d');
+
+ // `transferToImageBitmap` shouldn't throw on it's own.
+ canvas.transferToImageBitmap();
+ // Make sure the exception isn't caused by calling the function twice.
+ canvas.transferToImageBitmap();
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ assert_throws_dom("InvalidStateError",
+ () => canvas.transferToImageBitmap());
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.unclosed-nested.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.unclosed-nested.w.html
index dd1c36ea47197..e330e1710cf48 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.unclosed-nested.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.unclosed-nested.w.html
@@ -13,20 +13,29 @@
2d.layer.unclosed-nested
const canvas = new OffscreenCanvas(200, 200);
const ctx = canvas.getContext('2d');
- ctx.fillStyle = 'rgba(0, 0, 255, 1)';
- ctx.fillRect(60, 60, 75, 50);
- ctx.globalAlpha = 0.5;
+ // `transferToImageBitmap` is used to transfer the test result to the
+ // worker's parent, but `transferToImageBitmap` can't be called on canvas
+ // with unclosed layers. We can however draw to a separate offscreen canvas
+ // and write it to the main canvas using `drawImage`.
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
- ctx.beginLayer();
- ctx.fillStyle = 'rgba(225, 0, 0, 1)';
- ctx.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx2.fillRect(60, 60, 75, 50);
+ ctx2.globalAlpha = 0.5;
- ctx.beginLayer();
- ctx.fillStyle = 'rgba(0, 255, 0, 1)';
- ctx.fillRect(70, 70, 75, 50);
+ ctx2.beginLayer();
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
- ctx.endLayer();
- // Missing ctx.endLayer() here.
+ ctx2.beginLayer();
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx2.endLayer();
+ // Missing ctx2.endLayer() here.
+
+ ctx.drawImage(canvas2, 0, 0);
const bitmap = canvas.transferToImageBitmap();
self.postMessage(bitmap, bitmap);
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.unclosed.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.unclosed.w.html
index 830dea7e3d116..1da44c26c8661 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.unclosed.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.unclosed.w.html
@@ -13,14 +13,23 @@
2d.layer.unclosed
const canvas = new OffscreenCanvas(200, 200);
const ctx = canvas.getContext('2d');
- ctx.fillStyle = 'purple';
- ctx.fillRect(60, 60, 75, 50);
- ctx.globalAlpha = 0.5;
+ // `transferToImageBitmap` is used to transfer the test result to the
+ // worker's parent, but `transferToImageBitmap` can't be called on canvas
+ // with unclosed layers. We can however draw to a separate offscreen canvas
+ // and write it to the main canvas using `drawImage`.
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
- ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}});
- ctx.fillRect(40, 40, 75, 50);
- ctx.fillStyle = 'grey';
- ctx.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'purple';
+ ctx2.fillRect(60, 60, 75, 50);
+ ctx2.globalAlpha = 0.5;
+
+ ctx2.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}});
+ ctx2.fillRect(40, 40, 75, 50);
+ ctx2.fillStyle = 'grey';
+ ctx2.fillRect(50, 50, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
const bitmap = canvas.transferToImageBitmap();
self.postMessage(bitmap, bitmap);
diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/layers.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/layers.yaml
index 9145108bd3c27..41cd2ddfb3d88 100644
--- a/testing/web-platform/tests/html/canvas/tools/yaml-new/layers.yaml
+++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/layers.yaml
@@ -312,14 +312,29 @@
desc: Check that layers are rendered even if not closed.
size: [200, 200]
code: |
- ctx.fillStyle = 'purple';
- ctx.fillRect(60, 60, 75, 50);
- ctx.globalAlpha = 0.5;
+ {% set ns = namespace(ctx='ctx') %}
+ {% if canvas_type == 'worker' %}
+ // `transferToImageBitmap` is used to transfer the test result to the
+ // worker's parent, but `transferToImageBitmap` can't be called on canvas
+ // with unclosed layers. We can however draw to a separate offscreen canvas
+ // and write it to the main canvas using `drawImage`.
+ const canvas2 = new OffscreenCanvas({{ size[0] }}, {{ size[1] }});
+ const ctx2 = canvas2.getContext('2d');
+ {% set ns.ctx = 'ctx2' %}
+ {% endif %}
- ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}});
- ctx.fillRect(40, 40, 75, 50);
- ctx.fillStyle = 'grey';
- ctx.fillRect(50, 50, 75, 50);
+ {{ ns.ctx }}.fillStyle = 'purple';
+ {{ ns.ctx }}.fillRect(60, 60, 75, 50);
+ {{ ns.ctx }}.globalAlpha = 0.5;
+
+ {{ ns.ctx }}.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}});
+ {{ ns.ctx }}.fillRect(40, 40, 75, 50);
+ {{ ns.ctx }}.fillStyle = 'grey';
+ {{ ns.ctx }}.fillRect(50, 50, 75, 50);
+
+ {% if canvas_type == 'worker' %}
+ ctx.drawImage(canvas2, 0, 0);
+ {% endif %}
reference: |
ctx.fillStyle = 'purple';
ctx.fillRect(60, 60, 75, 50);
@@ -336,20 +351,35 @@
desc: Check that layers are rendered even if not closed.
size: [200, 200]
code: |
- ctx.fillStyle = 'rgba(0, 0, 255, 1)';
- ctx.fillRect(60, 60, 75, 50);
- ctx.globalAlpha = 0.5;
+ {% set ns = namespace(ctx='ctx') %}
+ {% if canvas_type == 'worker' %}
+ // `transferToImageBitmap` is used to transfer the test result to the
+ // worker's parent, but `transferToImageBitmap` can't be called on canvas
+ // with unclosed layers. We can however draw to a separate offscreen canvas
+ // and write it to the main canvas using `drawImage`.
+ const canvas2 = new OffscreenCanvas({{ size[0] }}, {{ size[1] }});
+ const ctx2 = canvas2.getContext('2d');
+ {% set ns.ctx = 'ctx2' %}
+ {% endif %}
- ctx.beginLayer();
- ctx.fillStyle = 'rgba(225, 0, 0, 1)';
- ctx.fillRect(50, 50, 75, 50);
+ {{ ns.ctx }}.fillStyle = 'rgba(0, 0, 255, 1)';
+ {{ ns.ctx }}.fillRect(60, 60, 75, 50);
+ {{ ns.ctx }}.globalAlpha = 0.5;
- ctx.beginLayer();
- ctx.fillStyle = 'rgba(0, 255, 0, 1)';
- ctx.fillRect(70, 70, 75, 50);
+ {{ ns.ctx }}.beginLayer();
+ {{ ns.ctx }}.fillStyle = 'rgba(225, 0, 0, 1)';
+ {{ ns.ctx }}.fillRect(50, 50, 75, 50);
- ctx.endLayer();
- // Missing ctx.endLayer() here.
+ {{ ns.ctx }}.beginLayer();
+ {{ ns.ctx }}.fillStyle = 'rgba(0, 255, 0, 1)';
+ {{ ns.ctx }}.fillRect(70, 70, 75, 50);
+
+ {{ ns.ctx }}.endLayer();
+ // Missing {{ ns.ctx }}.endLayer() here.
+
+ {% if canvas_type == 'worker' %}
+ ctx.drawImage(canvas2, 0, 0);
+ {% endif %}
reference: |
const canvas1 = document.createElement('canvas');
const ctx1 = canvas1.getContext('2d');
@@ -443,44 +473,18 @@
canvasType: ['HTMLCanvas']
flush_canvas: canvas.toDataURL();
-
-- name: 2d.layer.render-opportunities.transferToImageBitmap
- desc: Checks that transferToImageBitmap flushes and rebuilds the state stack.
- size: [200, 200]
+- name: 2d.layer.transferToImageBitmap
+ desc: Check that calling transferToImageBitmap in a layer throws an exception.
canvasType: ['OffscreenCanvas', 'Worker']
code: |
- ctx.fillStyle = 'purple';
- ctx.fillRect(60, 60, 75, 50);
- ctx.globalAlpha = 0.5;
-
- ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}});
- ctx.fillRect(40, 40, 75, 50);
- ctx.fillStyle = 'grey';
- ctx.fillRect(50, 50, 75, 50);
-
- // Force a flush and restoration of the state stack.
- // `transferToImageBitmap` clears the frame but preserves render states.
+ // `transferToImageBitmap` shouldn't throw on it's own.
canvas.transferToImageBitmap();
-
- ctx.fillRect(70, 70, 75, 50);
- ctx.fillStyle = 'orange';
- ctx.fillRect(80, 80, 75, 50);
- ctx.endLayer();
-
- ctx.fillRect(80, 40, 75, 50);
- reference: |
- ctx.fillStyle = 'purple';
- ctx.globalAlpha = 0.5;
-
- ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}});
- ctx.fillStyle = 'grey';
- ctx.fillRect(70, 70, 75, 50);
- ctx.fillStyle = 'orange';
- ctx.fillRect(80, 80, 75, 50);
- ctx.endLayer();
-
- ctx.fillRect(80, 40, 75, 50);
-
+ // Make sure the exception isn't caused by calling the function twice.
+ canvas.transferToImageBitmap();
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ assert_throws_dom("InvalidStateError",
+ () => canvas.transferToImageBitmap());
- name: 2d.layer.several-complex
desc: >-