summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html')
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/disable_bfcache.js15
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor-pushstate.html1
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.html1
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.js17
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js5
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-cross-origin.sub.html65
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-iframe.html45
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-initial-navigation.html35
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-from-click.html74
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation-hidden-document.html68
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation.html64
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-cross-origin-redirect.sub.html69
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-redirect.html64
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-reload-navigation.html65
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-navigation.html64
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-with-cross-origin-redirect.sub.html69
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-cross-origin-redirect-no-bfcache.https.sub.html77
-rw-r--r--testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-no-bfcache.https.html75
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer-1.html16
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer-2.html56
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer.html26
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-location-interface/assign-replace-from-iframe.html31
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-location-interface/assign-replace-from-top-to-nested-iframe.html36
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-location-interface/assign-with-nested-iframe.html21
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-location-interface/replace-with-nested-iframe.html21
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-contents.sub.html14
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-postmessage-to-parent-parent.sub.html14
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-with-iframe.html9
-rw-r--r--testing/web-platform/tests/html/browsers/history/the-location-interface/resources/replace-or-assign-call-on-iframe.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/drawing-images-to-the-canvas/2d.drawImage.detachedcanvas.html28
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.html22
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.html69
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.html49
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html44
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.html49
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html43
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.html40
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html51
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.html49
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.html48
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.html320
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html56
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html (renamed from testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic-expected.html)4
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html (renamed from testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x-expected.html)4
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html (renamed from testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html (renamed from testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y-expected.html)4
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html (renamed from testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only-expected.html)4
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html (renamed from testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html (renamed from testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only-expected.html)4
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html (renamed from testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.html4
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.blur.exceptions.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.colorMatrix.html104
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.discrete-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.discrete.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.gamma-expected.html44
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.gamma.html41
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.identity-expected.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.identity.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.linear-expected.html44
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.linear.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.table-expected.html51
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.table.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.convolveMatrix.exceptions.html60
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow-expected.html57
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow.exceptions.html269
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow.html94
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic-expected.html)4
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.turbulence.inputTypes.html130
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.filter-expected.html25
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.filter.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.getTransform.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.resetTransform-expected.html19
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.resetTransform.html28
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.setTransform-expected.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.setTransform.html28
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.shadow-in-transformed-layer-expected.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.shadow-in-transformed-layer.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.drawImage-expected.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.drawImage.html33
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html1
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html1
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html1
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html1
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html14
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.html22
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.worker.js22
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.html69
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.worker.js69
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.html53
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.w.html54
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.worker.js62
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html44
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.html53
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.w.html57
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.worker.js53
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html27
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.html35
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.w.html50
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.worker.js40
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html43
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.html44
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.w.html53
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.worker.js52
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.html53
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.w.html54
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.worker.js62
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.html48
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.worker.js48
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.html320
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.worker.js320
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html56
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.w.html56
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.w.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic.w.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html (renamed from testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x-expected.html)4
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.w.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x.w.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y-expected.html)4
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.w.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y.w.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html (renamed from testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only-expected.html)4
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.w.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only.w.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only-expected.html)4
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.w.html (renamed from testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only.w.html)6
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.html4
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.worker.js4
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.blur.exceptions.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.blur.exceptions.worker.js33
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.colorMatrix.html105
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.colorMatrix.worker.js100
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete.html41
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete.w.html55
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma-expected.html44
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma.html44
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma.w.html58
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity-expected.html27
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity.html37
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity.w.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear-expected.html44
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear.html40
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear.w.html54
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table-expected.html51
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table.html41
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table.w.html55
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.convolveMatrix.exceptions.html61
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.convolveMatrix.exceptions.worker.js56
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow-expected.html57
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.exceptions.html270
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.exceptions.worker.js265
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.html97
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.w.html111
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.w.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.w.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.w.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.w.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.html24
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.w.html38
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.turbulence.inputTypes.html131
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.turbulence.inputTypes.worker.js126
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter-expected.html25
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter.html32
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter.w.html46
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.html32
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.worker.js27
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform-expected.html19
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform.w.html45
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform-expected.html20
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform.html31
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform.w.html45
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer-expected.html27
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer.html34
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer.w.html48
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage-expected.html29
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage.html36
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage.w.html50
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.html1
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.w.html1
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.html1
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.w.html1
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html1
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.html1
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html1
-rw-r--r--testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html1
-rw-r--r--testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py213
-rw-r--r--testing/web-platform/tests/html/canvas/tools/name2dir-offscreen.yaml2
-rw-r--r--testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml8
-rw-r--r--testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml706
-rw-r--r--testing/web-platform/tests/html/canvas/tools/yaml-new/layers.yaml204
-rw-r--r--testing/web-platform/tests/html/dom/elements/global-attributes/dir-assorted.window.js5
-rw-r--r--testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-dataChange.html31
-rw-r--r--testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-ref.html13
-rw-r--r--testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-replace.html32
-rw-r--r--testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-textContent.html31
-rw-r--r--testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-41-ref.html2
-rw-r--r--testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-42-ref.html25
-rw-r--r--testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-42.html33
-rw-r--r--testing/web-platform/tests/html/dom/elements/global-attributes/dir_auto-N-EN-ref.html6
-rw-r--r--testing/web-platform/tests/html/dom/elements/global-attributes/dir_auto-N-EN.html4
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-001.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-001.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-002.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-002.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-003.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-003.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-004.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-004.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-005.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-005.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-006.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-006.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-007.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-007.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-008.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-008.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-009.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-009.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-010.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-010.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-011.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-011.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-012.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-012.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-013.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-013.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-014.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-014.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-015.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-015.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-016.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-016.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-017.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-017.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-018.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-018.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-019.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-019.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-020.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-020.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-021.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-021.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-022.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-022.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-023.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-023.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-024.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-024.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-025.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-025.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-026.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-026.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-027.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-027.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-028.html (renamed from testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-028.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-029.html29
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-030.html34
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-031.html32
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-032.html34
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-033.html30
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-034.html30
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-035.html31
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-036.html31
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-037.html31
-rw-r--r--testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-038.html35
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/writing-suggestions/writingsuggestions.html182
-rw-r--r--testing/web-platform/tests/html/rendering/bidi-rendering/unicode-bidi-ua-rules.html88
-rw-r--r--testing/web-platform/tests/html/rendering/non-replaced-elements/sections-and-headings/headings-styles-no-h1-in-section.tentative.html147
-rw-r--r--testing/web-platform/tests/html/rendering/non-replaced-elements/sections-and-headings/headings-styles.html22
-rw-r--r--testing/web-platform/tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-overflow.html1
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-button-min-height-001-ref.html11
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-button-min-height-001.html15
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/field-sizing-textarea.html4
-rw-r--r--testing/web-platform/tests/html/resources/common.js6
-rw-r--r--testing/web-platform/tests/html/semantics/disabled-elements/event-propagate-disabled.tentative.html1
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/302-no-Location-header-text-css.asis4
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css0
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css.headers1
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css.headers1
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-bad-mime-type.html27
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-non-OK-status.html17
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime-move-within-document.html31
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-scroller-nested-2.html2
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.https.html (renamed from testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.https.html (renamed from testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.html)0
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.sub.js (renamed from testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.js)18
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin.tentative.sub.window.js28
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js2
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-site.tentative.sub.window.js43
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js2
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js2
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation.tentative.sub.window.js (renamed from testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js)21
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-attribute-crash.html18
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-invalidation.tentative.html23
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist.tentative.html2
-rw-r--r--testing/web-platform/tests/html/semantics/forms/the-select-element/select-datalist-options-idl.tentative.html81
-rw-r--r--testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html1
-rw-r--r--testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-open.html4
-rw-r--r--testing/web-platform/tests/html/semantics/interactive-elements/the-summary-element/interactive-content.html232
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/interestelement-interface.tentative.html164
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/invokeelement-interface.tentative.html16
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/invokeevent-interface.tentative.html6
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html8
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-behavior.tentative.html455
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html64
-rw-r--r--testing/web-platform/tests/html/semantics/invokers/resources/invoker-utils.js8
-rw-r--r--testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.html38
-rw-r--r--testing/web-platform/tests/html/semantics/permission-element/invalid-css-properties.html34
-rw-r--r--testing/web-platform/tests/html/semantics/permission-element/negative-offset-and-margin.html67
-rw-r--r--testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html99
-rw-r--r--testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html94
-rw-r--r--testing/web-platform/tests/html/semantics/popovers/popovertarget-reflection.html8
-rw-r--r--testing/web-platform/tests/html/semantics/popovers/resources/popover-utils.js8
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html2
-rw-r--r--testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html2
-rw-r--r--testing/web-platform/tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html4
-rwxr-xr-xtesting/web-platform/tests/html/syntax/speculative-parsing/tools/generate.py2
-rw-r--r--testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.https.html8
330 files changed, 11111 insertions, 1720 deletions
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/disable_bfcache.js b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/disable_bfcache.js
new file mode 100644
index 0000000000..dea70ef4bd
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/disable_bfcache.js
@@ -0,0 +1,15 @@
+// Try to disable BFCache by acquiring and never releasing a Web Lock.
+// This requires HTTPS.
+// Note: This is a workaround depending on non-specified WebLock+BFCache
+// behavior, and doesn't work on Safari. We might want to introduce a
+// test-only BFCache-disabling API instead in the future.
+// https://github.com/web-platform-tests/wpt/issues/16359#issuecomment-795004780
+// https://crbug.com/1298336
+window.disableBFCache = () => {
+ return new Promise(resolve => {
+ navigator.locks.request("disablebfcache", () => {
+ resolve();
+ return new Promise(() => {});
+ });
+ });
+};
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor-pushstate.html b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor-pushstate.html
index dcf4a798d0..3dd8f341f1 100644
--- a/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor-pushstate.html
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor-pushstate.html
@@ -11,3 +11,4 @@
window.isLoadedFromPushState = true;
</script>
<script src="executor.js" type="module"></script>
+<script src="disable_bfcache.js" type="module"></script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.html b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.html
index 2d118bbe2b..c3af5f6ba8 100644
--- a/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.html
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.html
@@ -3,3 +3,4 @@
<script src="event-recorder.js" type="module"></script>
<script src="worker-helper.js" type="module"></script>
<script src="executor.js" type="module"></script>
+<script src="disable_bfcache.js" type="module"></script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.js b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.js
index 67ce068130..5137616d85 100644
--- a/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.js
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/executor.js
@@ -45,20 +45,3 @@ window.prepareNavigation = function(callback) {
{once: true});
executor.suspend(callback);
}
-
-// Try to disable BFCache by acquiring and never releasing a Web Lock.
-// This requires HTTPS.
-// Note: This is a workaround depending on non-specified WebLock+BFCache
-// behavior, and doesn't work on Safari. We might want to introduce a
-// test-only BFCache-disabling API instead in the future.
-// https://github.com/web-platform-tests/wpt/issues/16359#issuecomment-795004780
-// https://crbug.com/1298336
-window.disableBFCache = () => {
- return new Promise(resolve => {
- // Use page's UUID as a unique lock name.
- navigator.locks.request(uuid, () => {
- resolve();
- return new Promise(() => {});
- });
- });
-};
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js
index 80c164f560..ad2119b738 100644
--- a/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js
@@ -41,13 +41,14 @@ function sorted(s) {
return Array.from(s).sort();
}
-// Assert expected reasons and the reported reasons match.
+// Assert expected reasons are all present. Note that the extra reasons are allowed
+// as UAs might block bfcache for their specific reasons.
function matchReasons(expectedNotRestoredReasonsSet, notRestoredReasonsSet) {
const missing = setMinus(
expectedNotRestoredReasonsSet, notRestoredReasonsSet, 'Missing reasons');
const extra = setMinus(
notRestoredReasonsSet, expectedNotRestoredReasonsSet, 'Extra reasons');
- assert_true(missing.size + extra.size == 0, `Expected: ${sorted(expectedNotRestoredReasonsSet)}\n` +
+ assert_true(missing.size == 0, `Expected: ${sorted(expectedNotRestoredReasonsSet)}\n` +
`Got: ${sorted(notRestoredReasonsSet)}\n` +
`Missing: ${sorted(missing)}\n` +
`Extra: ${sorted(extra)}\n`);
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-cross-origin.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-cross-origin.sub.html
new file mode 100644
index 0000000000..4b68c32378
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-cross-origin.sub.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<title>Tests pageswap for cross-origin navigations</title>
+<link rel="author" title="Khushal Sagar" href="mailto:khushalsagar@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script>
+const expectedUrl = get_host_info().HTTPS_REMOTE_ORIGIN + "/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-cross-origin.sub.html?new";
+
+const params = new URLSearchParams(location.search);
+// The page the popup navigates to.
+const is_new_page = params.has('new');
+// The initial page in the popup.
+const is_popup_page = params.has('popup');
+// The test page itself.
+const is_test_page = !is_popup_page && !is_new_page;
+
+const channel = new BroadcastChannel("testchannel");
+
+if (is_test_page) {
+ const expectedUrl = location.href + "?new";
+ const expectedEvents = ["pageswap", "pagehide"];
+
+ promise_test(async t => {
+ let popup;
+ onload = () => {
+ window.events = [];
+ popup = window.open("?popup");
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on navigation from script`);
+} else if (is_popup_page) {
+ onload = () => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ location.href = expectedUrl;
+ }));
+
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.activation != null)
+ window.opener.events.push("activation");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ channel.postMessage("nav");
+ };
+ };
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-iframe.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-iframe.html
new file mode 100644
index 0000000000..05ca1a9428
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-iframe.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<title>Tests pageswap dispatch on iframe Documents</title>
+<link rel="author" title="Khushal Sagar" href="mailto:khushalsagar@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script>
+setup({explicit_done: true});
+
+function runTest(frame) {
+ let frameWindow = frame.contentWindow;
+
+ let pageswapfired = false;
+ let expectedUrl = frameWindow.location.href + '?new';
+ frameWindow.onpageswap = (e) => {
+ assert_equals(e.activation.entry.url, expectedUrl, 'activation url incorrect in pageswap');
+ assert_equals(e.activation.navigationType, "push", 'navigation type incorrect in pageswap');
+ assert_equals(e.activation.from, frameWindow.navigation.currentEntry, 'from entry incorrect in pageswap');
+ assert_false(e.activation.entry.sameDocument, 'new entry must be cross-document');
+ pageswapfired = true;
+ }
+
+ frameWindow.onpagehide = (e) => {
+ assert_true(pageswapfired, 'pageswap not fired');
+ done();
+ }
+
+ frame.src = expectedUrl;
+}
+
+promise_test(async t => {
+ onload = () => {
+ let frame = document.createElement('iframe');
+ frame.src = "/resources/blank.html";
+ frame.onload = () => {
+ frame.contentWindow.requestAnimationFrame(() => {
+ runTest(frame);
+ });
+ }
+ document.body.appendChild(frame);
+ };
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-initial-navigation.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-initial-navigation.html
new file mode 100644
index 0000000000..5483b9394d
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-initial-navigation.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<title>Tests pageswap dispatch on initial doc navigation</title>
+<link rel="author" title="Khushal Sagar" href="mailto:khushalsagar@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script>
+setup({explicit_done: true});
+
+function runTest(frame) {
+ let frameWindow = frame.contentWindow;
+
+ let pageswapfired = false;
+ frameWindow.onpageswap = (e) => {
+ pageswapfired = true;
+ }
+
+ frameWindow.onpagehide = (e) => {
+ assert_true(pageswapfired, 'pageswap fired');
+ done();
+ }
+
+ frame.srcdoc = '<html></html>';
+}
+
+promise_test(async t => {
+ onload = () => {
+ let frame = document.createElement('iframe');
+ document.body.appendChild(frame);
+ runTest(frame);
+ };
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-from-click.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-from-click.html
new file mode 100644
index 0000000000..936158cd47
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-from-click.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<title>pageswap navigationactivation for push navigations from user click</title>
+<link rel="help" href="https://html.spec.whatwg.org/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script>
+const expectedUrl = location.href + '?new';
+
+const params = new URLSearchParams(location.search);
+// The page the popup navigates to.
+const is_new_page = params.has('new');
+// The initial page in the popup.
+const is_popup_page = params.has('popup');
+// The test page itself.
+const is_test_page = !is_popup_page && !is_new_page;
+
+const channel = new BroadcastChannel("testchannel");
+
+if (is_test_page) {
+ const expectedUrl = location.href + "?new";
+ const expectedEvents = ["pageswap", expectedUrl, "push","from", "pagehide"];
+
+ promise_test(async t => {
+ let popup;
+ onload = () => {
+ document.getElementById('nav_link').remove();
+ window.events = [];
+ popup = window.open("?popup");
+
+ popup.addEventListener("load", () => {
+ popup.requestAnimationFrame(
+ () => popup.requestAnimationFrame(() => {
+ let nav_link = popup.document.getElementById('nav_link');
+ test_driver
+ .click(nav_link)
+ .catch(() => assert_unreached("click failed"));
+ }));
+ });
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on navigation from user click`);
+} else if (is_popup_page) {
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ window.opener.events.push(e.activation.entry.url);
+ window.opener.events.push(e.activation.navigationType);
+ if (e.activation.from == navigation.currentEntry)
+ window.opener.events.push("from");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ channel.postMessage("nav");
+ };
+}
+</script>
+<body>
+ <a id="nav_link" href='/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-from-click.html?new'>Click me</a>
+ </body>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation-hidden-document.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation-hidden-document.html
new file mode 100644
index 0000000000..0a699232f0
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation-hidden-document.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<title>Tests pageswap dispatch on hidden Documents</title>
+<link rel="author" title="Khushal Sagar" href="mailto:khushalsagar@chromium.org">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script>
+const expectedUrl = location.href + '?new';
+
+const params = new URLSearchParams(location.search);
+// The page the popup navigates to.
+const is_new_page = params.has('new');
+// The initial page in the popup.
+const is_popup_page = params.has('popup');
+// The test page itself.
+const is_test_page = !is_popup_page && !is_new_page;
+
+const channel = new BroadcastChannel("testchannel");
+
+if (is_test_page) {
+ const expectedUrl = location.href + "?new";
+ const expectedEvents = ["pageswap", expectedUrl, "push","from", "pagehide"];
+
+ promise_test(async t => {
+ let popup;
+ onload = async () => {
+ window.events = [];
+ popup = window.open("?popup");
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on navigation from script`);
+} else if (is_popup_page) {
+ onload = async () => {
+ await test_driver.minimize_window();
+ assert_equals(document.visibilityState, "hidden");
+ assert_equals(document.hidden, true);
+
+ location.href = location.href.split('?')[0] + '?new';
+ };
+
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ window.opener.events.push(e.activation.entry.url);
+ window.opener.events.push(e.activation.navigationType);
+ if (e.activation.from == navigation.currentEntry)
+ window.opener.events.push("from");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ channel.postMessage("nav");
+ };
+ }
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation.html
new file mode 100644
index 0000000000..4542d7cae2
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-navigation.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<title>pageswap navigationactivation for push navigations</title>
+<link rel="help" href="https://html.spec.whatwg.org/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const expectedUrl = location.href + '?new';
+
+const params = new URLSearchParams(location.search);
+// The page the popup navigates to.
+const is_new_page = params.has('new');
+// The initial page in the popup.
+const is_popup_page = params.has('popup');
+// The test page itself.
+const is_test_page = !is_popup_page && !is_new_page;
+
+const channel = new BroadcastChannel("testchannel");
+
+if (is_test_page) {
+ const expectedUrl = location.href + "?new";
+ const expectedEvents = ["pageswap", expectedUrl, "push","from", "pagehide"];
+
+ promise_test(async t => {
+ let popup;
+ onload = () => {
+ window.events = [];
+ popup = window.open("?popup");
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on navigation from script`);
+} else if (is_popup_page) {
+ onload = () => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ location.href = location.href.split('?')[0] + '?new';
+ }));
+
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ window.opener.events.push(e.activation.entry.url);
+ window.opener.events.push(e.activation.navigationType);
+ if (e.activation.from == navigation.currentEntry)
+ window.opener.events.push("from");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ channel.postMessage("nav");
+ };
+ };
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-cross-origin-redirect.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-cross-origin-redirect.sub.html
new file mode 100644
index 0000000000..8ecf920b51
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-cross-origin-redirect.sub.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<title>pageswap navigationactivation for push navigations with a same-origin final url with cross-origin redirects</title>
+<link rel="help" href="https://html.spec.whatwg.org/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script>
+const params = new URLSearchParams(location.search);
+// The page the popup navigates to.
+const is_new_page = params.has('new');
+// The initial page in the popup.
+const is_popup_page = params.has('popup');
+// The test page itself.
+const is_test_page = !is_popup_page && !is_new_page;
+
+const channel = new BroadcastChannel("testchannel");
+
+if (is_test_page) {
+ const expectedUrl = location.href + "?new";
+ const expectedEvents = ["pageswap", "pagehide", "pagereveal", "activation"];
+
+ promise_test(async t => {
+ let popup;
+ onload = () => {
+ window.events = [];
+ popup = window.open("?popup");
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on navigation with same-origin redirect`);
+} else if (is_popup_page) {
+ onload = () => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ let newUrl = get_host_info().HTTPS_REMOTE_ORIGIN + "/common/redirect.py?location=" + location.href.split('?')[0] + "?new";
+ location.href = newUrl
+ }));
+
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ if (e.activation != null)
+ window.opener.events.push("activation");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ };
+ };
+} else {
+ assert_true(is_new_page);
+ onpageshow = () => {
+ window.opener.events.push("pagereveal");
+ if (navigation.activation.from != null)
+ window.opener.events.push("activation");
+ channel.postMessage("nav");
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-redirect.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-redirect.html
new file mode 100644
index 0000000000..8252fff84d
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-redirect.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<title>pageswap navigationactivation for push navigations with a same-origin redirect</title>
+<link rel="help" href="https://html.spec.whatwg.org/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const expectedUrl = location.href + '?new';
+
+const params = new URLSearchParams(location.search);
+// The page the popup navigates to.
+const is_new_page = params.has('new');
+// The initial page in the popup.
+const is_popup_page = params.has('popup');
+// The test page itself.
+const is_test_page = !is_popup_page && !is_new_page;
+
+const channel = new BroadcastChannel("testchannel");
+
+if (is_test_page) {
+ const expectedUrl = location.href + "?new";
+ const expectedEvents = ["pageswap", expectedUrl, "push","from", "pagehide"];
+
+ promise_test(async t => {
+ let popup;
+ onload = () => {
+ window.events = [];
+ popup = window.open("?popup");
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on navigation with same-origin redirect`);
+} else if (is_popup_page) {
+ onload = () => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ location.href = "/common/redirect.py?location=/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-push-with-redirect.html?new";
+ }));
+
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ window.opener.events.push(e.activation.entry.url);
+ window.opener.events.push(e.activation.navigationType);
+ if (e.activation.from == navigation.currentEntry)
+ window.opener.events.push("from");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ channel.postMessage("nav");
+ };
+ };
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-reload-navigation.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-reload-navigation.html
new file mode 100644
index 0000000000..f7539ebc47
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-reload-navigation.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<title>pageswap navigationactivation for replace navigations</title>
+<link rel="help" href="https://html.spec.whatwg.org/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const expectedUrl = location.href + '?new';
+
+const params = new URLSearchParams(location.search);
+// The initial page in the popup.
+const is_popup_page = params.has('popup') && !window.opener.didreload;
+// The test page itself.
+const is_test_page = !params.has('popup');
+
+const channel = new BroadcastChannel("testchannel");
+
+if (is_test_page) {
+ const expectedUrl = location.href.split('?')[0] + "?popup";
+ const expectedEvents = ["pageswap", "entry", "reload","from", "pagehide"];
+
+ promise_test(async t => {
+ let popup;
+ onload = () => {
+ window.events = [];
+ window.didreload = false;
+ popup = window.open("?popup");
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on replace navigation from script`);
+} else if (is_popup_page) {
+ onload = () => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ window.opener.didreload = true;
+ location.reload();
+ }));
+
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ if (e.activation.entry == navigation.currentEntry)
+ window.opener.events.push("entry");
+ window.opener.events.push(e.activation.navigationType);
+ if (e.activation.from == navigation.currentEntry)
+ window.opener.events.push("from");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ channel.postMessage("nav");
+ };
+ };
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-navigation.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-navigation.html
new file mode 100644
index 0000000000..f6b3f7408c
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-navigation.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<title>pageswap navigationactivation for replace navigations</title>
+<link rel="help" href="https://html.spec.whatwg.org/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const expectedUrl = location.href + '?new';
+
+const params = new URLSearchParams(location.search);
+// The page the popup navigates to.
+const is_new_page = params.has('new');
+// The initial page in the popup.
+const is_popup_page = params.has('popup');
+// The test page itself.
+const is_test_page = !is_popup_page && !is_new_page;
+
+const channel = new BroadcastChannel("testchannel");
+
+if (is_test_page) {
+ const expectedUrl = location.href.split('?')[0] + "?new";
+ const expectedEvents = ["pageswap", expectedUrl, "replace","from", "pagehide"];
+
+ promise_test(async t => {
+ let popup;
+ onload = () => {
+ window.events = [];
+ popup = window.open("?popup");
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on replace navigation from script`);
+} else if (is_popup_page) {
+ onload = () => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ location.replace(location.href.split('?')[0] + '?new');
+ }));
+
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ window.opener.events.push(e.activation.entry.url);
+ window.opener.events.push(e.activation.navigationType);
+ if (e.activation.from == navigation.currentEntry)
+ window.opener.events.push("from");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ channel.postMessage("nav");
+ };
+ };
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-with-cross-origin-redirect.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-with-cross-origin-redirect.sub.html
new file mode 100644
index 0000000000..c6ced62057
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-replace-with-cross-origin-redirect.sub.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<title>pageswap navigationactivation for replace navigations with a same-origin final url with cross-origin redirects</title>
+<link rel="help" href="https://html.spec.whatwg.org/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script>
+const params = new URLSearchParams(location.search);
+// The page the popup navigates to.
+const is_new_page = params.has('new');
+// The initial page in the popup.
+const is_popup_page = params.has('popup');
+// The test page itself.
+const is_test_page = !is_popup_page && !is_new_page;
+
+const channel = new BroadcastChannel("testchannel");
+
+if (is_test_page) {
+ const expectedUrl = location.href + "?new";
+ const expectedEvents = ["pageswap", "pagehide", "pagereveal", "activation"];
+
+ promise_test(async t => {
+ let popup;
+ onload = () => {
+ window.events = [];
+ popup = window.open("?popup");
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on navigation with same-origin redirect`);
+} else if (is_popup_page) {
+ onload = () => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ let newUrl = get_host_info().HTTPS_REMOTE_ORIGIN + "/common/redirect.py?location=" + location.href.split('?')[0] + "?new";
+ location.replace(newUrl);
+ }));
+
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ if (e.activation != null)
+ window.opener.events.push("activation");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ };
+ };
+} else {
+ assert_true(is_new_page);
+ onpageshow = () => {
+ window.opener.events.push("pagereveal");
+ if (navigation.activation.from != null)
+ window.opener.events.push("activation");
+ channel.postMessage("nav");
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-cross-origin-redirect-no-bfcache.https.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-cross-origin-redirect-no-bfcache.https.sub.html
new file mode 100644
index 0000000000..5543830721
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-cross-origin-redirect-no-bfcache.https.sub.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<title>pageswap navigationactivation for traverse navigation when original navigation has cross-origin redirect</title>
+<link rel="help" href="https://html.spec.whatwg.org/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/common.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/disable_bfcache.js"></script>
+<style></style>
+<script>
+const channel = new BroadcastChannel("testchannel");
+
+const params = new URLSearchParams(location.search);
+const is_initial_page_first_navigation = params.has('popup') && navigation.entries().length == 1;
+const is_new_page = params.has('new');
+const is_test_page = !params.has('popup') && !params.has('new');
+
+// The test page which opens a popup for the navigation sequence.
+if (is_test_page) {
+ const expectedUrl = location.href.split('?')[0] + "?popup";
+ const expectedEvents = ["pageswap", expectedUrl, "traverse","from", "pagehide"];
+
+ promise_test(async t => {
+ let popup;
+ onload = () => {
+ window.events = [];
+ popup = window.open("?popup");
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on traverse navigation from script`);
+} else if (is_initial_page_first_navigation) {
+ // The popup page which the user navigates back to.
+ onload = async () => {
+ await disableBFCache();
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ let newUrl = get_host_info().HTTPS_REMOTE_ORIGIN + "/common/redirect.py?location=" + location.href.split('?')[0] + "?new";
+ location.href = newUrl
+ }));
+ };
+
+ onpageshow = (e) => {
+ assert_false(e.persisted, 'the test should run without BFCache');
+ }
+} else if (is_new_page) {
+ onload = () => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ navigation.back();
+ }));
+ };
+
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ window.opener.events.push(e.activation.entry.url);
+ window.opener.events.push(e.activation.navigationType);
+ if (e.activation.from == navigation.currentEntry)
+ window.opener.events.push("from");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ channel.postMessage("nav");
+ };
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-no-bfcache.https.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-no-bfcache.https.html
new file mode 100644
index 0000000000..9e8c0e100e
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-traverse-navigation-no-bfcache.https.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<title>pageswap navigationactivation for traverse navigations</title>
+<link rel="help" href="https://html.spec.whatwg.org/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/common.js"></script>
+<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/disable_bfcache.js"></script>
+<style></style>
+<script>
+const channel = new BroadcastChannel("testchannel");
+
+const params = new URLSearchParams(location.search);
+const is_initial_page_first_navigation = params.has('popup') && navigation.entries().length == 1;
+const is_new_page = params.has('new');
+const is_test_page = !params.has('popup') && !params.has('new');
+
+// The test page which opens a popup for the navigation sequence.
+if (is_test_page) {
+ const expectedUrl = location.href.split('?')[0] + "?popup";
+ const expectedEvents = ["pageswap", expectedUrl, "traverse","from", "pagehide"];
+
+ promise_test(async t => {
+ let popup;
+ onload = () => {
+ window.events = [];
+ popup = window.open("?popup");
+ };
+
+ await new Promise(resolve => {
+ channel.addEventListener(
+ "message", t.step_func(async (e) => {
+ if (e.data === "nav") {
+ assert_array_equals(window.events, expectedEvents, 'incorrect event order');
+ popup.close();
+ resolve();
+ }
+ }));
+ });
+ }, `pageswap on traverse navigation from script`);
+} else if (is_initial_page_first_navigation) {
+ // The popup page which the user navigates back to.
+ onload = async () => {
+ await disableBFCache();
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ location.href = location.href.split('?')[0] + '?new';
+ }));
+ };
+
+ onpageshow = (e) => {
+ assert_false(e.persisted, 'the test should run without BFCache');
+ }
+} else if (is_new_page) {
+ onload = () => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ navigation.back();
+ }));
+ };
+
+ onpageswap = (e) => {
+ window.opener.events.push("pageswap");
+ if (e.viewTransition != null)
+ window.opener.events.push("transition");
+ window.opener.events.push(e.activation.entry.url);
+ window.opener.events.push(e.activation.navigationType);
+ if (e.activation.from == navigation.currentEntry)
+ window.opener.events.push("from");
+ };
+
+ onpagehide = () => {
+ window.opener.events.push("pagehide");
+ channel.postMessage("nav");
+ };
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer-1.html
new file mode 100644
index 0000000000..d083a2a1d3
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>
+ Ensure referrer header persists after
+ history.pushState/replaceState/fragment navigation and reload
+ </title>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+ location.href = "history_reload_referrer-2.html?pipe=sub";
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer-2.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer-2.html
new file mode 100644
index 0000000000..d85517a15f
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer-2.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>
+ Ensure referrer header persists after
+ history.pushState/replaceState/fragment navigation and reload
+ </title>
+ </head>
+ <body>
+ <a id="fragment" href="#fragment">fragment</a>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+ const step = localStorage.getItem("history_reload_referrer_step") || "1";
+ localStorage.setItem("history_reload_referrer_step", parseInt(step) + 1);
+
+ var httpReferer = unescape("{{headers[referer]}}");
+ var expectedReferrer = location.href.replace(
+ /\/[^\/]*$/,
+ "\/history_reload_referrer-1.html"
+ );
+
+ parent.test(function () {
+ parent.assert_equals(httpReferer, expectedReferrer);
+ }, `Step ${step}: Checking HTTP referrer (is "${httpReferer}")`);
+ parent.test(function () {
+ parent.assert_equals(document.referrer, expectedReferrer);
+ }, `Step ${step}: Checking document.referrer (is "${httpReferer}")`);
+
+ switch (step) {
+ case "1":
+ history.pushState("", "", location);
+ location.reload();
+ break;
+
+ case "2":
+ history.replaceState("", "", location);
+ location.reload();
+ break;
+
+ case "3":
+ document.getElementById("fragment").click();
+ location.reload();
+ break;
+
+ case "4":
+ localStorage.removeItem("history_reload_referrer_step");
+ parent.done();
+ break;
+
+ default:
+ throw new Error(`Unexpected step "${step}"`);
+ }
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer.html
new file mode 100644
index 0000000000..d11ee89702
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_reload_referrer.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>
+ Ensure referrer header persists after
+ history.pushState/replaceState/fragment navigation and reload
+ </title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script
+ type="text/javascript"
+ src="/resources/testharnessreport.js"
+ ></script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+ setup({ explicit_done: true });
+ var iframe = document.createElement("iframe");
+ window.onload = function () {
+ iframe.setAttribute("src", "history_reload_referrer-1.html");
+ document.body.appendChild(iframe);
+ };
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign-replace-from-iframe.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign-replace-from-iframe.html
new file mode 100644
index 0000000000..a0cd9f25ef
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign-replace-from-iframe.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Referer with location.replace and location.assign</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <iframe src="/resources/blank.html" hidden></iframe>
+ <script>
+ async_test(function(t) {
+ function on_message(e) {
+ const referrer = e.data;
+ assert_equals(referrer, window.location.href);
+ t.done();
+ }
+ window.addEventListener('message', t.step_func(on_message), false);
+ document.querySelector("iframe").contentWindow.location.replace("resources/iframe-contents.sub.html?replace");
+ }, "Browser sends Referer header in iframe request when location.replace is called from an iframe");
+ async_test(function(t) {
+ function on_message(e) {
+ const referrer = e.data;
+ assert_equals(referrer, window.location.href);
+ t.done();
+ }
+ window.addEventListener('message', t.step_func(on_message), false);
+ document.querySelector("iframe").contentWindow.location.assign("resources/iframe-contents.sub.html?assign");
+ }, "Browser sends Referer header in iframe request when location.assign is called from an iframe");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign-replace-from-top-to-nested-iframe.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign-replace-from-top-to-nested-iframe.html
new file mode 100644
index 0000000000..eb6e4960dc
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign-replace-from-top-to-nested-iframe.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Referer with location.replace and location.assign with nested iframes</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <iframe src="resources/iframe-with-iframe.html" hidden></iframe>
+ <script>
+ const iframe = document.querySelector("iframe");
+ async_test(function(t) {
+ function on_message(e) {
+ const referrer = e.data;
+ assert_equals(referrer, iframe.contentWindow.location.href);
+ t.done();
+ }
+ window.addEventListener('message', t.step_func(on_message), false);
+ window.addEventListener('load', function () {
+ iframe.contentDocument.querySelector("iframe").contentWindow.location.replace("/resources/blank.html");
+ }, false);
+ }, "Browser sends Referer header in nested iframe request when location.replace is called on an iframe");
+ async_test(function(t) {
+ function on_message(e) {
+ const referrer = e.data;
+ assert_equals(referrer, iframe.contentWindow.location.href);
+ t.done();
+ }
+ window.addEventListener('message', t.step_func(on_message), false);
+ window.addEventListener('load', function () {
+ iframe.contentDocument.querySelector("iframe").contentWindow.location.replace("/resources/blank.html");
+ }, false);
+ }, "Browser sends Referer header in nested iframe request when location.assign is called on an iframe");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign-with-nested-iframe.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign-with-nested-iframe.html
new file mode 100644
index 0000000000..e043623c08
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign-with-nested-iframe.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Referer with location.assign and nested frames</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <iframe src="resources/replace-or-assign-call-on-iframe.html?assign" hidden></iframe>
+ <script>
+ async_test(function(t) {
+ function on_message(e) {
+ const nestedIframeReferrer = e.data;
+ assert_equals(nestedIframeReferrer, document.querySelector("iframe").contentWindow.location.href);
+ t.done();
+ }
+ window.addEventListener('message', t.step_func(on_message), false);
+ }, "Browser sends Referer header when location.assign is called in iframe document on another nested iframe element");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/replace-with-nested-iframe.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/replace-with-nested-iframe.html
new file mode 100644
index 0000000000..e6620bd29c
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/replace-with-nested-iframe.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Referer with location.replace and nested frames</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <iframe src="resources/replace-or-assign-call-on-iframe.html?replace" hidden></iframe>
+ <script>
+ async_test(function(t) {
+ function on_message(e) {
+ const nestedIframeReferrer = e.data;
+ assert_equals(nestedIframeReferrer, document.querySelector("iframe").contentWindow.location.href);
+ t.done();
+ }
+ window.addEventListener('message', t.step_func(on_message), false);
+ }, "Browser sends Referer header when location.replace is called in iframe document on another nested iframe element");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-contents.sub.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-contents.sub.html
new file mode 100644
index 0000000000..8ac0a264db
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-contents.sub.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Resource file for test of Referer with location.replace</title>
+ </head>
+ <body>
+ <div></div>
+ <script>
+ const referer = "{{header_or_default(referer, missing)}}"
+ window.parent.postMessage(referer);
+ document.querySelector("div").textContent = `Referer header: ${referer}`;
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-postmessage-to-parent-parent.sub.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-postmessage-to-parent-parent.sub.html
new file mode 100644
index 0000000000..25c4af19a3
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-postmessage-to-parent-parent.sub.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Resource file for test of Referer with location.replace</title>
+ </head>
+ <body>
+ <div></div>
+ <script>
+ const referer = "{{header_or_default(referer, missing)}}"
+ window.parent.parent.postMessage(referer);
+ document.querySelector("div").textContent = `Referer header: ${referer}`;
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-with-iframe.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-with-iframe.html
new file mode 100644
index 0000000000..675f293ffa
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/iframe-with-iframe.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Resource file for test of Referer with location.replace and location.assign</title>
+ </head>
+ <body>
+ <iframe src="iframe-postmessage-to-parent-parent.sub.html"></iframe>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/replace-or-assign-call-on-iframe.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/replace-or-assign-call-on-iframe.html
new file mode 100644
index 0000000000..bdad8334a5
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/replace-or-assign-call-on-iframe.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Referer with location.replace and location.assign</title>
+ </head>
+ <body>
+ <iframe src="/resources/blank.html" hidden></iframe>
+ <script>
+ window.addEventListener('message', function (e) {
+ const referrer = e.data;
+ window.parent.postMessage(referrer);
+ });
+ if (window.location.search === "?replace") {
+ document.querySelector("iframe").contentWindow.location.replace("iframe-contents.sub.html?replace");
+ } else if (window.location.search === "?assign") {
+ document.querySelector("iframe").contentWindow.location.assign("iframe-contents.sub.html?assign");
+ }
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/drawing-images-to-the-canvas/2d.drawImage.detachedcanvas.html b/testing/web-platform/tests/html/canvas/element/drawing-images-to-the-canvas/2d.drawImage.detachedcanvas.html
new file mode 100644
index 0000000000..e301537330
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/drawing-images-to-the-canvas/2d.drawImage.detachedcanvas.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.detachedcanvas</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.detachedcanvas</h1>
+<p class="desc">drawImage with detached OffscreenCanvas as the source should throw exception</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage with detached OffscreenCanvas as the source should throw exception");
+_addTest(function(canvas, ctx) {
+
+ var canvas2 = new OffscreenCanvas(80, 80);
+ (new MessageChannel()).port1.postMessage(canvas2, [canvas2]);
+ assert_throws_dom("INVALID_STATE_ERR", function() { ctx.drawImage(canvas2, 0, 0); });
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.html
index 42fb1ee8f8..dc94792867 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.html
@@ -8,7 +8,7 @@
<body class="show_output">
<h1>2d.filter.canvasFilterObject.blur.exceptions.tentative</h1>
-<p class="desc">Test exceptions on CanvasFilter() blur.object</p>
+<p class="desc">Test exceptions on gaussianBlur filter</p>
<p class="output">Actual output:</p>
@@ -16,15 +16,21 @@
<ul id="d"></ul>
<script>
-var t = async_test("Test exceptions on CanvasFilter() blur.object");
+var t = async_test("Test exceptions on gaussianBlur filter");
_addTest(function(canvas, ctx) {
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur'}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: undefined}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: 'foo'}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: [1,2,3]}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: NaN}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: 'foo'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: [1,2,3]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: {}}); });
});
</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.html
index b2f6a6ac97..56cf1bf0b1 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.html
@@ -8,7 +8,7 @@
<body class="show_output">
<h1>2d.filter.canvasFilterObject.colorMatrix.tentative</h1>
-<p class="desc">Test the functionality of ColorMatrix filters in CanvasFilter objects</p>
+<p class="desc">Test the functionality of ColorMatrix filters</p>
<p class="output">Actual output:</p>
@@ -16,41 +16,70 @@
<ul id="d"></ul>
<script>
-var t = async_test("Test the functionality of ColorMatrix filters in CanvasFilter objects");
+var t = async_test("Test the functionality of ColorMatrix filters");
_addTest(function(canvas, ctx) {
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: 'foo'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: null}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 'a']}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, Infinity]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: undefined}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: 'foo'}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: null}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: [1, 2, 3]}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 'a']}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, Infinity]}); });
+
ctx.fillStyle = '#f00';
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 0});
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 0});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 255,0,0,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 90});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 90});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,91,0,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 180});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 180});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,109,109,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 270});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 270});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 109,18,255,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'saturate', values: 0.5});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'saturate', values: 0.5});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 155,27,27,255, 2);
+
ctx.clearRect(0, 0, 100, 50);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'luminanceToAlpha'});
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'luminanceToAlpha'});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,0,0,54, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', values: [
- 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 0
- ]});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: [
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0
+ ]});
ctx.fillRect(0, 0, 50, 25);
ctx.fillStyle = '#0f0';
ctx.fillRect(50, 0, 50, 25);
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html
new file mode 100644
index 0000000000..2b1c1c1c07
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with discrete type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getTransformedValue(C, V) {
+ // Get the right interval
+ const n = V.length;
+ const k = C == 1 ? n - 1 : Math.floor(C * n);
+ return V[k];
+ }
+
+ function getColor(inputColor, tableValues) {
+ const result = [0, 0, 0];
+ for (const i in inputColor) {
+ const C = inputColor[i]/255;
+ const Cprime = getTransformedValue(C, tableValues[i]);
+ result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
+ }
+ return result;
+ }
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(
+ color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.html
index b392b189f2..0a4830568b 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.html
@@ -1,41 +1,16 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
-<body class="show_output">
-
<h1>2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</h1>
<p class="desc">Test pixels on CanvasFilter() componentTransfer with discrete type</p>
-
-
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-
-<ul id="d"></ul>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
<script>
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with discrete type");
-_addTest(function(canvas, ctx) {
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getTransformedValue(C, V) {
- // Get the right interval
- const n = V.length;
- const k = C == 1 ? n - 1 : Math.floor(C * n);
- return V[k];
- }
-
- function getColor(inputColor, tableValues) {
- const result = [0, 0, 0];
- for (const i in inputColor) {
- const C = inputColor[i]/255;
- const Cprime = getTransformedValue(C, tableValues[i]);
- result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
- }
- return result;
- }
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
tableValuesR = [0, 0, 1, 1];
tableValuesG = [2, 0, 0.5, 3];
@@ -54,13 +29,9 @@ _addTest(function(canvas, ctx) {
[50, 68, 87],
];
- for (const color of inputColors) {
- let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
-
-});
</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html
new file mode 100644
index 0000000000..5adc9f53e2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with gamma type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getColor(inputColor, amplitude, exponent, offset) {
+ return [
+ Math.max(0, Math.min(1, Math.pow(inputColor[0]/255,
+ exponent[0]) * amplitude[0] + offset[0])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[1]/255,
+ exponent[1]) * amplitude[1] + offset[1])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[2]/255,
+ exponent[2]) * amplitude[2] + offset[2])) * 255,
+ ];
+ }
+
+ const amplitudes = [2, 1.1, 0.5];
+ const exponents = [5, 3, 1];
+ const offsets = [0.25, 0, 0.5];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(color, amplitudes, exponents, offsets);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.html
index e5bff7e44d..22e3abe624 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.html
@@ -1,40 +1,27 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
-<body class="show_output">
-
<h1>2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</h1>
<p class="desc">Test pixels on CanvasFilter() componentTransfer with gamma type</p>
-
-
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-
-<ul id="d"></ul>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
<script>
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with gamma type");
-_addTest(function(canvas, ctx) {
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getColor(inputColor, amplitude, exponent, offset) {
- return [
- Math.max(0, Math.min(1, Math.pow(inputColor[0]/255, exponent[0]) * amplitude[0] + offset[0])) * 255,
- Math.max(0, Math.min(1, Math.pow(inputColor[1]/255, exponent[1]) * amplitude[1] + offset[1])) * 255,
- Math.max(0, Math.min(1, Math.pow(inputColor[2]/255, exponent[2]) * amplitude[2] + offset[2])) * 255,
- ];
- }
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
const amplitudes = [2, 1.1, 0.5];
const exponents = [5, 3, 1];
const offsets = [0.25, 0, 0.5];
ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'gamma', amplitude: amplitudes[0], exponent: exponents[0], offset: offsets[0]},
- funcG: {type: 'gamma', amplitude: amplitudes[1], exponent: exponents[1], offset: offsets[1]},
- funcB: {type: 'gamma', amplitude: amplitudes[2], exponent: exponents[2], offset: offsets[2]},
+ funcR: {type: 'gamma', amplitude: amplitudes[0],
+ exponent: exponents[0], offset: offsets[0]},
+ funcG: {type: 'gamma', amplitude: amplitudes[1],
+ exponent: exponents[1], offset: offsets[1]},
+ funcB: {type: 'gamma', amplitude: amplitudes[2],
+ exponent: exponents[2], offset: offsets[2]},
});
const inputColors = [
@@ -45,13 +32,9 @@ _addTest(function(canvas, ctx) {
[50, 68, 87],
];
- for (const color of inputColors) {
- let outputColor = getColor(color, amplitudes, exponents, offsets);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
-
-});
</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html
new file mode 100644
index 0000000000..895d531206
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.identity.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.identity.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with identity type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ let outputColor = inputColors[i];
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.html
index ecd3830be3..17761ce31a 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.html
@@ -1,23 +1,15 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html">
<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.identity.tentative</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
-<body class="show_output">
-
<h1>2d.filter.canvasFilterObject.componentTransfer.identity.tentative</h1>
<p class="desc">Test pixels on CanvasFilter() componentTransfer with identity type</p>
-
-
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-
-<ul id="d"></ul>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
<script>
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with identity type");
-_addTest(function(canvas, ctx) {
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
ctx.filter = new CanvasFilter({name: 'componentTransfer',
funcR: {type: 'identity'},
@@ -33,12 +25,9 @@ _addTest(function(canvas, ctx) {
[50, 68, 87],
];
- for (const color of inputColors) {
- ctx.fillStyle = `rgba(${color[0]}, ${color[1]}, ${color[2]}, 1)`,
- ctx.fillRect(0, 0, 10, 10);
- _assertPixel(canvas, 5, 5, color[0],color[1],color[2],255);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
-
-});
</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html
new file mode 100644
index 0000000000..c4ad790d56
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.linear.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.linear.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with linear type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getColor(inputColor, slopes, intercepts) {
+ return [
+ Math.max(0, Math.min(1,
+ inputColor[0]/255 * slopes[0] + intercepts[0])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[1]/255 * slopes[1] + intercepts[1])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[2]/255 * slopes[2] + intercepts[2])) * 255,
+ ];
+ }
+
+ const slopes = [0.5, 1.2, -0.2];
+ const intercepts = [0.25, 0, 0.5];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(color, slopes, intercepts);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.html
index 8708887f6a..5ea5f8e0e3 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.html
@@ -1,32 +1,16 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.linear.tentative</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
-<body class="show_output">
-
<h1>2d.filter.canvasFilterObject.componentTransfer.linear.tentative</h1>
<p class="desc">Test pixels on CanvasFilter() componentTransfer with linear type</p>
-
-
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-
-<ul id="d"></ul>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
<script>
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with linear type");
-_addTest(function(canvas, ctx) {
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getColor(inputColor, slopes, intercepts) {
- return [
- Math.max(0, Math.min(1, inputColor[0]/255 * slopes[0] + intercepts[0])) * 255,
- Math.max(0, Math.min(1, inputColor[1]/255 * slopes[1] + intercepts[1])) * 255,
- Math.max(0, Math.min(1, inputColor[2]/255 * slopes[2] + intercepts[2])) * 255,
- ];
- }
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
const slopes = [0.5, 1.2, -0.2];
const intercepts = [0.25, 0, 0.5];
@@ -44,13 +28,9 @@ _addTest(function(canvas, ctx) {
[50, 68, 87],
];
- for (const color of inputColors) {
- let outputColor = getColor(color, slopes, intercepts);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
-
-});
</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html
new file mode 100644
index 0000000000..29e250614c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.table.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.table.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with table type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getTransformedValue(C, V) {
+ // Get the right interval
+ const n = V.length - 1;
+ const k = C == 1 ? n - 1 : Math.floor(C * n);
+ return V[k] + (C - k/n) * n * (V[k + 1] - V[k]);
+ }
+
+ function getColor(inputColor, tableValues) {
+ const result = [0, 0, 0];
+ for (const i in inputColor) {
+ const C = inputColor[i]/255;
+ const Cprime = getTransformedValue(C, tableValues[i]);
+ result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
+ }
+ return result;
+ }
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(
+ color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.html
index 4b296d9fd7..0f74d9c3bf 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.html
@@ -1,41 +1,16 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.table.tentative</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
-<body class="show_output">
-
<h1>2d.filter.canvasFilterObject.componentTransfer.table.tentative</h1>
<p class="desc">Test pixels on CanvasFilter() componentTransfer with table type</p>
-
-
-<p class="output">Actual output:</p>
-<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-
-<ul id="d"></ul>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
<script>
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with table type");
-_addTest(function(canvas, ctx) {
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getTransformedValue(C, V) {
- // Get the right interval
- const n = V.length - 1;
- const k = C == 1 ? n - 1 : Math.floor(C * n);
- return V[k] + (C - k/n) * n * (V[k + 1] - V[k]);
- }
-
- function getColor(inputColor, tableValues) {
- const result = [0, 0, 0];
- for (const i in inputColor) {
- const C = inputColor[i]/255;
- const Cprime = getTransformedValue(C, tableValues[i]);
- result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
- }
- return result;
- }
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
tableValuesR = [0, 0, 1, 1];
tableValuesG = [2, 0, 0.5, 3];
@@ -54,13 +29,9 @@ _addTest(function(canvas, ctx) {
[50, 68, 87],
];
- for (const color of inputColors) {
- let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
-
-});
</script>
-
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.html
index b80600c141..a288541057 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.html
@@ -19,23 +19,39 @@
var t = async_test("Test exceptions on CanvasFilter() convolveMatrix");
_addTest(function(canvas, ctx) {
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', divisor: 2}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: null}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: 1}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: []}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [1]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[], []]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 2], []]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', divisor: 2}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: null}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: 1}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: []}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [1]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[], []]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 2], []]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]}); });
// This should not throw an error
- ctx.filter = new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[]]});
- ctx.filter = new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1]]});
+ ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[]]});
+ ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1]]});
});
</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.html
index 8c07a72b2b..05984a47f8 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.html
@@ -19,104 +19,250 @@
var t = async_test("Test exceptions on CanvasFilter() dropShadow object");
_addTest(function(canvas, ctx) {
+ // Should not throw an error.
// dx
- _assert(new CanvasFilter({name: 'dropShadow', dx: 10}), "new CanvasFilter({name: 'dropShadow', dx: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: -1}), "new CanvasFilter({name: 'dropShadow', dx: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: 0.5}), "new CanvasFilter({name: 'dropShadow', dx: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: null}), "new CanvasFilter({name: 'dropShadow', dx: null})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: true}), "new CanvasFilter({name: 'dropShadow', dx: true})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: false}), "new CanvasFilter({name: 'dropShadow', dx: false})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: []}), "new CanvasFilter({name: 'dropShadow', dx: []})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: [20]}), "new CanvasFilter({name: 'dropShadow', dx: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: '30'}), "new CanvasFilter({name: 'dropShadow', dx: '30'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: '30'});
// dy
- _assert(new CanvasFilter({name: 'dropShadow', dy: 10}), "new CanvasFilter({name: 'dropShadow', dy: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: -1}), "new CanvasFilter({name: 'dropShadow', dy: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: 0.5}), "new CanvasFilter({name: 'dropShadow', dy: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: null}), "new CanvasFilter({name: 'dropShadow', dy: null})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: true}), "new CanvasFilter({name: 'dropShadow', dy: true})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: false}), "new CanvasFilter({name: 'dropShadow', dy: false})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: []}), "new CanvasFilter({name: 'dropShadow', dy: []})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: [20]}), "new CanvasFilter({name: 'dropShadow', dy: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: '30'}), "new CanvasFilter({name: 'dropShadow', dy: '30'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: '30'});
// floodOpacity
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: 10}), "new CanvasFilter({name: 'dropShadow', floodOpacity: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: -1}), "new CanvasFilter({name: 'dropShadow', floodOpacity: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: 0.5}), "new CanvasFilter({name: 'dropShadow', floodOpacity: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: null}), "new CanvasFilter({name: 'dropShadow', floodOpacity: null})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: true}), "new CanvasFilter({name: 'dropShadow', floodOpacity: true})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: false}), "new CanvasFilter({name: 'dropShadow', floodOpacity: false})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: []}), "new CanvasFilter({name: 'dropShadow', floodOpacity: []})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: [20]}), "new CanvasFilter({name: 'dropShadow', floodOpacity: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: '30'}), "new CanvasFilter({name: 'dropShadow', floodOpacity: '30'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: '30'});
+ // dx
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: '30'});
+ // dy
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: '30'});
+ // floodOpacity
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: '30'});
// stdDeviation
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: 10}), "new CanvasFilter({name: 'dropShadow', stdDeviation: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: -1}), "new CanvasFilter({name: 'dropShadow', stdDeviation: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: 0.5}), "new CanvasFilter({name: 'dropShadow', stdDeviation: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: null}), "new CanvasFilter({name: 'dropShadow', stdDeviation: null})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: true}), "new CanvasFilter({name: 'dropShadow', stdDeviation: true})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: false}), "new CanvasFilter({name: 'dropShadow', stdDeviation: false})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: []}), "new CanvasFilter({name: 'dropShadow', stdDeviation: []})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [20]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: '30'}), "new CanvasFilter({name: 'dropShadow', stdDeviation: '30'})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [10, -1]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [10, -1]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [0.5, null]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [0.5, null]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [true, false]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [true, false]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [[], [20]]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [[], [\""+(20)+"\"]]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: ['30', ['40']]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: ['30', ['40']]})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: '30'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [10, -1]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [0.5, null]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [true, false]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [[], [20]]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: ['30', ['40']]});
// floodColor
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: 'red'}), "new CanvasFilter({name: 'dropShadow', floodColor: 'red'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: 'canvas'}), "new CanvasFilter({name: 'dropShadow', floodColor: 'canvas'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'}), "new CanvasFilter({name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: '#aabbccdd'}), "new CanvasFilter({name: 'dropShadow', floodColor: '#aabbccdd'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: '#abcd'}), "new CanvasFilter({name: 'dropShadow', floodColor: '#abcd'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'red'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'canvas'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: '#aabbccdd'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: '#abcd'});
+ // Should throw a TypeError.
// dx
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: [1, 2]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: [1, 2]}); });
// dy
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: [1, 2]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: [1, 2]}); });
// floodOpacity
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: [1, 2]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: [1, 2]}); });
// stdDeviation
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, 2, 3]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, NaN]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, Infinity]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, -Infinity]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, undefined]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, 'test']}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, {}]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, [2, 3]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, 2, 3]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, NaN]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, Infinity]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, -Infinity]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, undefined]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, 'test']}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, {}]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, [2, 3]]}); });
// floodColor
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: 'rgba(NaN, 3, 2, 1)'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: 10}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: null}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'rgba(NaN, 3, 2, 1)'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 10}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: null}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: NaN}); });
});
</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html
index 47bb891b3f..d6e7066473 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html
@@ -22,86 +22,58 @@
// Parameter defaults.
ctx.filter = new CanvasFilter({name: 'dropShadow'});
ctx.fillRect(10, 10, 80, 80);
-
// All parameters specified.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
floodColor: 'purple', floodOpacity: 0.7});
ctx.fillRect(110, 10, 80, 80);
-
// Named color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'purple'});
ctx.fillRect(10, 110, 80, 80);
-
// System color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'LinkText'});
ctx.fillRect(110, 110, 80, 80);
-
// Numerical color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'rgba(20, 50, 130, 1)'});
ctx.fillRect(210, 110, 80, 80);
-
// Transparent floodColor.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'rgba(20, 50, 130, 0.7)'});
ctx.fillRect(310, 110, 80, 80);
-
// Transparent floodColor and floodOpacity.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'rgba(20, 50, 130, 0.7)', floodOpacity: 0.7});
ctx.fillRect(410, 110, 80, 80);
-
// No blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
floodColor: 'purple'});
ctx.fillRect(10, 210, 80, 80);
-
// Single float blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
floodColor: 'purple'});
ctx.fillRect(110, 210, 80, 80);
-
// Single negative float blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
floodColor: 'purple'});
ctx.fillRect(210, 210, 80, 80);
-
// Two floats (X&Y) blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
floodColor: 'purple'});
ctx.fillRect(310, 210, 80, 80);
-
// Two negative floats (X&Y) blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
floodColor: 'purple'});
ctx.fillRect(410, 210, 80, 80);
-
// Degenerate parameter values.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
floodColor: 'purple', floodOpacity: [2]});
ctx.fillRect(10, 310, 80, 80);
-
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
floodColor: 'purple', floodOpacity: '0.8'});
ctx.fillRect(110, 310, 80, 80);
-
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
floodColor: 'purple', floodOpacity: ['0.4']});
ctx.fillRect(210, 310, 80, 80);
</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html
index f9571f208e..dac31c97f1 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic-expected.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic</h1>
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<svg xmlns="http://www.w3.org/2000/svg"
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html
index 6376d07b0e..f4c8c1033a 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html
index e76613271f..88d0cb2de2 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x-expected.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x</h1>
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<svg xmlns="http://www.w3.org/2000/svg"
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html
index 145cb32757..b3efcb8c3e 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html
index 0f214fca9f..744983d4ae 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y-expected.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y</h1>
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<svg xmlns="http://www.w3.org/2000/svg"
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html
index e921e0eaa6..d5cc6e0058 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html
index 285a641726..e611113e42 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only-expected.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only</h1>
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<svg xmlns="http://www.w3.org/2000/svg"
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html
index fd6ac687f9..4e8576fe74 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html
index d59945b5da..c6d915cb07 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only-expected.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only</h1>
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<svg xmlns="http://www.w3.org/2000/svg"
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html
index 6442433e7c..ec0a2353cf 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.html
index c24cfd2398..b85add4b66 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.html
@@ -116,12 +116,12 @@ _addTest(function(canvas, ctx) {
for (testCase of errorTestCases) {
const filterOptions = {...{name: 'turbulence'}, ...testCase};
- assert_throws_js(TypeError, function() { new CanvasFilter(filterOptions); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(filterOptions); });
}
for (testCase of workingTestCases) {
const filterOptions = {...{name: 'turbulence'}, ...testCase};
- _assert(new CanvasFilter(filterOptions) != null, "new CanvasFilter(filterOptions) != null");
+ ctx.filter = new CanvasFilter(filterOptions);
}
});
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.blur.exceptions.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.blur.exceptions.html
new file mode 100644
index 0000000000..7176a7d0a4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.blur.exceptions.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.blur.exceptions</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.filter.layers.blur.exceptions</h1>
+<p class="desc">Test exceptions on gaussianBlur filter</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Test exceptions on gaussianBlur filter");
+_addTest(function(canvas, ctx) {
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur'}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: undefined}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: 'foo'}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: [1,2,3]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: NaN}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: {}}}); });
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.colorMatrix.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.colorMatrix.html
new file mode 100644
index 0000000000..ef0ae0f949
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.colorMatrix.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.colorMatrix</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.filter.layers.colorMatrix</h1>
+<p class="desc">Test the functionality of ColorMatrix filters</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Test the functionality of ColorMatrix filters");
+_addTest(function(canvas, ctx) {
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: undefined}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: 'foo'}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: null}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: [1, 2, 3]}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 'a']}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, Infinity]}}); });
+
+ ctx.fillStyle = '#f00';
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 0}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 255,0,0,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 90}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,91,0,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 180}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,109,109,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 270}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 109,18,255,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'saturate', values: 0.5}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 155,27,27,255, 2);
+
+ ctx.clearRect(0, 0, 100, 50);
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'luminanceToAlpha'}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,0,0,54, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: [
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0
+ ]}});
+ ctx.fillRect(0, 0, 50, 25);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(50, 0, 50, 25);
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 25, 50, 25);
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(50, 25, 50, 25);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,255,0,255, 2);
+ _assertPixelApprox(canvas, 60,10, 0,255,0,255, 2);
+ _assertPixelApprox(canvas, 10,30, 0,255,0,255, 2);
+ _assertPixelApprox(canvas, 60,30, 0,255,0,255, 2);
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.discrete-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.discrete-expected.html
new file mode 100644
index 0000000000..8419953b3d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.discrete-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.componentTransfer.discrete</title>
+<h1>2d.filter.layers.componentTransfer.discrete</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with discrete type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getTransformedValue(C, V) {
+ // Get the right interval
+ const n = V.length;
+ const k = C == 1 ? n - 1 : Math.floor(C * n);
+ return V[k];
+ }
+
+ function getColor(inputColor, tableValues) {
+ const result = [0, 0, 0];
+ for (const i in inputColor) {
+ const C = inputColor[i]/255;
+ const Cprime = getTransformedValue(C, tableValues[i]);
+ result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
+ }
+ return result;
+ }
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(
+ color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.discrete.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.discrete.html
new file mode 100644
index 0000000000..ef9db79547
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.discrete.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.componentTransfer.discrete-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.discrete</title>
+<h1>2d.filter.layers.componentTransfer.discrete</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with discrete type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'discrete', tableValues: tableValuesR},
+ funcG: {type: 'discrete', tableValues: tableValuesG},
+ funcB: {type: 'discrete', tableValues: tableValuesB},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.gamma-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.gamma-expected.html
new file mode 100644
index 0000000000..3e5d980896
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.gamma-expected.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.componentTransfer.gamma</title>
+<h1>2d.filter.layers.componentTransfer.gamma</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with gamma type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getColor(inputColor, amplitude, exponent, offset) {
+ return [
+ Math.max(0, Math.min(1, Math.pow(inputColor[0]/255,
+ exponent[0]) * amplitude[0] + offset[0])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[1]/255,
+ exponent[1]) * amplitude[1] + offset[1])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[2]/255,
+ exponent[2]) * amplitude[2] + offset[2])) * 255,
+ ];
+ }
+
+ const amplitudes = [2, 1.1, 0.5];
+ const exponents = [5, 3, 1];
+ const offsets = [0.25, 0, 0.5];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(color, amplitudes, exponents, offsets);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.gamma.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.gamma.html
new file mode 100644
index 0000000000..cccd07e92b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.gamma.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.componentTransfer.gamma-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.gamma</title>
+<h1>2d.filter.layers.componentTransfer.gamma</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with gamma type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const amplitudes = [2, 1.1, 0.5];
+ const exponents = [5, 3, 1];
+ const offsets = [0.25, 0, 0.5];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'gamma', amplitude: amplitudes[0],
+ exponent: exponents[0], offset: offsets[0]},
+ funcG: {type: 'gamma', amplitude: amplitudes[1],
+ exponent: exponents[1], offset: offsets[1]},
+ funcB: {type: 'gamma', amplitude: amplitudes[2],
+ exponent: exponents[2], offset: offsets[2]},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.identity-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.identity-expected.html
new file mode 100644
index 0000000000..9f1439f37b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.identity-expected.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.componentTransfer.identity</title>
+<h1>2d.filter.layers.componentTransfer.identity</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with identity type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ let outputColor = inputColors[i];
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.identity.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.identity.html
new file mode 100644
index 0000000000..3a06353849
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.identity.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.componentTransfer.identity-expected.html">
+<title>Canvas test: 2d.filter.layers.componentTransfer.identity</title>
+<h1>2d.filter.layers.componentTransfer.identity</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with identity type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'identity'},
+ funcG: {type: 'identity'},
+ funcB: {type: 'identity'},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.linear-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.linear-expected.html
new file mode 100644
index 0000000000..f922055ff2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.linear-expected.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.componentTransfer.linear</title>
+<h1>2d.filter.layers.componentTransfer.linear</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with linear type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getColor(inputColor, slopes, intercepts) {
+ return [
+ Math.max(0, Math.min(1,
+ inputColor[0]/255 * slopes[0] + intercepts[0])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[1]/255 * slopes[1] + intercepts[1])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[2]/255 * slopes[2] + intercepts[2])) * 255,
+ ];
+ }
+
+ const slopes = [0.5, 1.2, -0.2];
+ const intercepts = [0.25, 0, 0.5];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(color, slopes, intercepts);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.linear.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.linear.html
new file mode 100644
index 0000000000..c9e744ebef
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.linear.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.componentTransfer.linear-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.linear</title>
+<h1>2d.filter.layers.componentTransfer.linear</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with linear type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const slopes = [0.5, 1.2, -0.2];
+ const intercepts = [0.25, 0, 0.5];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'linear', slope: slopes[0], intercept: intercepts[0]},
+ funcG: {type: 'linear', slope: slopes[1], intercept: intercepts[1]},
+ funcB: {type: 'linear', slope: slopes[2], intercept: intercepts[2]},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.table-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.table-expected.html
new file mode 100644
index 0000000000..0f6736d87d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.table-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.componentTransfer.table</title>
+<h1>2d.filter.layers.componentTransfer.table</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with table type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getTransformedValue(C, V) {
+ // Get the right interval
+ const n = V.length - 1;
+ const k = C == 1 ? n - 1 : Math.floor(C * n);
+ return V[k] + (C - k/n) * n * (V[k + 1] - V[k]);
+ }
+
+ function getColor(inputColor, tableValues) {
+ const result = [0, 0, 0];
+ for (const i in inputColor) {
+ const C = inputColor[i]/255;
+ const Cprime = getTransformedValue(C, tableValues[i]);
+ result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
+ }
+ return result;
+ }
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(
+ color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.table.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.table.html
new file mode 100644
index 0000000000..eae036b142
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.componentTransfer.table.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.componentTransfer.table-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.table</title>
+<h1>2d.filter.layers.componentTransfer.table</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with table type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'table', tableValues: tableValuesR},
+ funcG: {type: 'table', tableValues: tableValuesG},
+ funcB: {type: 'table', tableValues: tableValuesB},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.convolveMatrix.exceptions.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.convolveMatrix.exceptions.html
new file mode 100644
index 0000000000..ae45cb865c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.convolveMatrix.exceptions.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.convolveMatrix.exceptions</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.filter.layers.convolveMatrix.exceptions</h1>
+<p class="desc">Test exceptions on CanvasFilter() convolveMatrix</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Test exceptions on CanvasFilter() convolveMatrix");
+_addTest(function(canvas, ctx) {
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix'}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', divisor: 2}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: null}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: 1}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: []}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [1]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[], []]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 2], []]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]}}); });
+ // This should not throw an error
+ ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[]]}});
+ ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1]]}});
+ ctx.endLayer();
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow-expected.html
new file mode 100644
index 0000000000..1719d99b4a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow-expected.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.dropShadow</title>
+<h1>2d.filter.layers.dropShadow</h1>
+<p class="desc">Test CanvasFilter() dropShadow object.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width=520 height=420
+ color-interpolation-filters="sRGB">
+ <rect x=0 y=0 width=100% height=50 fill="teal" />
+ <rect x=0 y=100 width=100% height=50 fill="teal" />
+ <rect x=0 y=200 width=100% height=50 fill="teal" />
+ <rect x=0 y=300 width=100% height=50 fill="teal" />
+
+ <rect x=10 y=10 width=80 height=80 fill="crimson"
+ filter="drop-shadow(2px 2px 2px black)"/>
+ <rect x=110 y=10 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 5px rgba(128, 0, 128, 0.7))"/>
+
+ <rect x=10 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px purple)"/>
+ <rect x=110 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px LinkText)"/>
+ <rect x=210 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px rgba(20, 50, 130, 1))"/>
+ <rect x=310 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px rgba(20, 50, 130, 0.7))"/>
+ <rect x=410 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px rgba(20, 50, 130, 0.49))"/>
+
+ <rect x=10 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 0px purple)"/>
+ <rect x=110 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 5px purple)"/>
+ <rect x=210 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 0px purple)"/>
+ <filter id="separable-filter"
+ x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx=9 dy=12 stdDeviation="3 5" flood-color="purple"/>
+ </filter>
+ <rect x=310 y=210 width=80 height=80 fill="crimson"
+ filter="url(#separable-filter)"/>
+ <rect x=410 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 0px purple)"/>
+
+ <rect x=10 y=310 width=80 height=80 fill="crimson"
+ filter="drop-shadow(-5px 0px 0px purple)"/>
+ <filter id="separable-filter-degenerate"
+ x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx=0 dy=5 stdDeviation="0 3"
+ flood-color="rgba(128, 0, 128, 0.8)"/>
+ </filter>
+ <rect x=110 y=310 width=80 height=80 fill="crimson"
+ filter="url(#separable-filter-degenerate)"/>
+ <rect x=210 y=310 width=80 height=80 fill="crimson"
+ filter="drop-shadow(1px 10px 0px rgba(128, 0, 128, 0.4))"/>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow.exceptions.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow.exceptions.html
new file mode 100644
index 0000000000..df5e0c7dc3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow.exceptions.html
@@ -0,0 +1,269 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.dropShadow.exceptions</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.filter.layers.dropShadow.exceptions</h1>
+<p class="desc">Test exceptions on CanvasFilter() dropShadow object</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Test exceptions on CanvasFilter() dropShadow object");
+_addTest(function(canvas, ctx) {
+
+ // Should not throw an error.
+ // dx
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: '30'}}); ctx.endLayer();
+ // dy
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: '30'}}); ctx.endLayer();
+ // floodOpacity
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: '30'}}); ctx.endLayer();
+ // dx
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: '30'}}); ctx.endLayer();
+ // dy
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: '30'}}); ctx.endLayer();
+ // floodOpacity
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: '30'}}); ctx.endLayer();
+ // stdDeviation
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: '30'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [10, -1]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [0.5, null]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [true, false]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [[], [20]]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: ['30', ['40']]}}); ctx.endLayer();
+ // floodColor
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'red'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'canvas'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: '#aabbccdd'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: '#abcd'}}); ctx.endLayer();
+
+ // Should throw a TypeError.
+ // dx
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: [1, 2]}}); ctx.endLayer(); });
+ // dy
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: [1, 2]}}); ctx.endLayer(); });
+ // floodOpacity
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: [1, 2]}}); ctx.endLayer(); });
+ // stdDeviation
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, 2, 3]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, NaN]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, Infinity]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, -Infinity]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, undefined]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, 'test']}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, {}]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, [2, 3]]}}); ctx.endLayer(); });
+ // floodColor
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'rgba(NaN, 3, 2, 1)'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 10}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: null}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: NaN}}); ctx.endLayer(); });
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow.html
new file mode 100644
index 0000000000..ceb20bb9eb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.dropShadow.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.dropShadow-expected.html">
+<title>Canvas test: 2d.filter.layers.dropShadow</title>
+<h1>2d.filter.layers.dropShadow</h1>
+<p class="desc">Test CanvasFilter() dropShadow object.</p>
+<canvas id="canvas" width="520" height="420">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(0, 0, 520, 50);
+ ctx.fillRect(0, 100, 520, 50);
+ ctx.fillRect(0, 200, 520, 50);
+ ctx.fillRect(0, 300, 520, 50);
+
+ ctx.fillStyle = 'crimson';
+
+ // Parameter defaults.
+ ctx.beginLayer({filter: {name: 'dropShadow'}});
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+ // All parameters specified.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ floodColor: 'purple', floodOpacity: 0.7}});
+ ctx.fillRect(110, 10, 80, 80);
+ ctx.endLayer();
+ // Named color.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'purple'}});
+ ctx.fillRect(10, 110, 80, 80);
+ ctx.endLayer();
+ // System color.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'LinkText'}});
+ ctx.fillRect(110, 110, 80, 80);
+ ctx.endLayer();
+ // Numerical color.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 1)'}});
+ ctx.fillRect(210, 110, 80, 80);
+ ctx.endLayer();
+ // Transparent floodColor.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 0.7)'}});
+ ctx.fillRect(310, 110, 80, 80);
+ ctx.endLayer();
+ // Transparent floodColor and floodOpacity.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 0.7)', floodOpacity: 0.7}});
+ ctx.fillRect(410, 110, 80, 80);
+ ctx.endLayer();
+ // No blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
+ floodColor: 'purple'}});
+ ctx.fillRect(10, 210, 80, 80);
+ ctx.endLayer();
+ // Single float blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ floodColor: 'purple'}});
+ ctx.fillRect(110, 210, 80, 80);
+ ctx.endLayer();
+ // Single negative float blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
+ floodColor: 'purple'}});
+ ctx.fillRect(210, 210, 80, 80);
+ ctx.endLayer();
+ // Two floats (X&Y) blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
+ floodColor: 'purple'}});
+ ctx.fillRect(310, 210, 80, 80);
+ ctx.endLayer();
+ // Two negative floats (X&Y) blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
+ floodColor: 'purple'}});
+ ctx.fillRect(410, 210, 80, 80);
+ ctx.endLayer();
+ // Degenerate parameter values.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
+ floodColor: 'purple', floodOpacity: [2]}});
+ ctx.fillRect(10, 310, 80, 80);
+ ctx.endLayer();
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
+ floodColor: 'purple', floodOpacity: '0.8'}});
+ ctx.fillRect(110, 310, 80, 80);
+ ctx.endLayer();
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
+ floodColor: 'purple', floodOpacity: ['0.4']}});
+ ctx.fillRect(210, 310, 80, 80);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html
index f9571f208e..4f93754862 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic-expected.html
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic</h1>
+<title>Canvas test: 2d.filter.layers.gaussianBlur.isotropic</title>
+<h1>2d.filter.layers.gaussianBlur.isotropic</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<svg xmlns="http://www.w3.org/2000/svg"
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic.html
new file mode 100644
index 0000000000..a2cc098896
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.isotropic.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur.isotropic-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.isotropic</title>
+<h1>2d.filter.layers.gaussianBlur.isotropic</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html
new file mode 100644
index 0000000000..255270c192
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-x</title>
+<h1>2d.filter.layers.gaussianBlur.mostly-x</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 1" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x.html
new file mode 100644
index 0000000000..0090e0e71e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-x.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur.mostly-x-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-x</title>
+<h1>2d.filter.layers.gaussianBlur.mostly-x</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 1],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html
new file mode 100644
index 0000000000..76a46b1533
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-y</title>
+<h1>2d.filter.layers.gaussianBlur.mostly-y</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="1 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y.html
new file mode 100644
index 0000000000..5c481cbe25
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.mostly-y.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur.mostly-y-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-y</title>
+<h1>2d.filter.layers.gaussianBlur.mostly-y</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [1, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only-expected.html
new file mode 100644
index 0000000000..26741f9847
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur.x-only</title>
+<h1>2d.filter.layers.gaussianBlur.x-only</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 0" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only.html
new file mode 100644
index 0000000000..f7940eb921
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.x-only.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur.x-only-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.x-only</title>
+<h1>2d.filter.layers.gaussianBlur.x-only</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 0],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only-expected.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only-expected.html
new file mode 100644
index 0000000000..d00eec6b57
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur.y-only</title>
+<h1>2d.filter.layers.gaussianBlur.y-only</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="0 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only.html
new file mode 100644
index 0000000000..59421a1ff3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.gaussianBlur.y-only.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur.y-only-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.y-only</title>
+<h1>2d.filter.layers.gaussianBlur.y-only</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [0, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.turbulence.inputTypes.html b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.turbulence.inputTypes.html
new file mode 100644
index 0000000000..26dceaae16
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/filters/2d.filter.layers.turbulence.inputTypes.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.turbulence.inputTypes</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.filter.layers.turbulence.inputTypes</h1>
+<p class="desc">Test exceptions on CanvasFilter() turbulence object</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Test exceptions on CanvasFilter() turbulence object");
+_addTest(function(canvas, ctx) {
+
+ const errorTestCases = [
+ {baseFrequency: {}},
+ {baseFrequency: -1},
+ {baseFrequency: [0, -1]},
+ {baseFrequency: NaN},
+ {baseFrequency: Infinity},
+ {baseFrequency: undefined},
+ {baseFrequency: -Infinity},
+ {baseFrequency: 'test'},
+
+ {numOctaves: {}},
+ {numOctaves: -1},
+ {numOctaves: NaN},
+ {numOctaves: Infinity},
+ {numOctaves: undefined},
+ {numOctaves: -Infinity},
+ {numOctaves: [1, 1]},
+ {numOctaves: 'test'},
+
+ {seed: {}},
+ {seed: NaN},
+ {seed: Infinity},
+ {seed: undefined},
+ {seed: -Infinity},
+ {seed: [1, 1]},
+ {seed: 'test'},
+
+ {stitchTiles: {}},
+ {stitchTiles: NaN},
+ {stitchTiles: Infinity},
+ {stitchTiles: undefined},
+ {stitchTiles: -Infinity},
+ {stitchTiles: [1, 1]},
+ {stitchTiles: 'test'},
+ {stitchTiles: null},
+ {stitchTiles: []},
+ {stitchTiles: [10]},
+ {stitchTiles: 30},
+ {stitchTiles: false},
+ {stitchTiles: true},
+ {stitchTiles: '10'},
+ {stitchTiles: -1},
+
+ {type: {}},
+ {type: NaN},
+ {type: Infinity},
+ {type: undefined},
+ {type: -Infinity},
+ {type: [1, 1]},
+ {type: 'test'},
+ {type: null},
+ {type: []},
+ {type: [10]},
+ {type: 30},
+ {type: false},
+ {type: true},
+ {type: '10'},
+ {type: -1},
+ ]
+
+ // null and [] = 0 when parsed as number
+ const workingTestCases = [
+ {baseFrequency: null},
+ {baseFrequency: []},
+ {baseFrequency: [10]},
+ {baseFrequency: [10, 3]},
+ {baseFrequency: 30},
+ {baseFrequency: false},
+ {baseFrequency: true},
+ {baseFrequency: '10'},
+
+ {numOctaves: null},
+ {numOctaves: []},
+ {numOctaves: [10]},
+ {numOctaves: 30},
+ {numOctaves: false},
+ {numOctaves: true},
+ {numOctaves: '10'},
+
+ {seed: null},
+ {seed: []},
+ {seed: [10]},
+ {seed: 30},
+ {seed: false},
+ {seed: true},
+ {seed: '10'},
+ {seed: -1},
+
+ {stitchTiles: 'stitch'},
+ {stitchTiles: 'noStitch'},
+
+ {type: 'fractalNoise'},
+ {type: 'turbulence'},
+ ]
+
+ for (testCase of errorTestCases) {
+ const filterOptions = {...{name: 'turbulence'}, ...testCase};
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter: filterOptions}); });
+ }
+
+ for (testCase of workingTestCases) {
+ const filterOptions = {...{name: 'turbulence'}, ...testCase};
+ ctx.beginLayer({filter: filterOptions});
+ ctx.endLayer();
+ }
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.filter-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.filter-expected.html
new file mode 100644
index 0000000000..5fc1ac9acd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.filter-expected.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.ctm.filter</title>
+<h1>2d.layer.ctm.filter</h1>
+<p class="desc">Checks that parent transforms affect layer filters.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="grey" />
+ </filter>
+
+ <g filter="url(#filter)">
+ <g transform="translate(30, 90) scale(2) rotate(90)">
+ <rect x="-30" y="-5" width=60 height=10></rect>
+ </g>
+ </g>
+
+ <g transform="translate(80, 90) scale(2) rotate(90)">
+ <g filter="url(#filter)">
+ <rect x="-30" y="-5" width=60 height=10></rect>
+ </g>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.filter.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.filter.html
new file mode 100644
index 0000000000..3d56ac3601
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.filter.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.ctm.filter-expected.html">
+<title>Canvas test: 2d.layer.ctm.filter</title>
+<h1>2d.layer.ctm.filter</h1>
+<p class="desc">Checks that parent transforms affect layer filters.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // Transforms inside the layer should not apply to the layer's filter.
+ ctx.beginLayer({filter: 'drop-shadow(5px 5px 0px grey)'});
+ ctx.translate(30, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+ ctx.fillRect(-30, -5, 60, 10);
+ ctx.endLayer();
+
+ // Transforms in the layer's parent should apply to the layer's filter.
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+ ctx.beginLayer({filter: 'drop-shadow(5px 5px 0px grey)'});
+ ctx.fillRect(-30, -5, 60, 10);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.getTransform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.getTransform.html
new file mode 100644
index 0000000000..7a69c59527
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.getTransform.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.ctm.getTransform</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.ctm.getTransform</h1>
+<p class="desc">Tests getTransform inside layers.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Tests getTransform inside layers.");
+_addTest(function(canvas, ctx) {
+
+ ctx.translate(10, 20);
+ ctx.beginLayer();
+ ctx.scale(2, 3);
+ const m = ctx.getTransform();
+ assert_array_equals([m.a, m.b, m.c, m.d, m.e, m.f], [2, 0, 0, 3, 10, 20]);
+ ctx.endLayer();
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.resetTransform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.resetTransform-expected.html
new file mode 100644
index 0000000000..fd4c1746c7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.resetTransform-expected.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.ctm.resetTransform</title>
+<h1>2d.layer.ctm.resetTransform</h1>
+<p class="desc">Tests resetTransform inside layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 20, 20);
+
+ ctx.translate(40, 0);
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.resetTransform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.resetTransform.html
new file mode 100644
index 0000000000..9291f8f3f2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.resetTransform.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.ctm.resetTransform-expected.html">
+<title>Canvas test: 2d.layer.ctm.resetTransform</title>
+<h1>2d.layer.ctm.resetTransform</h1>
+<p class="desc">Tests resetTransform inside layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(40, 0);
+
+ ctx.beginLayer();
+ ctx.rotate(2);
+ ctx.beginLayer();
+ ctx.scale(5, 6);
+ ctx.resetTransform();
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 20, 20);
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.setTransform-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.setTransform-expected.html
new file mode 100644
index 0000000000..45a3d095e1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.setTransform-expected.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.ctm.setTransform</title>
+<h1>2d.layer.ctm.setTransform</h1>
+<p class="desc">Tests setTransform inside layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(80, 0);
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+
+ ctx.setTransform(4, 0, 0, 2, 20, 10);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 10, 10);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.setTransform.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.setTransform.html
new file mode 100644
index 0000000000..b5d98ba45f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.setTransform.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.ctm.setTransform-expected.html">
+<title>Canvas test: 2d.layer.ctm.setTransform</title>
+<h1>2d.layer.ctm.setTransform</h1>
+<p class="desc">Tests setTransform inside layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(80, 0);
+
+ ctx.beginLayer();
+ ctx.rotate(2);
+ ctx.beginLayer();
+ ctx.scale(5, 6);
+ ctx.setTransform(4, 0, 0, 2, 20, 10);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 10, 10);
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.shadow-in-transformed-layer-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.shadow-in-transformed-layer-expected.html
new file mode 100644
index 0000000000..312ca19b4c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.shadow-in-transformed-layer-expected.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.ctm.shadow-in-transformed-layer</title>
+<h1>2d.layer.ctm.shadow-in-transformed-layer</h1>
+<p class="desc">Check shadows inside of a transformed layer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'grey';
+ ctx.fillRect(-30, -5, 60, 10);
+
+ const canvas2 = new OffscreenCanvas(100, 100);
+ const ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(0, 0, 40, 10);
+ ctx.drawImage(canvas2, -30, -30);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.shadow-in-transformed-layer.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.shadow-in-transformed-layer.html
new file mode 100644
index 0000000000..f047bd30b2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.ctm.shadow-in-transformed-layer.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.ctm.shadow-in-transformed-layer-expected.html">
+<title>Canvas test: 2d.layer.ctm.shadow-in-transformed-layer</title>
+<h1>2d.layer.ctm.shadow-in-transformed-layer</h1>
+<p class="desc">Check shadows inside of a transformed layer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+
+ ctx.beginLayer();
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'grey';
+ ctx.fillRect(-30, -5, 60, 10);
+
+ const canvas2 = new OffscreenCanvas(100, 100);
+ const ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(0, 0, 40, 10);
+ ctx.drawImage(canvas2, -30, -30);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.drawImage-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.drawImage-expected.html
new file mode 100644
index 0000000000..26f6e75214
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.drawImage-expected.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.drawImage</title>
+<h1>2d.layer.drawImage</h1>
+<p class="desc">Checks that drawImage writes the image to the layer and not the parent directly.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'skyblue';
+ ctx.fillRect(0, 0, 100, 100);
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
+ stdDeviation: 0, floodColor: 'navy'}});
+
+ ctx.fillStyle = 'maroon';
+ ctx.fillRect(20, 20, 50, 50);
+
+ ctx.globalCompositeOperation = 'xor';
+
+ // Should xor only with the layer content, not the parents'.
+ ctx.fillStyle = 'pink';
+ ctx.fillRect(40, 40, 50, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.drawImage.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.drawImage.html
new file mode 100644
index 0000000000..58206c3eb8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.drawImage.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.drawImage-expected.html">
+<title>Canvas test: 2d.layer.drawImage</title>
+<h1>2d.layer.drawImage</h1>
+<p class="desc">Checks that drawImage writes the image to the layer and not the parent directly.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'skyblue';
+ ctx.fillRect(0, 0, 100, 100);
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
+ stdDeviation: 0, floodColor: 'navy'}});
+
+ ctx.fillStyle = 'maroon';
+ ctx.fillRect(20, 20, 50, 50);
+
+ ctx.globalCompositeOperation = 'xor';
+
+ // The image should xor only with the layer content, not the parents'.
+ const canvas_image = new OffscreenCanvas(200,200);
+ const ctx_image = canvas_image.getContext("2d");
+ ctx_image.fillStyle = 'pink';
+ ctx_image.fillRect(40, 40, 50, 50);
+ ctx.drawImage(canvas_image, 0, 0);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html
index 17e0f0c8c5..98ea67e9e9 100644
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<link rel="match" href="2d.layer.global-states.filter.alpha.blending-expected.html">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-2453">
<title>Canvas test: 2d.layer.global-states.filter.alpha.blending</title>
<h1>2d.layer.global-states.filter.alpha.blending</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html
index 71a27cf710..29041d4933 100644
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<link rel="match" href="2d.layer.global-states.filter.alpha.composite-expected.html">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-5204">
<title>Canvas test: 2d.layer.global-states.filter.alpha.composite</title>
<h1>2d.layer.global-states.filter.alpha.composite</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html
index 5133aa170e..85718cffba 100644
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<link rel="match" href="2d.layer.global-states.filter.alpha-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6766">
<title>Canvas test: 2d.layer.global-states.filter.alpha</title>
<h1>2d.layer.global-states.filter.alpha</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html
index 6aa8e75a95..aaeb167ccf 100644
--- a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<link rel="match" href="2d.layer.global-states.filter.alpha.shadow-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6311">
<title>Canvas test: 2d.layer.global-states.filter.alpha.shadow</title>
<h1>2d.layer.global-states.filter.alpha.shadow</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html
index ff0eebe2e0..ea5600b006 100644
--- a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html
@@ -1,28 +1,28 @@
<body>
<svg style="display:none">>
<filter id="base">
- <feTurbulence baseFrequency="0.025"/>
+ <feTurbulence baseFrequency="0.03125"/>
</filter>
<filter id="base2d">
- <feTurbulence baseFrequency="0.025, 0.1"/>
+ <feTurbulence baseFrequency="0.03125, 0.125"/>
</filter>
<filter id="highFrequency">
- <feTurbulence baseFrequency="0.05"/>
+ <feTurbulence baseFrequency="0.0625"/>
</filter>
<filter id="seed">
- <feTurbulence baseFrequency="0.025" seed="100"/>
+ <feTurbulence baseFrequency="0.03125" seed="100"/>
</filter>
<filter id="numOctaves">
- <feTurbulence baseFrequency="0.025" numOctaves="2"/>
+ <feTurbulence baseFrequency="0.03125" numOctaves="2"/>
</filter>
<filter id="empty">
<feTurbulence/>
</filter>
<filter id="fractalNoise">
- <feTurbulence baseFrequency="0.025" type="fractalNoise"/>
+ <feTurbulence baseFrequency="0.03125" type="fractalNoise"/>
</filter>
<filter id="stitchTiles">
- <feTurbulence baseFrequency="0.025" stitchTiles="noStitch"/>
+ <feTurbulence baseFrequency="0.03125" stitchTiles="noStitch"/>
</filter>
</body>
<script>
@@ -34,4 +34,4 @@
ctx.filter = `url(#${tc.id})`;
ctx.fillRect(0, 0, 1, 1);
}
-</script> \ No newline at end of file
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html
index b5b494825e..eb0803e42e 100644
--- a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html
@@ -5,14 +5,14 @@
</body>
<script>
const testCases = [
- {baseFrequency: 0.025},
- {baseFrequency: [0.025, 0.1]},
- {baseFrequency: 0.05},
- {baseFrequency: 0.025, seed: 100},
- {baseFrequency: 0.025, numOctaves: 2},
+ {baseFrequency: 0.03125},
+ {baseFrequency: [0.03125, 0.125]},
+ {baseFrequency: 0.0625},
+ {baseFrequency: 0.03125, seed: 100},
+ {baseFrequency: 0.03125, numOctaves: 2},
{},
- {baseFrequency: 0.025, type: "fractalNoise"},
- {baseFrequency: 0.025, stitchTiles: "stitch"},
+ {baseFrequency: 0.03125, type: "fractalNoise"},
+ {baseFrequency: 0.03125, stitchTiles: "stitch"},
]
for (tc of testCases) {
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.html
index d8f14529c5..e7461eacdb 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.html
@@ -6,11 +6,11 @@
<script src="/html/canvas/resources/canvas-tests.js"></script>
<h1>2d.filter.canvasFilterObject.blur.exceptions.tentative</h1>
-<p class="desc">Test exceptions on CanvasFilter() blur.object</p>
+<p class="desc">Test exceptions on gaussianBlur filter</p>
<script>
-var t = async_test("Test exceptions on CanvasFilter() blur.object");
+var t = async_test("Test exceptions on gaussianBlur filter");
var t_pass = t.done.bind(t);
var t_fail = t.step_func(function(reason) {
throw reason;
@@ -20,12 +20,18 @@ t.step(function() {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur'}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: undefined}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: 'foo'}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: [1,2,3]}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: NaN}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: 'foo'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: [1,2,3]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: {}}); });
t.done();
});
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.worker.js
index 9b3fb3c04c..1c27168968 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.tentative.worker.js
@@ -1,12 +1,12 @@
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.filter.canvasFilterObject.blur.exceptions.tentative
-// Description:Test exceptions on CanvasFilter() blur.object
+// Description:Test exceptions on gaussianBlur filter
// Note:
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Test exceptions on CanvasFilter() blur.object");
+var t = async_test("Test exceptions on gaussianBlur filter");
var t_pass = t.done.bind(t);
var t_fail = t.step_func(function(reason) {
throw reason;
@@ -16,12 +16,18 @@ t.step(function() {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur'}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: undefined}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: 'foo'}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: [1,2,3]}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: NaN}); });
- assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: 'foo'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: [1,2,3]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'gaussianBlur', stdDeviation: {}}); });
t.done();
});
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.html
index 242094d9f9..0370c1387b 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.html
@@ -6,11 +6,11 @@
<script src="/html/canvas/resources/canvas-tests.js"></script>
<h1>2d.filter.canvasFilterObject.colorMatrix.tentative</h1>
-<p class="desc">Test the functionality of ColorMatrix filters in CanvasFilter objects</p>
+<p class="desc">Test the functionality of ColorMatrix filters</p>
<script>
-var t = async_test("Test the functionality of ColorMatrix filters in CanvasFilter objects");
+var t = async_test("Test the functionality of ColorMatrix filters");
var t_pass = t.done.bind(t);
var t_fail = t.step_func(function(reason) {
throw reason;
@@ -20,38 +20,67 @@ t.step(function() {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: 'foo'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: null}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 'a']}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, Infinity]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: undefined}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: 'foo'}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: null}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: [1, 2, 3]}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 'a']}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, Infinity]}); });
+
ctx.fillStyle = '#f00';
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 0});
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 0});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 255,0,0,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 90});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 90});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,91,0,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 180});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 180});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,109,109,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 270});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 270});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 109,18,255,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'saturate', values: 0.5});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'saturate', values: 0.5});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 155,27,27,255, 2);
+
ctx.clearRect(0, 0, 100, 50);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'luminanceToAlpha'});
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'luminanceToAlpha'});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,0,0,54, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', values: [
- 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 0
- ]});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: [
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0
+ ]});
ctx.fillRect(0, 0, 50, 25);
ctx.fillStyle = '#0f0';
ctx.fillRect(50, 0, 50, 25);
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.worker.js
index d214e1d836..62e4582efd 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.colorMatrix.tentative.worker.js
@@ -1,12 +1,12 @@
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.filter.canvasFilterObject.colorMatrix.tentative
-// Description:Test the functionality of ColorMatrix filters in CanvasFilter objects
+// Description:Test the functionality of ColorMatrix filters
// Note:
importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");
-var t = async_test("Test the functionality of ColorMatrix filters in CanvasFilter objects");
+var t = async_test("Test the functionality of ColorMatrix filters");
var t_pass = t.done.bind(t);
var t_fail = t.step_func(function(reason) {
throw reason;
@@ -16,38 +16,67 @@ t.step(function() {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: 'foo'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: null}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 'a']}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, Infinity]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: undefined}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: 'foo'}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: null}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: [1, 2, 3]}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 'a']}); });
+
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, Infinity]}); });
+
ctx.fillStyle = '#f00';
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 0});
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 0});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 255,0,0,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 90});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 90});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,91,0,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 180});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 180});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,109,109,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 270});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'hueRotate', values: 270});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 109,18,255,255, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'saturate', values: 0.5});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'saturate', values: 0.5});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 155,27,27,255, 2);
+
ctx.clearRect(0, 0, 100, 50);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'luminanceToAlpha'});
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', type: 'luminanceToAlpha'});
ctx.fillRect(0, 0, 100, 50);
_assertPixelApprox(canvas, 10,10, 0,0,0,54, 2);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', values: [
- 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 0
- ]});
+
+ ctx.filter = new CanvasFilter(
+ {name: 'colorMatrix', values: [
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0
+ ]});
ctx.fillRect(0, 0, 50, 25);
ctx.fillStyle = '#0f0';
ctx.fillRect(50, 0, 50, 25);
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html
new file mode 100644
index 0000000000..2b1c1c1c07
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with discrete type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getTransformedValue(C, V) {
+ // Get the right interval
+ const n = V.length;
+ const k = C == 1 ? n - 1 : Math.floor(C * n);
+ return V[k];
+ }
+
+ function getColor(inputColor, tableValues) {
+ const result = [0, 0, 0];
+ for (const i in inputColor) {
+ const C = inputColor[i]/255;
+ const Cprime = getTransformedValue(C, tableValues[i]);
+ result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
+ }
+ return result;
+ }
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(
+ color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.html
index ff1de6bc9c..491d073efb 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.html
@@ -1,42 +1,16 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas test: 2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</title>
<h1>2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</h1>
<p class="desc">Test pixels on CanvasFilter() componentTransfer with discrete type</p>
-
-
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
<script>
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with discrete type");
-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');
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getTransformedValue(C, V) {
- // Get the right interval
- const n = V.length;
- const k = C == 1 ? n - 1 : Math.floor(C * n);
- return V[k];
- }
-
- function getColor(inputColor, tableValues) {
- const result = [0, 0, 0];
- for (const i in inputColor) {
- const C = inputColor[i]/255;
- const Cprime = getTransformedValue(C, tableValues[i]);
- result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
- }
- return result;
- }
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
tableValuesR = [0, 0, 1, 1];
tableValuesG = [2, 0, 0.5, 3];
@@ -55,13 +29,12 @@ t.step(function() {
[50, 68, 87],
];
- for (const color of inputColors) {
- let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
- t.done();
-});
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.w.html
new file mode 100644
index 0000000000..d3a999a242
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.w.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.discrete.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.discrete.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with discrete type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ funcR: {type: 'discrete', tableValues: tableValuesR},
+ funcG: {type: 'discrete', tableValues: tableValuesG},
+ funcB: {type: 'discrete', tableValues: tableValuesB},
+ });
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.worker.js
deleted file mode 100644
index 0e68f4899f..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.discrete.tentative.worker.js
+++ /dev/null
@@ -1,62 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.filter.canvasFilterObject.componentTransfer.discrete.tentative
-// Description:Test pixels on CanvasFilter() componentTransfer with discrete type
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with discrete type");
-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');
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getTransformedValue(C, V) {
- // Get the right interval
- const n = V.length;
- const k = C == 1 ? n - 1 : Math.floor(C * n);
- return V[k];
- }
-
- function getColor(inputColor, tableValues) {
- const result = [0, 0, 0];
- for (const i in inputColor) {
- const C = inputColor[i]/255;
- const Cprime = getTransformedValue(C, tableValues[i]);
- result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
- }
- return result;
- }
-
- tableValuesR = [0, 0, 1, 1];
- tableValuesG = [2, 0, 0.5, 3];
- tableValuesB = [1, -1, 5, 0];
- ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'discrete', tableValues: tableValuesR},
- funcG: {type: 'discrete', tableValues: tableValuesG},
- funcB: {type: 'discrete', tableValues: tableValuesB},
- });
-
- const inputColors = [
- [255, 255, 255],
- [0, 0, 0],
- [127, 0, 34],
- [252, 186, 3],
- [50, 68, 87],
- ];
-
- for (const color of inputColors) {
- let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]);
- ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
- }
- t.done();
-});
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html
new file mode 100644
index 0000000000..5adc9f53e2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with gamma type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getColor(inputColor, amplitude, exponent, offset) {
+ return [
+ Math.max(0, Math.min(1, Math.pow(inputColor[0]/255,
+ exponent[0]) * amplitude[0] + offset[0])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[1]/255,
+ exponent[1]) * amplitude[1] + offset[1])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[2]/255,
+ exponent[2]) * amplitude[2] + offset[2])) * 255,
+ ];
+ }
+
+ const amplitudes = [2, 1.1, 0.5];
+ const exponents = [5, 3, 1];
+ const offsets = [0.25, 0, 0.5];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(color, amplitudes, exponents, offsets);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.html
index 64c30fc417..b262f3b1d3 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.html
@@ -1,41 +1,27 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas test: 2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</title>
<h1>2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</h1>
<p class="desc">Test pixels on CanvasFilter() componentTransfer with gamma type</p>
-
-
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
<script>
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with gamma type");
-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');
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getColor(inputColor, amplitude, exponent, offset) {
- return [
- Math.max(0, Math.min(1, Math.pow(inputColor[0]/255, exponent[0]) * amplitude[0] + offset[0])) * 255,
- Math.max(0, Math.min(1, Math.pow(inputColor[1]/255, exponent[1]) * amplitude[1] + offset[1])) * 255,
- Math.max(0, Math.min(1, Math.pow(inputColor[2]/255, exponent[2]) * amplitude[2] + offset[2])) * 255,
- ];
- }
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
const amplitudes = [2, 1.1, 0.5];
const exponents = [5, 3, 1];
const offsets = [0.25, 0, 0.5];
ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'gamma', amplitude: amplitudes[0], exponent: exponents[0], offset: offsets[0]},
- funcG: {type: 'gamma', amplitude: amplitudes[1], exponent: exponents[1], offset: offsets[1]},
- funcB: {type: 'gamma', amplitude: amplitudes[2], exponent: exponents[2], offset: offsets[2]},
+ funcR: {type: 'gamma', amplitude: amplitudes[0],
+ exponent: exponents[0], offset: offsets[0]},
+ funcG: {type: 'gamma', amplitude: amplitudes[1],
+ exponent: exponents[1], offset: offsets[1]},
+ funcB: {type: 'gamma', amplitude: amplitudes[2],
+ exponent: exponents[2], offset: offsets[2]},
});
const inputColors = [
@@ -46,13 +32,12 @@ t.step(function() {
[50, 68, 87],
];
- for (const color of inputColors) {
- let outputColor = getColor(color, amplitudes, exponents, offsets);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
- t.done();
-});
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.w.html
new file mode 100644
index 0000000000..1fe346eacf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.w.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.gamma.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.gamma.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with gamma type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ const amplitudes = [2, 1.1, 0.5];
+ const exponents = [5, 3, 1];
+ const offsets = [0.25, 0, 0.5];
+ ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ funcR: {type: 'gamma', amplitude: amplitudes[0],
+ exponent: exponents[0], offset: offsets[0]},
+ funcG: {type: 'gamma', amplitude: amplitudes[1],
+ exponent: exponents[1], offset: offsets[1]},
+ funcB: {type: 'gamma', amplitude: amplitudes[2],
+ exponent: exponents[2], offset: offsets[2]},
+ });
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.worker.js
deleted file mode 100644
index d59bc699df..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.gamma.tentative.worker.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.filter.canvasFilterObject.componentTransfer.gamma.tentative
-// Description:Test pixels on CanvasFilter() componentTransfer with gamma type
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with gamma type");
-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');
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getColor(inputColor, amplitude, exponent, offset) {
- return [
- Math.max(0, Math.min(1, Math.pow(inputColor[0]/255, exponent[0]) * amplitude[0] + offset[0])) * 255,
- Math.max(0, Math.min(1, Math.pow(inputColor[1]/255, exponent[1]) * amplitude[1] + offset[1])) * 255,
- Math.max(0, Math.min(1, Math.pow(inputColor[2]/255, exponent[2]) * amplitude[2] + offset[2])) * 255,
- ];
- }
-
- const amplitudes = [2, 1.1, 0.5];
- const exponents = [5, 3, 1];
- const offsets = [0.25, 0, 0.5];
- ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'gamma', amplitude: amplitudes[0], exponent: exponents[0], offset: offsets[0]},
- funcG: {type: 'gamma', amplitude: amplitudes[1], exponent: exponents[1], offset: offsets[1]},
- funcB: {type: 'gamma', amplitude: amplitudes[2], exponent: exponents[2], offset: offsets[2]},
- });
-
- const inputColors = [
- [255, 255, 255],
- [0, 0, 0],
- [127, 0, 34],
- [252, 186, 3],
- [50, 68, 87],
- ];
-
- for (const color of inputColors) {
- let outputColor = getColor(color, amplitudes, exponents, offsets);
- ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
- }
- t.done();
-});
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html
new file mode 100644
index 0000000000..895d531206
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.identity.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.identity.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with identity type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ let outputColor = inputColors[i];
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.html
index e0d628952e..26b6e4c702 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.html
@@ -1,24 +1,15 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas test: 2d.filter.canvasFilterObject.componentTransfer.identity.tentative</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.identity.tentative</title>
<h1>2d.filter.canvasFilterObject.componentTransfer.identity.tentative</h1>
<p class="desc">Test pixels on CanvasFilter() componentTransfer with identity type</p>
-
-
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
<script>
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with identity type");
-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');
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
ctx.filter = new CanvasFilter({name: 'componentTransfer',
funcR: {type: 'identity'},
@@ -34,12 +25,12 @@ t.step(function() {
[50, 68, 87],
];
- for (const color of inputColors) {
- ctx.fillStyle = `rgba(${color[0]}, ${color[1]}, ${color[2]}, 1)`,
- ctx.fillRect(0, 0, 10, 10);
- _assertPixel(canvas, 5, 5, color[0],color[1],color[2],255);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
- t.done();
-});
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.w.html
new file mode 100644
index 0000000000..d2216d1647
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.w.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.identity.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.identity.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.identity.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with identity type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ funcR: {type: 'identity'},
+ funcG: {type: 'identity'},
+ funcB: {type: 'identity'},
+ });
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.worker.js
deleted file mode 100644
index 1b714b58ff..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.identity.tentative.worker.js
+++ /dev/null
@@ -1,40 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.filter.canvasFilterObject.componentTransfer.identity.tentative
-// Description:Test pixels on CanvasFilter() componentTransfer with identity type
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with identity type");
-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');
-
- ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'identity'},
- funcG: {type: 'identity'},
- funcB: {type: 'identity'},
- });
-
- const inputColors = [
- [255, 255, 255],
- [0, 0, 0],
- [127, 0, 34],
- [252, 186, 3],
- [50, 68, 87],
- ];
-
- for (const color of inputColors) {
- ctx.fillStyle = `rgba(${color[0]}, ${color[1]}, ${color[2]}, 1)`,
- ctx.fillRect(0, 0, 10, 10);
- _assertPixel(canvas, 5, 5, color[0],color[1],color[2],255);
- }
- t.done();
-});
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html
new file mode 100644
index 0000000000..c4ad790d56
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.linear.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.linear.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with linear type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getColor(inputColor, slopes, intercepts) {
+ return [
+ Math.max(0, Math.min(1,
+ inputColor[0]/255 * slopes[0] + intercepts[0])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[1]/255 * slopes[1] + intercepts[1])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[2]/255 * slopes[2] + intercepts[2])) * 255,
+ ];
+ }
+
+ const slopes = [0.5, 1.2, -0.2];
+ const intercepts = [0.25, 0, 0.5];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(color, slopes, intercepts);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.html
index adbe557fd9..3fc3bd9eec 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.html
@@ -1,33 +1,16 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas test: 2d.filter.canvasFilterObject.componentTransfer.linear.tentative</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.linear.tentative</title>
<h1>2d.filter.canvasFilterObject.componentTransfer.linear.tentative</h1>
<p class="desc">Test pixels on CanvasFilter() componentTransfer with linear type</p>
-
-
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
<script>
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with linear type");
-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');
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getColor(inputColor, slopes, intercepts) {
- return [
- Math.max(0, Math.min(1, inputColor[0]/255 * slopes[0] + intercepts[0])) * 255,
- Math.max(0, Math.min(1, inputColor[1]/255 * slopes[1] + intercepts[1])) * 255,
- Math.max(0, Math.min(1, inputColor[2]/255 * slopes[2] + intercepts[2])) * 255,
- ];
- }
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
const slopes = [0.5, 1.2, -0.2];
const intercepts = [0.25, 0, 0.5];
@@ -45,13 +28,12 @@ t.step(function() {
[50, 68, 87],
];
- for (const color of inputColors) {
- let outputColor = getColor(color, slopes, intercepts);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
- t.done();
-});
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.w.html
new file mode 100644
index 0000000000..054dbce929
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.w.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.linear.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.linear.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.linear.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with linear type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ const slopes = [0.5, 1.2, -0.2];
+ const intercepts = [0.25, 0, 0.5];
+ ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ funcR: {type: 'linear', slope: slopes[0], intercept: intercepts[0]},
+ funcG: {type: 'linear', slope: slopes[1], intercept: intercepts[1]},
+ funcB: {type: 'linear', slope: slopes[2], intercept: intercepts[2]},
+ });
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.worker.js
deleted file mode 100644
index fb2e01876f..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.linear.tentative.worker.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.filter.canvasFilterObject.componentTransfer.linear.tentative
-// Description:Test pixels on CanvasFilter() componentTransfer with linear type
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with linear type");
-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');
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getColor(inputColor, slopes, intercepts) {
- return [
- Math.max(0, Math.min(1, inputColor[0]/255 * slopes[0] + intercepts[0])) * 255,
- Math.max(0, Math.min(1, inputColor[1]/255 * slopes[1] + intercepts[1])) * 255,
- Math.max(0, Math.min(1, inputColor[2]/255 * slopes[2] + intercepts[2])) * 255,
- ];
- }
-
- const slopes = [0.5, 1.2, -0.2];
- const intercepts = [0.25, 0, 0.5];
- ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'linear', slope: slopes[0], intercept: intercepts[0]},
- funcG: {type: 'linear', slope: slopes[1], intercept: intercepts[1]},
- funcB: {type: 'linear', slope: slopes[2], intercept: intercepts[2]},
- });
-
- const inputColors = [
- [255, 255, 255],
- [0, 0, 0],
- [127, 0, 34],
- [252, 186, 3],
- [50, 68, 87],
- ];
-
- for (const color of inputColors) {
- let outputColor = getColor(color, slopes, intercepts);
- ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
- }
- t.done();
-});
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html
new file mode 100644
index 0000000000..29e250614c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.table.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.table.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with table type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getTransformedValue(C, V) {
+ // Get the right interval
+ const n = V.length - 1;
+ const k = C == 1 ? n - 1 : Math.floor(C * n);
+ return V[k] + (C - k/n) * n * (V[k + 1] - V[k]);
+ }
+
+ function getColor(inputColor, tableValues) {
+ const result = [0, 0, 0];
+ for (const i in inputColor) {
+ const C = inputColor[i]/255;
+ const Cprime = getTransformedValue(C, tableValues[i]);
+ result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
+ }
+ return result;
+ }
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(
+ color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.html
index 47048b68a1..ef2da126eb 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.html
@@ -1,42 +1,16 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>OffscreenCanvas test: 2d.filter.canvasFilterObject.componentTransfer.table.tentative</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/html/canvas/resources/canvas-tests.js"></script>
-
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.table.tentative</title>
<h1>2d.filter.canvasFilterObject.componentTransfer.table.tentative</h1>
<p class="desc">Test pixels on CanvasFilter() componentTransfer with table type</p>
-
-
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
<script>
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with table type");
-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');
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getTransformedValue(C, V) {
- // Get the right interval
- const n = V.length - 1;
- const k = C == 1 ? n - 1 : Math.floor(C * n);
- return V[k] + (C - k/n) * n * (V[k + 1] - V[k]);
- }
-
- function getColor(inputColor, tableValues) {
- const result = [0, 0, 0];
- for (const i in inputColor) {
- const C = inputColor[i]/255;
- const Cprime = getTransformedValue(C, tableValues[i]);
- result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
- }
- return result;
- }
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
tableValuesR = [0, 0, 1, 1];
tableValuesG = [2, 0, 0.5, 3];
@@ -55,13 +29,12 @@ t.step(function() {
[50, 68, 87],
];
- for (const color of inputColors) {
- let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
- t.done();
-});
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.w.html
new file mode 100644
index 0000000000..f39723da8e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.w.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.canvasFilterObject.componentTransfer.table.tentative-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.canvasFilterObject.componentTransfer.table.tentative</title>
+<h1>2d.filter.canvasFilterObject.componentTransfer.table.tentative</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with table type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ funcR: {type: 'table', tableValues: tableValuesR},
+ funcG: {type: 'table', tableValues: tableValuesG},
+ funcB: {type: 'table', tableValues: tableValuesB},
+ });
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.worker.js
deleted file mode 100644
index 0799e73a58..0000000000
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.componentTransfer.table.tentative.worker.js
+++ /dev/null
@@ -1,62 +0,0 @@
-// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
-// OffscreenCanvas test in a worker:2d.filter.canvasFilterObject.componentTransfer.table.tentative
-// Description:Test pixels on CanvasFilter() componentTransfer with table type
-// Note:
-
-importScripts("/resources/testharness.js");
-importScripts("/html/canvas/resources/canvas-tests.js");
-
-var t = async_test("Test pixels on CanvasFilter() componentTransfer with table type");
-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');
-
- // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
- function getTransformedValue(C, V) {
- // Get the right interval
- const n = V.length - 1;
- const k = C == 1 ? n - 1 : Math.floor(C * n);
- return V[k] + (C - k/n) * n * (V[k + 1] - V[k]);
- }
-
- function getColor(inputColor, tableValues) {
- const result = [0, 0, 0];
- for (const i in inputColor) {
- const C = inputColor[i]/255;
- const Cprime = getTransformedValue(C, tableValues[i]);
- result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
- }
- return result;
- }
-
- tableValuesR = [0, 0, 1, 1];
- tableValuesG = [2, 0, 0.5, 3];
- tableValuesB = [1, -1, 5, 0];
- ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'table', tableValues: tableValuesR},
- funcG: {type: 'table', tableValues: tableValuesG},
- funcB: {type: 'table', tableValues: tableValuesB},
- });
-
- const inputColors = [
- [255, 255, 255],
- [0, 0, 0],
- [127, 0, 34],
- [252, 186, 3],
- [50, 68, 87],
- ];
-
- for (const color of inputColors) {
- let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]);
- ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
- }
- t.done();
-});
-done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.html
index 301d11f888..08f8860e99 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.html
@@ -20,23 +20,39 @@ t.step(function() {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', divisor: 2}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: null}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: 1}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: []}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [1]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[], []]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 2], []]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', divisor: 2}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: null}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: 1}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: []}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [1]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[], []]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 2], []]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]}); });
// This should not throw an error
- ctx.filter = new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[]]});
- ctx.filter = new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1]]});
+ ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[]]});
+ ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1]]});
t.done();
});
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.worker.js
index b4ce4d76b2..105ed67a75 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative.worker.js
@@ -16,23 +16,39 @@ t.step(function() {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', divisor: 2}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: null}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: 1}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: []}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [1]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[], []]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 2], []]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', divisor: 2}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: null}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: 1}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: []}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [1]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[], []]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1, 2], []]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]}); });
// This should not throw an error
- ctx.filter = new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[]]});
- ctx.filter = new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1]]});
+ ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[]]});
+ ctx.filter = new CanvasFilter(
+ {name: 'convolveMatrix', kernelMatrix: [[1]]});
t.done();
});
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.html
index 3e55e97e54..cdd501ba8e 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.html
@@ -20,104 +20,250 @@ t.step(function() {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
+ // Should not throw an error.
// dx
- _assert(new CanvasFilter({name: 'dropShadow', dx: 10}), "new CanvasFilter({name: 'dropShadow', dx: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: -1}), "new CanvasFilter({name: 'dropShadow', dx: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: 0.5}), "new CanvasFilter({name: 'dropShadow', dx: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: null}), "new CanvasFilter({name: 'dropShadow', dx: null})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: true}), "new CanvasFilter({name: 'dropShadow', dx: true})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: false}), "new CanvasFilter({name: 'dropShadow', dx: false})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: []}), "new CanvasFilter({name: 'dropShadow', dx: []})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: [20]}), "new CanvasFilter({name: 'dropShadow', dx: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: '30'}), "new CanvasFilter({name: 'dropShadow', dx: '30'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: '30'});
// dy
- _assert(new CanvasFilter({name: 'dropShadow', dy: 10}), "new CanvasFilter({name: 'dropShadow', dy: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: -1}), "new CanvasFilter({name: 'dropShadow', dy: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: 0.5}), "new CanvasFilter({name: 'dropShadow', dy: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: null}), "new CanvasFilter({name: 'dropShadow', dy: null})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: true}), "new CanvasFilter({name: 'dropShadow', dy: true})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: false}), "new CanvasFilter({name: 'dropShadow', dy: false})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: []}), "new CanvasFilter({name: 'dropShadow', dy: []})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: [20]}), "new CanvasFilter({name: 'dropShadow', dy: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: '30'}), "new CanvasFilter({name: 'dropShadow', dy: '30'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: '30'});
// floodOpacity
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: 10}), "new CanvasFilter({name: 'dropShadow', floodOpacity: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: -1}), "new CanvasFilter({name: 'dropShadow', floodOpacity: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: 0.5}), "new CanvasFilter({name: 'dropShadow', floodOpacity: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: null}), "new CanvasFilter({name: 'dropShadow', floodOpacity: null})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: true}), "new CanvasFilter({name: 'dropShadow', floodOpacity: true})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: false}), "new CanvasFilter({name: 'dropShadow', floodOpacity: false})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: []}), "new CanvasFilter({name: 'dropShadow', floodOpacity: []})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: [20]}), "new CanvasFilter({name: 'dropShadow', floodOpacity: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: '30'}), "new CanvasFilter({name: 'dropShadow', floodOpacity: '30'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: '30'});
+ // dx
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: '30'});
+ // dy
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: '30'});
+ // floodOpacity
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: '30'});
// stdDeviation
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: 10}), "new CanvasFilter({name: 'dropShadow', stdDeviation: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: -1}), "new CanvasFilter({name: 'dropShadow', stdDeviation: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: 0.5}), "new CanvasFilter({name: 'dropShadow', stdDeviation: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: null}), "new CanvasFilter({name: 'dropShadow', stdDeviation: null})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: true}), "new CanvasFilter({name: 'dropShadow', stdDeviation: true})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: false}), "new CanvasFilter({name: 'dropShadow', stdDeviation: false})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: []}), "new CanvasFilter({name: 'dropShadow', stdDeviation: []})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [20]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: '30'}), "new CanvasFilter({name: 'dropShadow', stdDeviation: '30'})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [10, -1]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [10, -1]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [0.5, null]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [0.5, null]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [true, false]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [true, false]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [[], [20]]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [[], [\""+(20)+"\"]]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: ['30', ['40']]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: ['30', ['40']]})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: '30'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [10, -1]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [0.5, null]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [true, false]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [[], [20]]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: ['30', ['40']]});
// floodColor
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: 'red'}), "new CanvasFilter({name: 'dropShadow', floodColor: 'red'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: 'canvas'}), "new CanvasFilter({name: 'dropShadow', floodColor: 'canvas'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'}), "new CanvasFilter({name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: '#aabbccdd'}), "new CanvasFilter({name: 'dropShadow', floodColor: '#aabbccdd'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: '#abcd'}), "new CanvasFilter({name: 'dropShadow', floodColor: '#abcd'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'red'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'canvas'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: '#aabbccdd'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: '#abcd'});
+ // Should throw a TypeError.
// dx
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: [1, 2]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: [1, 2]}); });
// dy
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: [1, 2]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: [1, 2]}); });
// floodOpacity
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: [1, 2]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: [1, 2]}); });
// stdDeviation
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, 2, 3]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, NaN]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, Infinity]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, -Infinity]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, undefined]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, 'test']}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, {}]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, [2, 3]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, 2, 3]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, NaN]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, Infinity]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, -Infinity]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, undefined]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, 'test']}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, {}]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, [2, 3]]}); });
// floodColor
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: 'rgba(NaN, 3, 2, 1)'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: 10}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: null}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'rgba(NaN, 3, 2, 1)'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 10}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: null}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: NaN}); });
t.done();
});
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.worker.js
index bd18524f28..1d56865e68 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.exceptions.tentative.worker.js
@@ -16,104 +16,250 @@ t.step(function() {
var canvas = new OffscreenCanvas(100, 50);
var ctx = canvas.getContext('2d');
+ // Should not throw an error.
// dx
- _assert(new CanvasFilter({name: 'dropShadow', dx: 10}), "new CanvasFilter({name: 'dropShadow', dx: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: -1}), "new CanvasFilter({name: 'dropShadow', dx: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: 0.5}), "new CanvasFilter({name: 'dropShadow', dx: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: null}), "new CanvasFilter({name: 'dropShadow', dx: null})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: true}), "new CanvasFilter({name: 'dropShadow', dx: true})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: false}), "new CanvasFilter({name: 'dropShadow', dx: false})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: []}), "new CanvasFilter({name: 'dropShadow', dx: []})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: [20]}), "new CanvasFilter({name: 'dropShadow', dx: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', dx: '30'}), "new CanvasFilter({name: 'dropShadow', dx: '30'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: '30'});
// dy
- _assert(new CanvasFilter({name: 'dropShadow', dy: 10}), "new CanvasFilter({name: 'dropShadow', dy: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: -1}), "new CanvasFilter({name: 'dropShadow', dy: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: 0.5}), "new CanvasFilter({name: 'dropShadow', dy: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: null}), "new CanvasFilter({name: 'dropShadow', dy: null})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: true}), "new CanvasFilter({name: 'dropShadow', dy: true})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: false}), "new CanvasFilter({name: 'dropShadow', dy: false})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: []}), "new CanvasFilter({name: 'dropShadow', dy: []})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: [20]}), "new CanvasFilter({name: 'dropShadow', dy: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', dy: '30'}), "new CanvasFilter({name: 'dropShadow', dy: '30'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: '30'});
// floodOpacity
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: 10}), "new CanvasFilter({name: 'dropShadow', floodOpacity: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: -1}), "new CanvasFilter({name: 'dropShadow', floodOpacity: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: 0.5}), "new CanvasFilter({name: 'dropShadow', floodOpacity: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: null}), "new CanvasFilter({name: 'dropShadow', floodOpacity: null})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: true}), "new CanvasFilter({name: 'dropShadow', floodOpacity: true})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: false}), "new CanvasFilter({name: 'dropShadow', floodOpacity: false})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: []}), "new CanvasFilter({name: 'dropShadow', floodOpacity: []})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: [20]}), "new CanvasFilter({name: 'dropShadow', floodOpacity: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', floodOpacity: '30'}), "new CanvasFilter({name: 'dropShadow', floodOpacity: '30'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: '30'});
+ // dx
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: '30'});
+ // dy
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: '30'});
+ // floodOpacity
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: '30'});
// stdDeviation
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: 10}), "new CanvasFilter({name: 'dropShadow', stdDeviation: 10})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: -1}), "new CanvasFilter({name: 'dropShadow', stdDeviation: -1})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: 0.5}), "new CanvasFilter({name: 'dropShadow', stdDeviation: 0.5})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: null}), "new CanvasFilter({name: 'dropShadow', stdDeviation: null})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: true}), "new CanvasFilter({name: 'dropShadow', stdDeviation: true})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: false}), "new CanvasFilter({name: 'dropShadow', stdDeviation: false})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: []}), "new CanvasFilter({name: 'dropShadow', stdDeviation: []})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [20]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [\""+(20)+"\"]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: '30'}), "new CanvasFilter({name: 'dropShadow', stdDeviation: '30'})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [10, -1]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [10, -1]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [0.5, null]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [0.5, null]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [true, false]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [true, false]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: [[], [20]]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: [[], [\""+(20)+"\"]]})");
- _assert(new CanvasFilter({name: 'dropShadow', stdDeviation: ['30', ['40']]}), "new CanvasFilter({name: 'dropShadow', stdDeviation: ['30', ['40']]})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: 10});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: -1});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: 0.5});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: null});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: true});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: false});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: []});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [20]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: '30'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [10, -1]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [0.5, null]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [true, false]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [[], [20]]});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: ['30', ['40']]});
// floodColor
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: 'red'}), "new CanvasFilter({name: 'dropShadow', floodColor: 'red'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: 'canvas'}), "new CanvasFilter({name: 'dropShadow', floodColor: 'canvas'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'}), "new CanvasFilter({name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: '#aabbccdd'}), "new CanvasFilter({name: 'dropShadow', floodColor: '#aabbccdd'})");
- _assert(new CanvasFilter({name: 'dropShadow', floodColor: '#abcd'}), "new CanvasFilter({name: 'dropShadow', floodColor: '#abcd'})");
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'red'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'canvas'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: '#aabbccdd'});
+ ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: '#abcd'});
+ // Should throw a TypeError.
// dx
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dx: [1, 2]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dx: [1, 2]}); });
// dy
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', dy: [1, 2]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', dy: [1, 2]}); });
// floodOpacity
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodOpacity: [1, 2]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodOpacity: [1, 2]}); });
// stdDeviation
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: NaN}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: -Infinity}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: {}}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, 2, 3]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, NaN]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, Infinity]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, -Infinity]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, undefined]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, 'test']}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, {}]}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', stdDeviation: [1, [2, 3]]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: -Infinity}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: {}}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, 2, 3]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, NaN]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, Infinity]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, -Infinity]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, undefined]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, 'test']}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, {}]}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', stdDeviation: [1, [2, 3]]}); });
// floodColor
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: 'test'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: 'rgba(NaN, 3, 2, 1)'}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: 10}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: undefined}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: null}); });
- assert_throws_js(TypeError, function() { new CanvasFilter({name: 'dropShadow', floodColor: NaN}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'test'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 'rgba(NaN, 3, 2, 1)'}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: 10}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: undefined}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: null}); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(
+ {name: 'dropShadow', floodColor: NaN}); });
t.done();
});
done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html
index 81eb1eae45..7569304b95 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.html
@@ -22,86 +22,58 @@
// Parameter defaults.
ctx.filter = new CanvasFilter({name: 'dropShadow'});
ctx.fillRect(10, 10, 80, 80);
-
// All parameters specified.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
floodColor: 'purple', floodOpacity: 0.7});
ctx.fillRect(110, 10, 80, 80);
-
// Named color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'purple'});
ctx.fillRect(10, 110, 80, 80);
-
// System color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'LinkText'});
ctx.fillRect(110, 110, 80, 80);
-
// Numerical color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'rgba(20, 50, 130, 1)'});
ctx.fillRect(210, 110, 80, 80);
-
// Transparent floodColor.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'rgba(20, 50, 130, 0.7)'});
ctx.fillRect(310, 110, 80, 80);
-
// Transparent floodColor and floodOpacity.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'rgba(20, 50, 130, 0.7)', floodOpacity: 0.7});
ctx.fillRect(410, 110, 80, 80);
-
// No blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
floodColor: 'purple'});
ctx.fillRect(10, 210, 80, 80);
-
// Single float blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
floodColor: 'purple'});
ctx.fillRect(110, 210, 80, 80);
-
// Single negative float blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
floodColor: 'purple'});
ctx.fillRect(210, 210, 80, 80);
-
// Two floats (X&Y) blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
floodColor: 'purple'});
ctx.fillRect(310, 210, 80, 80);
-
// Two negative floats (X&Y) blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
floodColor: 'purple'});
ctx.fillRect(410, 210, 80, 80);
-
// Degenerate parameter values.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
floodColor: 'purple', floodOpacity: [2]});
ctx.fillRect(10, 310, 80, 80);
-
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
floodColor: 'purple', floodOpacity: '0.8'});
ctx.fillRect(110, 310, 80, 80);
-
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
floodColor: 'purple', floodOpacity: ['0.4']});
ctx.fillRect(210, 310, 80, 80);
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.w.html
index fe9087244a..2a26af4ec3 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.dropShadow.tentative.w.html
@@ -24,86 +24,58 @@
// Parameter defaults.
ctx.filter = new CanvasFilter({name: 'dropShadow'});
ctx.fillRect(10, 10, 80, 80);
-
// All parameters specified.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
floodColor: 'purple', floodOpacity: 0.7});
ctx.fillRect(110, 10, 80, 80);
-
// Named color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'purple'});
ctx.fillRect(10, 110, 80, 80);
-
// System color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'LinkText'});
ctx.fillRect(110, 110, 80, 80);
-
// Numerical color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'rgba(20, 50, 130, 1)'});
ctx.fillRect(210, 110, 80, 80);
-
// Transparent floodColor.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'rgba(20, 50, 130, 0.7)'});
ctx.fillRect(310, 110, 80, 80);
-
// Transparent floodColor and floodOpacity.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
floodColor: 'rgba(20, 50, 130, 0.7)', floodOpacity: 0.7});
ctx.fillRect(410, 110, 80, 80);
-
// No blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
floodColor: 'purple'});
ctx.fillRect(10, 210, 80, 80);
-
// Single float blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
floodColor: 'purple'});
ctx.fillRect(110, 210, 80, 80);
-
// Single negative float blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
floodColor: 'purple'});
ctx.fillRect(210, 210, 80, 80);
-
// Two floats (X&Y) blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
floodColor: 'purple'});
ctx.fillRect(310, 210, 80, 80);
-
// Two negative floats (X&Y) blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
floodColor: 'purple'});
ctx.fillRect(410, 210, 80, 80);
-
// Degenerate parameter values.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
floodColor: 'purple', floodOpacity: [2]});
ctx.fillRect(10, 310, 80, 80);
-
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
floodColor: 'purple', floodOpacity: '0.8'});
ctx.fillRect(110, 310, 80, 80);
-
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
+ ctx.filter = new CanvasFilter({name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
floodColor: 'purple', floodOpacity: ['0.4']});
ctx.fillRect(210, 310, 80, 80);
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html
new file mode 100644
index 0000000000..dac31c97f1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html
index 4417a1917c..801e6fdb8c 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.w.html
index d2024ad205..6c7c7f7649 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative.w.html
@@ -1,9 +1,9 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.isotropic</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.isotropic.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html
index e76613271f..88d0cb2de2 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x-expected.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x</h1>
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<svg xmlns="http://www.w3.org/2000/svg"
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html
index 2ea26359fe..ba986d8e7b 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.w.html
index fa49ea4682..86fe086327 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative.w.html
@@ -1,9 +1,9 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-x</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-x.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html
index 0f214fca9f..744983d4ae 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y-expected.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y</h1>
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<svg xmlns="http://www.w3.org/2000/svg"
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html
index a9783ccb6a..0265cfa6c4 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.w.html
index ab83f50ea0..c22b320857 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative.w.html
@@ -1,9 +1,9 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.mostly-y</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.mostly-y.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html
index 285a641726..e611113e42 100644
--- a/testing/web-platform/tests/html/canvas/element/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only-expected.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only</h1>
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<svg xmlns="http://www.w3.org/2000/svg"
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html
index 3028c2a700..3ed8e9ddf9 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.w.html
index e8482cf3ed..35cbc1b365 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative.w.html
@@ -1,9 +1,9 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.x-only</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.x-only.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html
index d59945b5da..c6d915cb07 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only-expected.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only</h1>
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<svg xmlns="http://www.w3.org/2000/svg"
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html
index fca324716b..f563ad9d77 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.w.html
index 50cfb3083a..171a41caa8 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative.w.html
@@ -1,9 +1,9 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
-<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only-expected.html">
-<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only</title>
-<h1>2d.filter.canvasFilterObject.gaussianBlur.tentative.y-only</h1>
+<link rel="match" href="2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative-expected.html">
+<title>Canvas test: 2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</title>
+<h1>2d.filter.canvasFilterObject.gaussianBlur.y-only.tentative</h1>
<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
<canvas id="canvas" width="100" height="100">
<p class="fallback">FAIL (fallback content)</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.html
index 040c62a96b..8ad2a5ccfb 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.html
@@ -117,12 +117,12 @@ t.step(function() {
for (testCase of errorTestCases) {
const filterOptions = {...{name: 'turbulence'}, ...testCase};
- assert_throws_js(TypeError, function() { new CanvasFilter(filterOptions); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(filterOptions); });
}
for (testCase of workingTestCases) {
const filterOptions = {...{name: 'turbulence'}, ...testCase};
- _assert(new CanvasFilter(filterOptions) != null, "new CanvasFilter(filterOptions) != null");
+ ctx.filter = new CanvasFilter(filterOptions);
}
t.done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.worker.js
index 1a950a9207..16199cb0ec 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.worker.js
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.turbulence.inputTypes.tentative.worker.js
@@ -113,12 +113,12 @@ t.step(function() {
for (testCase of errorTestCases) {
const filterOptions = {...{name: 'turbulence'}, ...testCase};
- assert_throws_js(TypeError, function() { new CanvasFilter(filterOptions); });
+ assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter(filterOptions); });
}
for (testCase of workingTestCases) {
const filterOptions = {...{name: 'turbulence'}, ...testCase};
- _assert(new CanvasFilter(filterOptions) != null, "new CanvasFilter(filterOptions) != null");
+ ctx.filter = new CanvasFilter(filterOptions);
}
t.done();
});
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.blur.exceptions.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.blur.exceptions.html
new file mode 100644
index 0000000000..36dd856456
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.blur.exceptions.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.filter.layers.blur.exceptions</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.filter.layers.blur.exceptions</h1>
+<p class="desc">Test exceptions on gaussianBlur filter</p>
+
+
+<script>
+var t = async_test("Test exceptions on gaussianBlur filter");
+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');
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur'}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: undefined}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: 'foo'}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: [1,2,3]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: NaN}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: {}}}); });
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.blur.exceptions.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.blur.exceptions.worker.js
new file mode 100644
index 0000000000..a053b8113c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.blur.exceptions.worker.js
@@ -0,0 +1,33 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.filter.layers.blur.exceptions
+// Description:Test exceptions on gaussianBlur filter
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("Test exceptions on gaussianBlur filter");
+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');
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur'}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: undefined}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: 'foo'}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: [1,2,3]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: NaN}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'gaussianBlur', stdDeviation: {}}}); });
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.colorMatrix.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.colorMatrix.html
new file mode 100644
index 0000000000..9e12acbbe0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.colorMatrix.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.filter.layers.colorMatrix</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.filter.layers.colorMatrix</h1>
+<p class="desc">Test the functionality of ColorMatrix filters</p>
+
+
+<script>
+var t = async_test("Test the functionality of ColorMatrix filters");
+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');
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: undefined}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: 'foo'}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: null}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: [1, 2, 3]}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 'a']}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, Infinity]}}); });
+
+ ctx.fillStyle = '#f00';
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 0}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 255,0,0,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 90}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,91,0,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 180}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,109,109,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 270}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 109,18,255,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'saturate', values: 0.5}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 155,27,27,255, 2);
+
+ ctx.clearRect(0, 0, 100, 50);
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'luminanceToAlpha'}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,0,0,54, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: [
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0
+ ]}});
+ ctx.fillRect(0, 0, 50, 25);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(50, 0, 50, 25);
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 25, 50, 25);
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(50, 25, 50, 25);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,255,0,255, 2);
+ _assertPixelApprox(canvas, 60,10, 0,255,0,255, 2);
+ _assertPixelApprox(canvas, 10,30, 0,255,0,255, 2);
+ _assertPixelApprox(canvas, 60,30, 0,255,0,255, 2);
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.colorMatrix.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.colorMatrix.worker.js
new file mode 100644
index 0000000000..12cdff3868
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.colorMatrix.worker.js
@@ -0,0 +1,100 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.filter.layers.colorMatrix
+// Description:Test the functionality of ColorMatrix filters
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("Test the functionality of ColorMatrix filters");
+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');
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: undefined}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: 'foo'}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: null}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: [1, 2, 3]}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 'a']}}); });
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, Infinity]}}); });
+
+ ctx.fillStyle = '#f00';
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 0}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 255,0,0,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 90}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,91,0,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 180}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,109,109,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'hueRotate', values: 270}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 109,18,255,255, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'saturate', values: 0.5}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 155,27,27,255, 2);
+
+ ctx.clearRect(0, 0, 100, 50);
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', type: 'luminanceToAlpha'}});
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,0,0,54, 2);
+
+ ctx.beginLayer({filter:
+ {name: 'colorMatrix', values: [
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0
+ ]}});
+ ctx.fillRect(0, 0, 50, 25);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(50, 0, 50, 25);
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 25, 50, 25);
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(50, 25, 50, 25);
+ ctx.endLayer();
+ _assertPixelApprox(canvas, 10,10, 0,255,0,255, 2);
+ _assertPixelApprox(canvas, 60,10, 0,255,0,255, 2);
+ _assertPixelApprox(canvas, 10,30, 0,255,0,255, 2);
+ _assertPixelApprox(canvas, 60,30, 0,255,0,255, 2);
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete-expected.html
new file mode 100644
index 0000000000..8419953b3d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.componentTransfer.discrete</title>
+<h1>2d.filter.layers.componentTransfer.discrete</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with discrete type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getTransformedValue(C, V) {
+ // Get the right interval
+ const n = V.length;
+ const k = C == 1 ? n - 1 : Math.floor(C * n);
+ return V[k];
+ }
+
+ function getColor(inputColor, tableValues) {
+ const result = [0, 0, 0];
+ for (const i in inputColor) {
+ const C = inputColor[i]/255;
+ const Cprime = getTransformedValue(C, tableValues[i]);
+ result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
+ }
+ return result;
+ }
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(
+ color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete.html
new file mode 100644
index 0000000000..459c2f2850
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.componentTransfer.discrete-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.discrete</title>
+<h1>2d.filter.layers.componentTransfer.discrete</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with discrete type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'discrete', tableValues: tableValuesR},
+ funcG: {type: 'discrete', tableValues: tableValuesG},
+ funcB: {type: 'discrete', tableValues: tableValuesB},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete.w.html
new file mode 100644
index 0000000000..86e1d54fb7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.discrete.w.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.componentTransfer.discrete-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.discrete</title>
+<h1>2d.filter.layers.componentTransfer.discrete</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with discrete type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'discrete', tableValues: tableValuesR},
+ funcG: {type: 'discrete', tableValues: tableValuesG},
+ funcB: {type: 'discrete', tableValues: tableValuesB},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma-expected.html
new file mode 100644
index 0000000000..3e5d980896
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma-expected.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.componentTransfer.gamma</title>
+<h1>2d.filter.layers.componentTransfer.gamma</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with gamma type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getColor(inputColor, amplitude, exponent, offset) {
+ return [
+ Math.max(0, Math.min(1, Math.pow(inputColor[0]/255,
+ exponent[0]) * amplitude[0] + offset[0])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[1]/255,
+ exponent[1]) * amplitude[1] + offset[1])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[2]/255,
+ exponent[2]) * amplitude[2] + offset[2])) * 255,
+ ];
+ }
+
+ const amplitudes = [2, 1.1, 0.5];
+ const exponents = [5, 3, 1];
+ const offsets = [0.25, 0, 0.5];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(color, amplitudes, exponents, offsets);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma.html
new file mode 100644
index 0000000000..9012115adf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.componentTransfer.gamma-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.gamma</title>
+<h1>2d.filter.layers.componentTransfer.gamma</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with gamma type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ const amplitudes = [2, 1.1, 0.5];
+ const exponents = [5, 3, 1];
+ const offsets = [0.25, 0, 0.5];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'gamma', amplitude: amplitudes[0],
+ exponent: exponents[0], offset: offsets[0]},
+ funcG: {type: 'gamma', amplitude: amplitudes[1],
+ exponent: exponents[1], offset: offsets[1]},
+ funcB: {type: 'gamma', amplitude: amplitudes[2],
+ exponent: exponents[2], offset: offsets[2]},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma.w.html
new file mode 100644
index 0000000000..767bcc58e5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.gamma.w.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.componentTransfer.gamma-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.gamma</title>
+<h1>2d.filter.layers.componentTransfer.gamma</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with gamma type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ const amplitudes = [2, 1.1, 0.5];
+ const exponents = [5, 3, 1];
+ const offsets = [0.25, 0, 0.5];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'gamma', amplitude: amplitudes[0],
+ exponent: exponents[0], offset: offsets[0]},
+ funcG: {type: 'gamma', amplitude: amplitudes[1],
+ exponent: exponents[1], offset: offsets[1]},
+ funcB: {type: 'gamma', amplitude: amplitudes[2],
+ exponent: exponents[2], offset: offsets[2]},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity-expected.html
new file mode 100644
index 0000000000..9f1439f37b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity-expected.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.componentTransfer.identity</title>
+<h1>2d.filter.layers.componentTransfer.identity</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with identity type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ let outputColor = inputColors[i];
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity.html
new file mode 100644
index 0000000000..901dae3bed
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.componentTransfer.identity-expected.html">
+<title>Canvas test: 2d.filter.layers.componentTransfer.identity</title>
+<h1>2d.filter.layers.componentTransfer.identity</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with identity type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'identity'},
+ funcG: {type: 'identity'},
+ funcB: {type: 'identity'},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity.w.html
new file mode 100644
index 0000000000..2e45018755
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.identity.w.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.componentTransfer.identity-expected.html">
+<title>Canvas test: 2d.filter.layers.componentTransfer.identity</title>
+<h1>2d.filter.layers.componentTransfer.identity</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with identity type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'identity'},
+ funcG: {type: 'identity'},
+ funcB: {type: 'identity'},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear-expected.html
new file mode 100644
index 0000000000..f922055ff2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear-expected.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.componentTransfer.linear</title>
+<h1>2d.filter.layers.componentTransfer.linear</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with linear type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getColor(inputColor, slopes, intercepts) {
+ return [
+ Math.max(0, Math.min(1,
+ inputColor[0]/255 * slopes[0] + intercepts[0])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[1]/255 * slopes[1] + intercepts[1])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[2]/255 * slopes[2] + intercepts[2])) * 255,
+ ];
+ }
+
+ const slopes = [0.5, 1.2, -0.2];
+ const intercepts = [0.25, 0, 0.5];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(color, slopes, intercepts);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear.html
new file mode 100644
index 0000000000..f418b72ad5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.componentTransfer.linear-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.linear</title>
+<h1>2d.filter.layers.componentTransfer.linear</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with linear type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ const slopes = [0.5, 1.2, -0.2];
+ const intercepts = [0.25, 0, 0.5];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'linear', slope: slopes[0], intercept: intercepts[0]},
+ funcG: {type: 'linear', slope: slopes[1], intercept: intercepts[1]},
+ funcB: {type: 'linear', slope: slopes[2], intercept: intercepts[2]},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear.w.html
new file mode 100644
index 0000000000..fbc29c86c1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.linear.w.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.componentTransfer.linear-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.linear</title>
+<h1>2d.filter.layers.componentTransfer.linear</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with linear type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ const slopes = [0.5, 1.2, -0.2];
+ const intercepts = [0.25, 0, 0.5];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'linear', slope: slopes[0], intercept: intercepts[0]},
+ funcG: {type: 'linear', slope: slopes[1], intercept: intercepts[1]},
+ funcB: {type: 'linear', slope: slopes[2], intercept: intercepts[2]},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table-expected.html
new file mode 100644
index 0000000000..0f6736d87d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.componentTransfer.table</title>
+<h1>2d.filter.layers.componentTransfer.table</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with table type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
+ function getTransformedValue(C, V) {
+ // Get the right interval
+ const n = V.length - 1;
+ const k = C == 1 ? n - 1 : Math.floor(C * n);
+ return V[k] + (C - k/n) * n * (V[k + 1] - V[k]);
+ }
+
+ function getColor(inputColor, tableValues) {
+ const result = [0, 0, 0];
+ for (const i in inputColor) {
+ const C = inputColor[i]/255;
+ const Cprime = getTransformedValue(C, tableValues[i]);
+ result[i] = Math.max(0, Math.min(1, Cprime)) * 255;
+ }
+ return result;
+ }
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(
+ color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table.html
new file mode 100644
index 0000000000..ef5e0f847b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.componentTransfer.table-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.table</title>
+<h1>2d.filter.layers.componentTransfer.table</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with table type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'table', tableValues: tableValuesR},
+ funcG: {type: 'table', tableValues: tableValuesG},
+ funcB: {type: 'table', tableValues: tableValuesB},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table.w.html
new file mode 100644
index 0000000000..b11f0ef6f3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.componentTransfer.table.w.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.componentTransfer.table-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-500">
+<title>Canvas test: 2d.filter.layers.componentTransfer.table</title>
+<h1>2d.filter.layers.componentTransfer.table</h1>
+<p class="desc">Test pixels on CanvasFilter() componentTransfer with table type</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ ctx.beginLayer({filter: {name: 'componentTransfer',
+ funcR: {type: 'table', tableValues: tableValuesR},
+ funcG: {type: 'table', tableValues: tableValuesG},
+ funcB: {type: 'table', tableValues: tableValuesB},
+ }});
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.convolveMatrix.exceptions.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.convolveMatrix.exceptions.html
new file mode 100644
index 0000000000..798822f104
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.convolveMatrix.exceptions.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.filter.layers.convolveMatrix.exceptions</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.filter.layers.convolveMatrix.exceptions</h1>
+<p class="desc">Test exceptions on CanvasFilter() convolveMatrix</p>
+
+
+<script>
+var t = async_test("Test exceptions on CanvasFilter() convolveMatrix");
+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');
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix'}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', divisor: 2}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: null}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: 1}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: []}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [1]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[], []]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 2], []]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]}}); });
+ // This should not throw an error
+ ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[]]}});
+ ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1]]}});
+ ctx.endLayer();
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.convolveMatrix.exceptions.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.convolveMatrix.exceptions.worker.js
new file mode 100644
index 0000000000..fa3be89ba2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.convolveMatrix.exceptions.worker.js
@@ -0,0 +1,56 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.filter.layers.convolveMatrix.exceptions
+// Description:Test exceptions on CanvasFilter() convolveMatrix
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("Test exceptions on CanvasFilter() convolveMatrix");
+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');
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix'}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', divisor: 2}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: null}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: 1}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: []}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [1]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[], []]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1, 2], []]}}); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]}}); });
+ // This should not throw an error
+ ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[]]}});
+ ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'convolveMatrix', kernelMatrix: [[1]]}});
+ ctx.endLayer();
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow-expected.html
new file mode 100644
index 0000000000..1719d99b4a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow-expected.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.dropShadow</title>
+<h1>2d.filter.layers.dropShadow</h1>
+<p class="desc">Test CanvasFilter() dropShadow object.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width=520 height=420
+ color-interpolation-filters="sRGB">
+ <rect x=0 y=0 width=100% height=50 fill="teal" />
+ <rect x=0 y=100 width=100% height=50 fill="teal" />
+ <rect x=0 y=200 width=100% height=50 fill="teal" />
+ <rect x=0 y=300 width=100% height=50 fill="teal" />
+
+ <rect x=10 y=10 width=80 height=80 fill="crimson"
+ filter="drop-shadow(2px 2px 2px black)"/>
+ <rect x=110 y=10 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 5px rgba(128, 0, 128, 0.7))"/>
+
+ <rect x=10 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px purple)"/>
+ <rect x=110 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px LinkText)"/>
+ <rect x=210 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px rgba(20, 50, 130, 1))"/>
+ <rect x=310 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px rgba(20, 50, 130, 0.7))"/>
+ <rect x=410 y=110 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 3px rgba(20, 50, 130, 0.49))"/>
+
+ <rect x=10 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 0px purple)"/>
+ <rect x=110 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 5px purple)"/>
+ <rect x=210 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 0px purple)"/>
+ <filter id="separable-filter"
+ x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx=9 dy=12 stdDeviation="3 5" flood-color="purple"/>
+ </filter>
+ <rect x=310 y=210 width=80 height=80 fill="crimson"
+ filter="url(#separable-filter)"/>
+ <rect x=410 y=210 width=80 height=80 fill="crimson"
+ filter="drop-shadow(9px 12px 0px purple)"/>
+
+ <rect x=10 y=310 width=80 height=80 fill="crimson"
+ filter="drop-shadow(-5px 0px 0px purple)"/>
+ <filter id="separable-filter-degenerate"
+ x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx=0 dy=5 stdDeviation="0 3"
+ flood-color="rgba(128, 0, 128, 0.8)"/>
+ </filter>
+ <rect x=110 y=310 width=80 height=80 fill="crimson"
+ filter="url(#separable-filter-degenerate)"/>
+ <rect x=210 y=310 width=80 height=80 fill="crimson"
+ filter="drop-shadow(1px 10px 0px rgba(128, 0, 128, 0.4))"/>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.exceptions.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.exceptions.html
new file mode 100644
index 0000000000..10392dea5a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.exceptions.html
@@ -0,0 +1,270 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.filter.layers.dropShadow.exceptions</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.filter.layers.dropShadow.exceptions</h1>
+<p class="desc">Test exceptions on CanvasFilter() dropShadow object</p>
+
+
+<script>
+var t = async_test("Test exceptions on CanvasFilter() dropShadow object");
+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');
+
+ // Should not throw an error.
+ // dx
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: '30'}}); ctx.endLayer();
+ // dy
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: '30'}}); ctx.endLayer();
+ // floodOpacity
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: '30'}}); ctx.endLayer();
+ // dx
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: '30'}}); ctx.endLayer();
+ // dy
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: '30'}}); ctx.endLayer();
+ // floodOpacity
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: '30'}}); ctx.endLayer();
+ // stdDeviation
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: '30'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [10, -1]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [0.5, null]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [true, false]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [[], [20]]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: ['30', ['40']]}}); ctx.endLayer();
+ // floodColor
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'red'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'canvas'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: '#aabbccdd'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: '#abcd'}}); ctx.endLayer();
+
+ // Should throw a TypeError.
+ // dx
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: [1, 2]}}); ctx.endLayer(); });
+ // dy
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: [1, 2]}}); ctx.endLayer(); });
+ // floodOpacity
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: [1, 2]}}); ctx.endLayer(); });
+ // stdDeviation
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, 2, 3]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, NaN]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, Infinity]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, -Infinity]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, undefined]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, 'test']}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, {}]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, [2, 3]]}}); ctx.endLayer(); });
+ // floodColor
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'rgba(NaN, 3, 2, 1)'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 10}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: null}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: NaN}}); ctx.endLayer(); });
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.exceptions.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.exceptions.worker.js
new file mode 100644
index 0000000000..86b8c56af6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.exceptions.worker.js
@@ -0,0 +1,265 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.filter.layers.dropShadow.exceptions
+// Description:Test exceptions on CanvasFilter() dropShadow object
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("Test exceptions on CanvasFilter() dropShadow object");
+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');
+
+ // Should not throw an error.
+ // dx
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: '30'}}); ctx.endLayer();
+ // dy
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: '30'}}); ctx.endLayer();
+ // floodOpacity
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: '30'}}); ctx.endLayer();
+ // dx
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: '30'}}); ctx.endLayer();
+ // dy
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: '30'}}); ctx.endLayer();
+ // floodOpacity
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: '30'}}); ctx.endLayer();
+ // stdDeviation
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: 10}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: -1}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: 0.5}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: null}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: true}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: false}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: []}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [20]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: '30'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [10, -1]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [0.5, null]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [true, false]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [[], [20]]}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: ['30', ['40']]}}); ctx.endLayer();
+ // floodColor
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'red'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'canvas'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'rgba(4, -3, 0.5, 1)'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: '#aabbccdd'}}); ctx.endLayer();
+ ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: '#abcd'}}); ctx.endLayer();
+
+ // Should throw a TypeError.
+ // dx
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dx: [1, 2]}}); ctx.endLayer(); });
+ // dy
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', dy: [1, 2]}}); ctx.endLayer(); });
+ // floodOpacity
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodOpacity: [1, 2]}}); ctx.endLayer(); });
+ // stdDeviation
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: NaN}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: -Infinity}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: {}}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, 2, 3]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, NaN]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, Infinity]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, -Infinity]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, undefined]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, 'test']}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, {}]}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', stdDeviation: [1, [2, 3]]}}); ctx.endLayer(); });
+ // floodColor
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'test'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 'rgba(NaN, 3, 2, 1)'}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: 10}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: undefined}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: null}}); ctx.endLayer(); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter:
+ {name: 'dropShadow', floodColor: NaN}}); ctx.endLayer(); });
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.html
new file mode 100644
index 0000000000..1ecf309fc4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.dropShadow-expected.html">
+<title>Canvas test: 2d.filter.layers.dropShadow</title>
+<h1>2d.filter.layers.dropShadow</h1>
+<p class="desc">Test CanvasFilter() dropShadow object.</p>
+<canvas id="canvas" width="520" height="420">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(520, 420);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(0, 0, 520, 50);
+ ctx.fillRect(0, 100, 520, 50);
+ ctx.fillRect(0, 200, 520, 50);
+ ctx.fillRect(0, 300, 520, 50);
+
+ ctx.fillStyle = 'crimson';
+
+ // Parameter defaults.
+ ctx.beginLayer({filter: {name: 'dropShadow'}});
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+ // All parameters specified.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ floodColor: 'purple', floodOpacity: 0.7}});
+ ctx.fillRect(110, 10, 80, 80);
+ ctx.endLayer();
+ // Named color.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'purple'}});
+ ctx.fillRect(10, 110, 80, 80);
+ ctx.endLayer();
+ // System color.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'LinkText'}});
+ ctx.fillRect(110, 110, 80, 80);
+ ctx.endLayer();
+ // Numerical color.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 1)'}});
+ ctx.fillRect(210, 110, 80, 80);
+ ctx.endLayer();
+ // Transparent floodColor.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 0.7)'}});
+ ctx.fillRect(310, 110, 80, 80);
+ ctx.endLayer();
+ // Transparent floodColor and floodOpacity.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 0.7)', floodOpacity: 0.7}});
+ ctx.fillRect(410, 110, 80, 80);
+ ctx.endLayer();
+ // No blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
+ floodColor: 'purple'}});
+ ctx.fillRect(10, 210, 80, 80);
+ ctx.endLayer();
+ // Single float blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ floodColor: 'purple'}});
+ ctx.fillRect(110, 210, 80, 80);
+ ctx.endLayer();
+ // Single negative float blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
+ floodColor: 'purple'}});
+ ctx.fillRect(210, 210, 80, 80);
+ ctx.endLayer();
+ // Two floats (X&Y) blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
+ floodColor: 'purple'}});
+ ctx.fillRect(310, 210, 80, 80);
+ ctx.endLayer();
+ // Two negative floats (X&Y) blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
+ floodColor: 'purple'}});
+ ctx.fillRect(410, 210, 80, 80);
+ ctx.endLayer();
+ // Degenerate parameter values.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
+ floodColor: 'purple', floodOpacity: [2]}});
+ ctx.fillRect(10, 310, 80, 80);
+ ctx.endLayer();
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
+ floodColor: 'purple', floodOpacity: '0.8'}});
+ ctx.fillRect(110, 310, 80, 80);
+ ctx.endLayer();
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
+ floodColor: 'purple', floodOpacity: ['0.4']}});
+ ctx.fillRect(210, 310, 80, 80);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.w.html
new file mode 100644
index 0000000000..e73b573779
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.dropShadow.w.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.dropShadow-expected.html">
+<title>Canvas test: 2d.filter.layers.dropShadow</title>
+<h1>2d.filter.layers.dropShadow</h1>
+<p class="desc">Test CanvasFilter() dropShadow object.</p>
+<canvas id="canvas" width="520" height="420">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(520, 420);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(0, 0, 520, 50);
+ ctx.fillRect(0, 100, 520, 50);
+ ctx.fillRect(0, 200, 520, 50);
+ ctx.fillRect(0, 300, 520, 50);
+
+ ctx.fillStyle = 'crimson';
+
+ // Parameter defaults.
+ ctx.beginLayer({filter: {name: 'dropShadow'}});
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+ // All parameters specified.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ floodColor: 'purple', floodOpacity: 0.7}});
+ ctx.fillRect(110, 10, 80, 80);
+ ctx.endLayer();
+ // Named color.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'purple'}});
+ ctx.fillRect(10, 110, 80, 80);
+ ctx.endLayer();
+ // System color.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'LinkText'}});
+ ctx.fillRect(110, 110, 80, 80);
+ ctx.endLayer();
+ // Numerical color.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 1)'}});
+ ctx.fillRect(210, 110, 80, 80);
+ ctx.endLayer();
+ // Transparent floodColor.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 0.7)'}});
+ ctx.fillRect(310, 110, 80, 80);
+ ctx.endLayer();
+ // Transparent floodColor and floodOpacity.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 0.7)', floodOpacity: 0.7}});
+ ctx.fillRect(410, 110, 80, 80);
+ ctx.endLayer();
+ // No blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
+ floodColor: 'purple'}});
+ ctx.fillRect(10, 210, 80, 80);
+ ctx.endLayer();
+ // Single float blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ floodColor: 'purple'}});
+ ctx.fillRect(110, 210, 80, 80);
+ ctx.endLayer();
+ // Single negative float blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
+ floodColor: 'purple'}});
+ ctx.fillRect(210, 210, 80, 80);
+ ctx.endLayer();
+ // Two floats (X&Y) blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
+ floodColor: 'purple'}});
+ ctx.fillRect(310, 210, 80, 80);
+ ctx.endLayer();
+ // Two negative floats (X&Y) blur.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
+ floodColor: 'purple'}});
+ ctx.fillRect(410, 210, 80, 80);
+ ctx.endLayer();
+ // Degenerate parameter values.
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
+ floodColor: 'purple', floodOpacity: [2]}});
+ ctx.fillRect(10, 310, 80, 80);
+ ctx.endLayer();
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
+ floodColor: 'purple', floodOpacity: '0.8'}});
+ ctx.fillRect(110, 310, 80, 80);
+ ctx.endLayer();
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
+ floodColor: 'purple', floodOpacity: ['0.4']}});
+ ctx.fillRect(210, 310, 80, 80);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html
new file mode 100644
index 0000000000..4f93754862
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur.isotropic</title>
+<h1>2d.filter.layers.gaussianBlur.isotropic</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.html
new file mode 100644
index 0000000000..50a98df1be
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur.isotropic-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.isotropic</title>
+<h1>2d.filter.layers.gaussianBlur.isotropic</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.w.html
new file mode 100644
index 0000000000..a68b8e78a2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.isotropic.w.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.gaussianBlur.isotropic-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.isotropic</title>
+<h1>2d.filter.layers.gaussianBlur.isotropic</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html
new file mode 100644
index 0000000000..255270c192
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-x</title>
+<h1>2d.filter.layers.gaussianBlur.mostly-x</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 1" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.html
new file mode 100644
index 0000000000..efc634796c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur.mostly-x-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-x</title>
+<h1>2d.filter.layers.gaussianBlur.mostly-x</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 1],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.w.html
new file mode 100644
index 0000000000..7d20d78503
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-x.w.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.gaussianBlur.mostly-x-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-x</title>
+<h1>2d.filter.layers.gaussianBlur.mostly-x</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 1],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html
new file mode 100644
index 0000000000..76a46b1533
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-y</title>
+<h1>2d.filter.layers.gaussianBlur.mostly-y</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="1 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.html
new file mode 100644
index 0000000000..bdc6e66fe5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur.mostly-y-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-y</title>
+<h1>2d.filter.layers.gaussianBlur.mostly-y</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [1, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.w.html
new file mode 100644
index 0000000000..dfd6438b19
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.mostly-y.w.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.gaussianBlur.mostly-y-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.mostly-y</title>
+<h1>2d.filter.layers.gaussianBlur.mostly-y</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [1, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only-expected.html
new file mode 100644
index 0000000000..26741f9847
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur.x-only</title>
+<h1>2d.filter.layers.gaussianBlur.x-only</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="4 0" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.html
new file mode 100644
index 0000000000..0d42acb8b5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur.x-only-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.x-only</title>
+<h1>2d.filter.layers.gaussianBlur.x-only</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 0],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.w.html
new file mode 100644
index 0000000000..b235c7ad38
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.x-only.w.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.gaussianBlur.x-only-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.x-only</title>
+<h1>2d.filter.layers.gaussianBlur.x-only</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [4, 0],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only-expected.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only-expected.html
new file mode 100644
index 0000000000..d00eec6b57
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.filter.layers.gaussianBlur.y-only</title>
+<h1>2d.filter.layers.gaussianBlur.y-only</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
+ <feGaussianBlur stdDeviation="0 4" />
+ </filter>
+ <rect x="25" y="25" width="50" height="50"
+ fill="teal" filter="url(#blur)" />
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.html
new file mode 100644
index 0000000000..c9bc85d699
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.filter.layers.gaussianBlur.y-only-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.y-only</title>
+<h1>2d.filter.layers.gaussianBlur.y-only</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [0, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.w.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.w.html
new file mode 100644
index 0000000000..5deb96c255
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.gaussianBlur.y-only.w.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.filter.layers.gaussianBlur.y-only-expected.html">
+<title>Canvas test: 2d.filter.layers.gaussianBlur.y-only</title>
+<h1>2d.filter.layers.gaussianBlur.y-only</h1>
+<p class="desc">Test CanvasFilter() with gaussianBlur.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 100);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'teal';
+ ctx.beginLayer({filter: {
+ name: 'gaussianBlur',
+ stdDeviation: [0, 4],
+ }});
+ ctx.fillRect(25, 25, 50, 50);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.turbulence.inputTypes.html b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.turbulence.inputTypes.html
new file mode 100644
index 0000000000..27f7748c84
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.turbulence.inputTypes.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.filter.layers.turbulence.inputTypes</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.filter.layers.turbulence.inputTypes</h1>
+<p class="desc">Test exceptions on CanvasFilter() turbulence object</p>
+
+
+<script>
+var t = async_test("Test exceptions on CanvasFilter() turbulence object");
+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');
+
+ const errorTestCases = [
+ {baseFrequency: {}},
+ {baseFrequency: -1},
+ {baseFrequency: [0, -1]},
+ {baseFrequency: NaN},
+ {baseFrequency: Infinity},
+ {baseFrequency: undefined},
+ {baseFrequency: -Infinity},
+ {baseFrequency: 'test'},
+
+ {numOctaves: {}},
+ {numOctaves: -1},
+ {numOctaves: NaN},
+ {numOctaves: Infinity},
+ {numOctaves: undefined},
+ {numOctaves: -Infinity},
+ {numOctaves: [1, 1]},
+ {numOctaves: 'test'},
+
+ {seed: {}},
+ {seed: NaN},
+ {seed: Infinity},
+ {seed: undefined},
+ {seed: -Infinity},
+ {seed: [1, 1]},
+ {seed: 'test'},
+
+ {stitchTiles: {}},
+ {stitchTiles: NaN},
+ {stitchTiles: Infinity},
+ {stitchTiles: undefined},
+ {stitchTiles: -Infinity},
+ {stitchTiles: [1, 1]},
+ {stitchTiles: 'test'},
+ {stitchTiles: null},
+ {stitchTiles: []},
+ {stitchTiles: [10]},
+ {stitchTiles: 30},
+ {stitchTiles: false},
+ {stitchTiles: true},
+ {stitchTiles: '10'},
+ {stitchTiles: -1},
+
+ {type: {}},
+ {type: NaN},
+ {type: Infinity},
+ {type: undefined},
+ {type: -Infinity},
+ {type: [1, 1]},
+ {type: 'test'},
+ {type: null},
+ {type: []},
+ {type: [10]},
+ {type: 30},
+ {type: false},
+ {type: true},
+ {type: '10'},
+ {type: -1},
+ ]
+
+ // null and [] = 0 when parsed as number
+ const workingTestCases = [
+ {baseFrequency: null},
+ {baseFrequency: []},
+ {baseFrequency: [10]},
+ {baseFrequency: [10, 3]},
+ {baseFrequency: 30},
+ {baseFrequency: false},
+ {baseFrequency: true},
+ {baseFrequency: '10'},
+
+ {numOctaves: null},
+ {numOctaves: []},
+ {numOctaves: [10]},
+ {numOctaves: 30},
+ {numOctaves: false},
+ {numOctaves: true},
+ {numOctaves: '10'},
+
+ {seed: null},
+ {seed: []},
+ {seed: [10]},
+ {seed: 30},
+ {seed: false},
+ {seed: true},
+ {seed: '10'},
+ {seed: -1},
+
+ {stitchTiles: 'stitch'},
+ {stitchTiles: 'noStitch'},
+
+ {type: 'fractalNoise'},
+ {type: 'turbulence'},
+ ]
+
+ for (testCase of errorTestCases) {
+ const filterOptions = {...{name: 'turbulence'}, ...testCase};
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter: filterOptions}); });
+ }
+
+ for (testCase of workingTestCases) {
+ const filterOptions = {...{name: 'turbulence'}, ...testCase};
+ ctx.beginLayer({filter: filterOptions});
+ ctx.endLayer();
+ }
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.turbulence.inputTypes.worker.js b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.turbulence.inputTypes.worker.js
new file mode 100644
index 0000000000..3728566c99
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/filters/2d.filter.layers.turbulence.inputTypes.worker.js
@@ -0,0 +1,126 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.filter.layers.turbulence.inputTypes
+// Description:Test exceptions on CanvasFilter() turbulence object
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("Test exceptions on CanvasFilter() turbulence object");
+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');
+
+ const errorTestCases = [
+ {baseFrequency: {}},
+ {baseFrequency: -1},
+ {baseFrequency: [0, -1]},
+ {baseFrequency: NaN},
+ {baseFrequency: Infinity},
+ {baseFrequency: undefined},
+ {baseFrequency: -Infinity},
+ {baseFrequency: 'test'},
+
+ {numOctaves: {}},
+ {numOctaves: -1},
+ {numOctaves: NaN},
+ {numOctaves: Infinity},
+ {numOctaves: undefined},
+ {numOctaves: -Infinity},
+ {numOctaves: [1, 1]},
+ {numOctaves: 'test'},
+
+ {seed: {}},
+ {seed: NaN},
+ {seed: Infinity},
+ {seed: undefined},
+ {seed: -Infinity},
+ {seed: [1, 1]},
+ {seed: 'test'},
+
+ {stitchTiles: {}},
+ {stitchTiles: NaN},
+ {stitchTiles: Infinity},
+ {stitchTiles: undefined},
+ {stitchTiles: -Infinity},
+ {stitchTiles: [1, 1]},
+ {stitchTiles: 'test'},
+ {stitchTiles: null},
+ {stitchTiles: []},
+ {stitchTiles: [10]},
+ {stitchTiles: 30},
+ {stitchTiles: false},
+ {stitchTiles: true},
+ {stitchTiles: '10'},
+ {stitchTiles: -1},
+
+ {type: {}},
+ {type: NaN},
+ {type: Infinity},
+ {type: undefined},
+ {type: -Infinity},
+ {type: [1, 1]},
+ {type: 'test'},
+ {type: null},
+ {type: []},
+ {type: [10]},
+ {type: 30},
+ {type: false},
+ {type: true},
+ {type: '10'},
+ {type: -1},
+ ]
+
+ // null and [] = 0 when parsed as number
+ const workingTestCases = [
+ {baseFrequency: null},
+ {baseFrequency: []},
+ {baseFrequency: [10]},
+ {baseFrequency: [10, 3]},
+ {baseFrequency: 30},
+ {baseFrequency: false},
+ {baseFrequency: true},
+ {baseFrequency: '10'},
+
+ {numOctaves: null},
+ {numOctaves: []},
+ {numOctaves: [10]},
+ {numOctaves: 30},
+ {numOctaves: false},
+ {numOctaves: true},
+ {numOctaves: '10'},
+
+ {seed: null},
+ {seed: []},
+ {seed: [10]},
+ {seed: 30},
+ {seed: false},
+ {seed: true},
+ {seed: '10'},
+ {seed: -1},
+
+ {stitchTiles: 'stitch'},
+ {stitchTiles: 'noStitch'},
+
+ {type: 'fractalNoise'},
+ {type: 'turbulence'},
+ ]
+
+ for (testCase of errorTestCases) {
+ const filterOptions = {...{name: 'turbulence'}, ...testCase};
+ assert_throws_js(TypeError, function() { ctx.beginLayer({filter: filterOptions}); });
+ }
+
+ for (testCase of workingTestCases) {
+ const filterOptions = {...{name: 'turbulence'}, ...testCase};
+ ctx.beginLayer({filter: filterOptions});
+ ctx.endLayer();
+ }
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter-expected.html
new file mode 100644
index 0000000000..5fc1ac9acd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter-expected.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.ctm.filter</title>
+<h1>2d.layer.ctm.filter</h1>
+<p class="desc">Checks that parent transforms affect layer filters.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="grey" />
+ </filter>
+
+ <g filter="url(#filter)">
+ <g transform="translate(30, 90) scale(2) rotate(90)">
+ <rect x="-30" y="-5" width=60 height=10></rect>
+ </g>
+ </g>
+
+ <g transform="translate(80, 90) scale(2) rotate(90)">
+ <g filter="url(#filter)">
+ <rect x="-30" y="-5" width=60 height=10></rect>
+ </g>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter.html
new file mode 100644
index 0000000000..e5efc24bcc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.ctm.filter-expected.html">
+<title>Canvas test: 2d.layer.ctm.filter</title>
+<h1>2d.layer.ctm.filter</h1>
+<p class="desc">Checks that parent transforms affect layer filters.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // Transforms inside the layer should not apply to the layer's filter.
+ ctx.beginLayer({filter: 'drop-shadow(5px 5px 0px grey)'});
+ ctx.translate(30, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+ ctx.fillRect(-30, -5, 60, 10);
+ ctx.endLayer();
+
+ // Transforms in the layer's parent should apply to the layer's filter.
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+ ctx.beginLayer({filter: 'drop-shadow(5px 5px 0px grey)'});
+ ctx.fillRect(-30, -5, 60, 10);
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter.w.html
new file mode 100644
index 0000000000..760a65e2c8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.filter.w.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.layer.ctm.filter-expected.html">
+<title>Canvas test: 2d.layer.ctm.filter</title>
+<h1>2d.layer.ctm.filter</h1>
+<p class="desc">Checks that parent transforms affect layer filters.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ // Transforms inside the layer should not apply to the layer's filter.
+ ctx.beginLayer({filter: 'drop-shadow(5px 5px 0px grey)'});
+ ctx.translate(30, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+ ctx.fillRect(-30, -5, 60, 10);
+ ctx.endLayer();
+
+ // Transforms in the layer's parent should apply to the layer's filter.
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+ ctx.beginLayer({filter: 'drop-shadow(5px 5px 0px grey)'});
+ ctx.fillRect(-30, -5, 60, 10);
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.html
new file mode 100644
index 0000000000..b2306d95ac
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.layer.ctm.getTransform</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.layer.ctm.getTransform</h1>
+<p class="desc">Tests getTransform inside layers.</p>
+
+
+<script>
+var t = async_test("Tests getTransform inside layers.");
+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');
+
+ ctx.translate(10, 20);
+ ctx.beginLayer();
+ ctx.scale(2, 3);
+ const m = ctx.getTransform();
+ assert_array_equals([m.a, m.b, m.c, m.d, m.e, m.f], [2, 0, 0, 3, 10, 20]);
+ ctx.endLayer();
+ t.done();
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.worker.js b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.worker.js
new file mode 100644
index 0000000000..54b1fee5d0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.getTransform.worker.js
@@ -0,0 +1,27 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.layer.ctm.getTransform
+// Description:Tests getTransform inside layers.
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+var t = async_test("Tests getTransform inside layers.");
+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');
+
+ ctx.translate(10, 20);
+ ctx.beginLayer();
+ ctx.scale(2, 3);
+ const m = ctx.getTransform();
+ assert_array_equals([m.a, m.b, m.c, m.d, m.e, m.f], [2, 0, 0, 3, 10, 20]);
+ ctx.endLayer();
+ t.done();
+});
+done();
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform-expected.html
new file mode 100644
index 0000000000..fd4c1746c7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform-expected.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.ctm.resetTransform</title>
+<h1>2d.layer.ctm.resetTransform</h1>
+<p class="desc">Tests resetTransform inside layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 20, 20);
+
+ ctx.translate(40, 0);
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform.html
new file mode 100644
index 0000000000..9508b34044
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.ctm.resetTransform-expected.html">
+<title>Canvas test: 2d.layer.ctm.resetTransform</title>
+<h1>2d.layer.ctm.resetTransform</h1>
+<p class="desc">Tests resetTransform inside layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 50);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(40, 0);
+
+ ctx.beginLayer();
+ ctx.rotate(2);
+ ctx.beginLayer();
+ ctx.scale(5, 6);
+ ctx.resetTransform();
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 20, 20);
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform.w.html
new file mode 100644
index 0000000000..7bf63e1473
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.resetTransform.w.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.layer.ctm.resetTransform-expected.html">
+<title>Canvas test: 2d.layer.ctm.resetTransform</title>
+<h1>2d.layer.ctm.resetTransform</h1>
+<p class="desc">Tests resetTransform inside layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 50);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(40, 0);
+
+ ctx.beginLayer();
+ ctx.rotate(2);
+ ctx.beginLayer();
+ ctx.scale(5, 6);
+ ctx.resetTransform();
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 20, 20);
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform-expected.html
new file mode 100644
index 0000000000..45a3d095e1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform-expected.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.ctm.setTransform</title>
+<h1>2d.layer.ctm.setTransform</h1>
+<p class="desc">Tests setTransform inside layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(80, 0);
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+
+ ctx.setTransform(4, 0, 0, 2, 20, 10);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 10, 10);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform.html
new file mode 100644
index 0000000000..91034943b6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.ctm.setTransform-expected.html">
+<title>Canvas test: 2d.layer.ctm.setTransform</title>
+<h1>2d.layer.ctm.setTransform</h1>
+<p class="desc">Tests setTransform inside layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(100, 50);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(80, 0);
+
+ ctx.beginLayer();
+ ctx.rotate(2);
+ ctx.beginLayer();
+ ctx.scale(5, 6);
+ ctx.setTransform(4, 0, 0, 2, 20, 10);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 10, 10);
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform.w.html
new file mode 100644
index 0000000000..8b1ea1ce51
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.setTransform.w.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.layer.ctm.setTransform-expected.html">
+<title>Canvas test: 2d.layer.ctm.setTransform</title>
+<h1>2d.layer.ctm.setTransform</h1>
+<p class="desc">Tests setTransform inside layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(100, 50);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(80, 0);
+
+ ctx.beginLayer();
+ ctx.rotate(2);
+ ctx.beginLayer();
+ ctx.scale(5, 6);
+ ctx.setTransform(4, 0, 0, 2, 20, 10);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 10, 10);
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer-expected.html
new file mode 100644
index 0000000000..312ca19b4c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer-expected.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.ctm.shadow-in-transformed-layer</title>
+<h1>2d.layer.ctm.shadow-in-transformed-layer</h1>
+<p class="desc">Check shadows inside of a transformed layer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'grey';
+ ctx.fillRect(-30, -5, 60, 10);
+
+ const canvas2 = new OffscreenCanvas(100, 100);
+ const ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(0, 0, 40, 10);
+ ctx.drawImage(canvas2, -30, -30);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer.html
new file mode 100644
index 0000000000..59305076f0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.ctm.shadow-in-transformed-layer-expected.html">
+<title>Canvas test: 2d.layer.ctm.shadow-in-transformed-layer</title>
+<h1>2d.layer.ctm.shadow-in-transformed-layer</h1>
+<p class="desc">Check shadows inside of a transformed layer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+
+ ctx.beginLayer();
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'grey';
+ ctx.fillRect(-30, -5, 60, 10);
+
+ const canvas2 = new OffscreenCanvas(100, 100);
+ const ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(0, 0, 40, 10);
+ ctx.drawImage(canvas2, -30, -30);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer.w.html
new file mode 100644
index 0000000000..486a028335
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.ctm.shadow-in-transformed-layer.w.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.layer.ctm.shadow-in-transformed-layer-expected.html">
+<title>Canvas test: 2d.layer.ctm.shadow-in-transformed-layer</title>
+<h1>2d.layer.ctm.shadow-in-transformed-layer</h1>
+<p class="desc">Check shadows inside of a transformed layer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+
+ ctx.beginLayer();
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'grey';
+ ctx.fillRect(-30, -5, 60, 10);
+
+ const canvas2 = new OffscreenCanvas(100, 100);
+ const ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(0, 0, 40, 10);
+ ctx.drawImage(canvas2, -30, -30);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage-expected.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage-expected.html
new file mode 100644
index 0000000000..26f6e75214
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage-expected.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.drawImage</title>
+<h1>2d.layer.drawImage</h1>
+<p class="desc">Checks that drawImage writes the image to the layer and not the parent directly.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'skyblue';
+ ctx.fillRect(0, 0, 100, 100);
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
+ stdDeviation: 0, floodColor: 'navy'}});
+
+ ctx.fillStyle = 'maroon';
+ ctx.fillRect(20, 20, 50, 50);
+
+ ctx.globalCompositeOperation = 'xor';
+
+ // Should xor only with the layer content, not the parents'.
+ ctx.fillStyle = 'pink';
+ ctx.fillRect(40, 40, 50, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage.html
new file mode 100644
index 0000000000..37718f6f2c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.drawImage-expected.html">
+<title>Canvas test: 2d.layer.drawImage</title>
+<h1>2d.layer.drawImage</h1>
+<p class="desc">Checks that drawImage writes the image to the layer and not the parent directly.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'skyblue';
+ ctx.fillRect(0, 0, 100, 100);
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
+ stdDeviation: 0, floodColor: 'navy'}});
+
+ ctx.fillStyle = 'maroon';
+ ctx.fillRect(20, 20, 50, 50);
+
+ ctx.globalCompositeOperation = 'xor';
+
+ // The image should xor only with the layer content, not the parents'.
+ const canvas_image = new OffscreenCanvas(200,200);
+ const ctx_image = canvas_image.getContext("2d");
+ ctx_image.fillStyle = 'pink';
+ ctx_image.fillRect(40, 40, 50, 50);
+ ctx.drawImage(canvas_image, 0, 0);
+
+ ctx.endLayer();
+
+ const outputCanvas = document.getElementById("canvas");
+ outputCanvas.getContext('2d').drawImage(canvas, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage.w.html
new file mode 100644
index 0000000000..78a235597d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.drawImage.w.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.layer.drawImage-expected.html">
+<title>Canvas test: 2d.layer.drawImage</title>
+<h1>2d.layer.drawImage</h1>
+<p class="desc">Checks that drawImage writes the image to the layer and not the parent directly.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script id='myWorker' type='text/worker'>
+ self.onmessage = function(e) {
+ const canvas = new OffscreenCanvas(200, 200);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'skyblue';
+ ctx.fillRect(0, 0, 100, 100);
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
+ stdDeviation: 0, floodColor: 'navy'}});
+
+ ctx.fillStyle = 'maroon';
+ ctx.fillRect(20, 20, 50, 50);
+
+ ctx.globalCompositeOperation = 'xor';
+
+ // The image should xor only with the layer content, not the parents'.
+ const canvas_image = new OffscreenCanvas(200,200);
+ const ctx_image = canvas_image.getContext("2d");
+ ctx_image.fillStyle = 'pink';
+ ctx_image.fillRect(40, 40, 50, 50);
+ ctx.drawImage(canvas_image, 0, 0);
+
+ ctx.endLayer();
+
+ const bitmap = canvas.transferToImageBitmap();
+ self.postMessage(bitmap, bitmap);
+ };
+</script>
+<script>
+ const blob = new Blob([document.getElementById('myWorker').textContent]);
+ const worker = new Worker(URL.createObjectURL(blob));
+ worker.addEventListener('message', msg => {
+ const outputCtx = document.getElementById("canvas").getContext('2d');
+ outputCtx.drawImage(msg.data, 0, 0);
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ worker.postMessage(null);
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.html
index be6f962b33..0e48cb49f7 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<link rel="match" href="2d.layer.global-states.filter.alpha.blending-expected.html">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-2453">
<title>Canvas test: 2d.layer.global-states.filter.alpha.blending</title>
<h1>2d.layer.global-states.filter.alpha.blending</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.w.html
index 2b53ad7c1e..3887ed4485 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.blending.w.html
@@ -2,6 +2,7 @@
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
<link rel="match" href="2d.layer.global-states.filter.alpha.blending-expected.html">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-2453">
<title>Canvas test: 2d.layer.global-states.filter.alpha.blending</title>
<h1>2d.layer.global-states.filter.alpha.blending</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.html
index 087fea88af..1a9bc8b733 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<link rel="match" href="2d.layer.global-states.filter.alpha.composite-expected.html">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-5204">
<title>Canvas test: 2d.layer.global-states.filter.alpha.composite</title>
<h1>2d.layer.global-states.filter.alpha.composite</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.w.html
index 6aa83a3278..5c90fe95aa 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.composite.w.html
@@ -2,6 +2,7 @@
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
<link rel="match" href="2d.layer.global-states.filter.alpha.composite-expected.html">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-5204">
<title>Canvas test: 2d.layer.global-states.filter.alpha.composite</title>
<h1>2d.layer.global-states.filter.alpha.composite</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html
index f1d631c25c..f64e8925f0 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<link rel="match" href="2d.layer.global-states.filter.alpha-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6766">
<title>Canvas test: 2d.layer.global-states.filter.alpha</title>
<h1>2d.layer.global-states.filter.alpha</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.html
index 2548c21181..5e8911ee17 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<link rel="match" href="2d.layer.global-states.filter.alpha.shadow-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6311">
<title>Canvas test: 2d.layer.global-states.filter.alpha.shadow</title>
<h1>2d.layer.global-states.filter.alpha.shadow</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html
index 5e1494422e..b3be7e1ac8 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.shadow.w.html
@@ -2,6 +2,7 @@
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
<link rel="match" href="2d.layer.global-states.filter.alpha.shadow-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6311">
<title>Canvas test: 2d.layer.global-states.filter.alpha.shadow</title>
<h1>2d.layer.global-states.filter.alpha.shadow</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html
index e75d668ad5..21e55f856c 100644
--- a/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html
+++ b/testing/web-platform/tests/html/canvas/offscreen/layers/2d.layer.global-states.filter.alpha.w.html
@@ -2,6 +2,7 @@
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<html class="reftest-wait">
<link rel="match" href="2d.layer.global-states.filter.alpha-expected.html">
+<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-6766">
<title>Canvas test: 2d.layer.global-states.filter.alpha</title>
<h1>2d.layer.global-states.filter.alpha</h1>
<p class="desc">Checks that layers with filters correctly use global render states.</p>
diff --git a/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py b/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py
index cf141f2f07..d7042810be 100644
--- a/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py
+++ b/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py
@@ -28,7 +28,7 @@
#
# * Test the tests, add new ones to Git, remove deleted ones from Git, etc.
-from typing import Any, List, Mapping, Optional, Set, Tuple
+from typing import Any, DefaultDict, List, Mapping, Optional, Set, Tuple
import re
import collections
@@ -184,6 +184,10 @@ def _remove_extra_newlines(text: str) -> str:
return text
def _expand_test_code(code: str) -> str:
+ code = re.sub(r' @moz-todo', '', code)
+
+ code = re.sub(r'@moz-UniversalBrowserRead;', '', code)
+
code = _remove_extra_newlines(code)
# Unroll expressions with a cross-product-style parameter expansion.
@@ -202,11 +206,13 @@ def _expand_test_code(code: str) -> str:
code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);',
r'_assertPixelApprox(canvas, \1, \2, \3);', code)
- code = re.sub(r'@assert throws (\S+_ERR) (.*);',
- r'assert_throws_dom("\1", function() { \2; });', code)
+ code = re.sub(r'@assert throws (\S+_ERR) (.*?);$',
+ r'assert_throws_dom("\1", function() { \2; });', code,
+ flags=re.MULTILINE | re.DOTALL)
- code = re.sub(r'@assert throws (\S+Error) (.*);',
- r'assert_throws_js(\1, function() { \2; });', code)
+ code = re.sub(r'@assert throws (\S+Error) (.*?);$',
+ r'assert_throws_js(\1, function() { \2; });', code,
+ flags=re.MULTILINE | re.DOTALL)
code = re.sub(
r'@assert (.*) === (.*);', lambda m: '_assertSame(%s, %s, "%s", "%s");'
@@ -226,10 +232,6 @@ def _expand_test_code(code: str) -> str:
r'@assert (.*);', lambda m: '_assert(%s, "%s");' % (m.group(
1), _escapeJS(m.group(1))), code)
- code = re.sub(r' @moz-todo', '', code)
-
- code = re.sub(r'@moz-UniversalBrowserRead;', '', code)
-
assert ('@' not in code)
return code
@@ -376,45 +378,50 @@ def _write_testharness_test(jinja_env: jinja2.Environment,
'utf-8')
+def _generate_expected_image(expected: str, name: str, sub_dir: str,
+ enabled_canvas_types: Set[CanvasType],
+ html_canvas_cfg: TestConfig,
+ offscreen_canvas_cfg: TestConfig) -> str:
+ """Creates a reference image using Cairo and returns the file location."""
+ if expected == 'green':
+ return '/images/green-100x50.png'
+ if expected == 'clear':
+ return '/images/clear-100x50.png'
+ if ';' in expected:
+ print('Found semicolon in %s' % name)
+ expected = re.sub(
+ r'^size (\d+) (\d+)',
+ r'surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \1, \2)'
+ r'\ncr = cairo.Context(surface)', expected)
+
+ if CanvasType.HTML_CANVAS in enabled_canvas_types:
+ expected_canvas = (
+ expected + "\nsurface.write_to_png('%s.png')\n" %
+ os.path.join(html_canvas_cfg.image_out_dir, sub_dir, name))
+ eval(compile(expected_canvas, '<test %s>' % name, 'exec'), {},
+ {'cairo': cairo})
+
+ if {CanvasType.OFFSCREEN_CANVAS, CanvasType.WORKER} & enabled_canvas_types:
+ expected_offscreen = (
+ expected + "\nsurface.write_to_png('%s.png')\n" %
+ os.path.join(offscreen_canvas_cfg.image_out_dir, sub_dir, name))
+ eval(compile(expected_offscreen, '<test %s>' % name, 'exec'), {},
+ {'cairo': cairo})
+
+ return '%s.png' % name
+
+
def _generate_test(test: Mapping[str, Any], jinja_env: jinja2.Environment,
- sub_dir: str, enabled_tests: Set[CanvasType],
+ name_to_sub_dir: Mapping[str, str],
+ used_tests: DefaultDict[str, Set[CanvasType]],
html_canvas_cfg: TestConfig,
offscreen_canvas_cfg: TestConfig) -> None:
_validate_test(test)
name = test['name']
- expected_img = None
- if 'expected' in test and test['expected'] is not None:
- expected = test['expected']
- if expected == 'green':
- expected_img = '/images/green-100x50.png'
- elif expected == 'clear':
- expected_img = '/images/clear-100x50.png'
- else:
- if ';' in expected:
- print('Found semicolon in %s' % name)
- expected = re.sub(
- r'^size (\d+) (\d+)',
- r'surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \1, \2)'
- r'\ncr = cairo.Context(surface)', expected)
-
- if CanvasType.HTML_CANVAS in enabled_tests:
- expected_canvas = (
- expected + "\nsurface.write_to_png('%s.png')\n" %
- os.path.join(html_canvas_cfg.image_out_dir, sub_dir, name))
- eval(compile(expected_canvas, '<test %s>' % name, 'exec'), {},
- {'cairo': cairo})
-
- if {CanvasType.OFFSCREEN_CANVAS, CanvasType.WORKER} & enabled_tests:
- expected_offscreen = (
- expected +
- "\nsurface.write_to_png('%s.png')\n" % os.path.join(
- offscreen_canvas_cfg.image_out_dir, sub_dir, name))
- eval(compile(expected_offscreen, '<test %s>' % name, 'exec'),
- {}, {'cairo': cairo})
-
- expected_img = '%s.png' % name
+ sub_dir = _get_test_sub_dir(name, name_to_sub_dir)
+ enabled_canvas_types = _get_enabled_canvas_types(test)
# Defaults:
params = {
@@ -423,11 +430,29 @@ def _generate_test(test: Mapping[str, Any], jinja_env: jinja2.Environment,
}
params.update(test)
+
+ # Render parameters used in the test name.
+ name = jinja_env.from_string(name).render(params)
+ print('\r(%s)' % name, ' ' * 32, '\t')
+
+ expected_img = None
+ if 'expected' in test and test['expected'] is not None:
+ expected_img = _generate_expected_image(test['expected'], name,
+ sub_dir, enabled_canvas_types,
+ html_canvas_cfg,
+ offscreen_canvas_cfg)
+
params.update({
'code': _expand_test_code(test['code']),
'expected_img': expected_img
})
+ already_tested = used_tests[name].intersection(enabled_canvas_types)
+ if already_tested:
+ raise InvalidTestDefinitionError(
+ f'Test {name} is defined twice for types {already_tested}')
+ used_tests[name].update(enabled_canvas_types)
+
canvas_path = os.path.join(html_canvas_cfg.out_dir, sub_dir, name)
offscreen_path = os.path.join(offscreen_canvas_cfg.out_dir, sub_dir, name)
if 'manual' in test:
@@ -435,11 +460,55 @@ def _generate_test(test: Mapping[str, Any], jinja_env: jinja2.Environment,
offscreen_path += '-manual'
if 'reference' in test or 'html_reference' in test:
- _write_reference_test(jinja_env, params, enabled_tests,
+ _write_reference_test(jinja_env, params, enabled_canvas_types,
canvas_path, offscreen_path)
else:
- _write_testharness_test(jinja_env, params, enabled_tests, canvas_path,
- offscreen_path)
+ _write_testharness_test(jinja_env, params, enabled_canvas_types,
+ canvas_path, offscreen_path)
+
+
+def _recursive_expand_variant_matrix(test_list: List[Mapping[str, Any]],
+ variant_matrix: List[Mapping[str, Any]],
+ current_selection: List[Tuple[str, Any]],
+ original_test: Mapping[str, Any]):
+ if len(current_selection) == len(variant_matrix):
+ # Selection for each variant is done, so add a new test to test_list.
+ test = original_test.copy()
+ variant_name_list = []
+ should_append_variant_names = original_test.get(
+ 'append_variants_to_name', True)
+ for variant_name, variant_params in current_selection:
+ variant_name_list.append(variant_name)
+ # Append variant name. Variant names starting with '_' are
+ # not appended, which is useful to create variants with the same
+ # name in different folders (element vs. offscreen).
+ if (should_append_variant_names
+ and not variant_name.startswith('_')):
+ test['name'] += '.' + variant_name
+ test.update(variant_params)
+ # Expose variant names as a list so they can be used from the yaml
+ # files, which helps with better naming of tests.
+ test.update({'variant_names': variant_name_list})
+ test_list.append(test)
+ else:
+ # Continue the recursion with each possible selection for the current
+ # variant.
+ variant = variant_matrix[len(current_selection)]
+ for variant_options in variant.items():
+ current_selection.append(variant_options)
+ _recursive_expand_variant_matrix(test_list, variant_matrix,
+ current_selection, original_test)
+ current_selection.pop()
+
+
+def _expand_variant_matrix(
+ variant_matrix: List[Mapping[str, Any]],
+ original_test: Mapping[str, Any]) -> List[Mapping[str, Any]]:
+ current_selection = []
+ matrix_tests = []
+ _recursive_expand_variant_matrix(matrix_tests, variant_matrix,
+ current_selection, original_test)
+ return matrix_tests
def genTestUtils_union(NAME2DIRFILE: str) -> None:
@@ -495,41 +564,25 @@ def genTestUtils_union(NAME2DIRFILE: str) -> None:
pass # Ignore if it already exists,
used_tests = collections.defaultdict(set)
- for original_test in tests:
- variants = original_test.get('variants', {'': dict()})
- for variant_name, variant_params in variants.items():
- test = original_test.copy()
- if variant_name or variant_params:
- # Append variant name. Variant names starting with '_' are
- # not appended, which is useful to create variants with the same
- # name in different folders (element vs. offscreen).
- if not variant_name.startswith('_'):
- test['name'] += '.' + variant_name
- test.update(variant_params)
-
- name = test['name']
- print('\r(%s)' % name, ' ' * 32, '\t')
-
- enabled_canvas_types = _get_enabled_canvas_types(test)
-
- already_tested = used_tests[name].intersection(
- enabled_canvas_types)
- if already_tested:
- raise InvalidTestDefinitionError(
- f'Test {name} is defined twice for types {already_tested}')
- used_tests[name].update(enabled_canvas_types)
-
- sub_dir = _get_test_sub_dir(name, name_to_sub_dir)
- _generate_test(
- test,
- jinja_env,
- sub_dir,
- enabled_canvas_types,
- html_canvas_cfg=TestConfig(
- out_dir=CANVASOUTPUTDIR,
- image_out_dir=CANVASIMAGEOUTPUTDIR),
- offscreen_canvas_cfg=TestConfig(
- out_dir=OFFSCREENCANVASOUTPUTDIR,
- image_out_dir=OFFSCREENCANVASIMAGEOUTPUTDIR))
+ for test in tests:
+ if 'variant_matrix' in test:
+ variants = _expand_variant_matrix(test['variant_matrix'], test)
+ elif 'variants' in test:
+ variant_matrix = [test['variants']]
+ variants = _expand_variant_matrix(variant_matrix, test)
+ else:
+ variants = [test]
+
+ for variant in variants:
+ _generate_test(variant,
+ jinja_env,
+ name_to_sub_dir,
+ used_tests,
+ html_canvas_cfg=TestConfig(
+ out_dir=CANVASOUTPUTDIR,
+ image_out_dir=CANVASIMAGEOUTPUTDIR),
+ offscreen_canvas_cfg=TestConfig(
+ out_dir=OFFSCREENCANVASOUTPUTDIR,
+ image_out_dir=OFFSCREENCANVASIMAGEOUTPUTDIR))
print()
diff --git a/testing/web-platform/tests/html/canvas/tools/name2dir-offscreen.yaml b/testing/web-platform/tests/html/canvas/tools/name2dir-offscreen.yaml
index c52acb793b..6e4b3f42b2 100644
--- a/testing/web-platform/tests/html/canvas/tools/name2dir-offscreen.yaml
+++ b/testing/web-platform/tests/html/canvas/tools/name2dir-offscreen.yaml
@@ -19,4 +19,4 @@
2d.missingargs: "conformance-requirements"
2d.voidreturn: "conformance-requirements"
2d.canvas.host: "canvas-host"
-2d.canvas.context: "canvas-context" \ No newline at end of file
+2d.canvas.context: "canvas-context"
diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml
index 93c556288d..09e9e00186 100644
--- a/testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml
+++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml
@@ -638,3 +638,11 @@
@nonfinite ctx.drawImage(<bitmap>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
@assert pixel 50,25 == 0,255,0,255;
expected: green
+
+- name: 2d.drawImage.detachedcanvas
+ desc: drawImage with detached OffscreenCanvas as the source should throw exception
+ canvasType: ['HTMLCanvas']
+ code: |
+ var canvas2 = new OffscreenCanvas(80, 80);
+ (new MessageChannel()).port1.postMessage(canvas2, [canvas2]);
+ @assert throws INVALID_STATE_ERR ctx.drawImage(canvas2, 0, 0);
diff --git a/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml b/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml
index 01c83a33e2..f327b9fe94 100644
--- a/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml
+++ b/testing/web-platform/tests/html/canvas/tools/yaml-new/filters.yaml
@@ -89,51 +89,102 @@
ctx.filter = 'this string is not a filter and should do nothing';
@assert ctx.filter.toString() == '[object CanvasFilter]';
-- name: 2d.filter.canvasFilterObject.blur.exceptions.tentative
- desc: Test exceptions on CanvasFilter() blur.object
+- name: 2d.filter.{{ variant_names[0] }}.blur.exceptions{{ tentative }}
+ desc: Test exceptions on gaussianBlur filter
code: |
- @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur'});
- @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: undefined});
- @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: 'foo'});
- @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: [1,2,3]});
- @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: NaN});
- @assert throws TypeError ctx.filter = new CanvasFilter({name: 'gaussianBlur', stdDeviation: {}});
-
-- name: 2d.filter.canvasFilterObject.colorMatrix.tentative
- desc: Test the functionality of ColorMatrix filters in CanvasFilter objects
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'gaussianBlur'}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'gaussianBlur', stdDeviation: undefined}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'gaussianBlur', stdDeviation: 'foo'}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'gaussianBlur', stdDeviation: [1,2,3]}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'gaussianBlur', stdDeviation: NaN}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'gaussianBlur', stdDeviation: {}}") }};
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter:
+ param})
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(
+ param)
+ tentative: .tentative
+
+- name: 2d.filter.{{ variant_names[0] }}.colorMatrix{{ tentative }}
+ desc: Test the functionality of ColorMatrix filters
code: |
- @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: undefined});
- @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: 'foo'});
- @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: null});
- @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3]});
- @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 'a']});
- @assert throws TypeError new CanvasFilter({name: 'colorMatrix', values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, Infinity]});
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix', values: undefined}") }};
+
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix', values: 'foo'}") }};
+
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix', values: null}") }};
+
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix', values: [1, 2, 3]}") }};
+
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 'a']}") }};
+
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix',
+ values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, Infinity]}") }};
+
ctx.fillStyle = '#f00';
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 0});
+ {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix', type: 'hueRotate', values: 0}") }};
ctx.fillRect(0, 0, 100, 50);
+ {{ close_layer -}}
@assert pixel 10,10 ==~ 255,0,0,255;
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 90});
+
+ {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix', type: 'hueRotate', values: 90}") }};
ctx.fillRect(0, 0, 100, 50);
+ {{ close_layer -}}
@assert pixel 10,10 ==~ 0,91,0,255;
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 180});
+
+ {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix', type: 'hueRotate', values: 180}") }};
ctx.fillRect(0, 0, 100, 50);
+ {{ close_layer -}}
@assert pixel 10,10 ==~ 0,109,109,255;
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'hueRotate', values: 270});
+
+ {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix', type: 'hueRotate', values: 270}") }};
ctx.fillRect(0, 0, 100, 50);
+ {{ close_layer -}}
@assert pixel 10,10 ==~ 109,18,255,255;
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'saturate', values: 0.5});
+
+ {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix', type: 'saturate', values: 0.5}") }};
ctx.fillRect(0, 0, 100, 50);
+ {{ close_layer -}}
@assert pixel 10,10 ==~ 155,27,27,255;
+
ctx.clearRect(0, 0, 100, 50);
- ctx.filter = new CanvasFilter({name: 'colorMatrix', type: 'luminanceToAlpha'});
+ {{ filter_declaration | replace("param",
+ "{name: 'colorMatrix', type: 'luminanceToAlpha'}") }};
ctx.fillRect(0, 0, 100, 50);
+ {{ close_layer -}}
@assert pixel 10,10 ==~ 0,0,0,54;
- ctx.filter = new CanvasFilter({name: 'colorMatrix', values: [
- 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 0
- ]});
+
+ {{ filter_declaration | replace("param", "{name: 'colorMatrix', values: [
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0
+ ]}") }};
ctx.fillRect(0, 0, 50, 25);
ctx.fillStyle = '#0f0';
ctx.fillRect(50, 0, 50, 25);
@@ -141,51 +192,120 @@
ctx.fillRect(0, 25, 50, 25);
ctx.fillStyle = '#fff';
ctx.fillRect(50, 25, 50, 25);
+ {{ close_layer -}}
@assert pixel 10,10 ==~ 0,255,0,255;
@assert pixel 60,10 ==~ 0,255,0,255;
@assert pixel 10,30 ==~ 0,255,0,255;
@assert pixel 60,30 ==~ 0,255,0,255;
-
-- name: 2d.filter.canvasFilterObject.convolveMatrix.exceptions.tentative
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter:
+ param})
+ close_layer: |
+ ctx.endLayer();
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(
+ param)
+ tentative: .tentative
+
+- name: 2d.filter.{{ variant_names[0] }}.convolveMatrix.exceptions{{ tentative }}
desc: Test exceptions on CanvasFilter() convolveMatrix
code: |
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix'});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', divisor: 2});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: null});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: 1});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: []});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [1]});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[], []]});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1, 2], []]});
- @assert throws TypeError new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]});
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix'}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', divisor: 2}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: null}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: 1}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [[1, 0], [0]]}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [[1, 'a'], [0]]}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [[1, 0], 0]}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [[1, 0], [0, Infinity]]}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: []}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [1]}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [1, 2, 3, 4]}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [[], []]}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [[1, 2], []]}") }};
+ @assert throws TypeError {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [[], [1, 2]]}") }};
// This should not throw an error
- ctx.filter = new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[]]});
- ctx.filter = new CanvasFilter({name: 'convolveMatrix', kernelMatrix: [[1]]});
-
-- name: 2d.filter.canvasFilterObject.componentTransfer.linear.tentative
+ {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [[]]}") }};
+ {{ close_layer -}}
+ {{ filter_declaration | replace("param",
+ "{name: 'convolveMatrix', kernelMatrix: [[1]]}") }};
+ {{ close_layer -}}
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter:
+ param})
+ close_layer: |
+ ctx.endLayer();
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(
+ param)
+ tentative: .tentative
+
+- name: >-
+ 2d.filter.{{ variant_names[0] }}.componentTransfer.linear{{ tentative }}
desc: Test pixels on CanvasFilter() componentTransfer with linear type
+ size: [100, 100]
+ fuzzy: maxDifference=0-2; totalPixels=0-500
code: |
+ const slopes = [0.5, 1.2, -0.2];
+ const intercepts = [0.25, 0, 0.5];
+ {{ filter_declaration | replace("param", "{name: 'componentTransfer',
+ funcR: {type: 'linear', slope: slopes[0], intercept: intercepts[0]},
+ funcG: {type: 'linear', slope: slopes[1], intercept: intercepts[1]},
+ funcB: {type: 'linear', slope: slopes[2], intercept: intercepts[2]},
+ }") }};
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ {{ close_layer }}
+ reference: |
// From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
function getColor(inputColor, slopes, intercepts) {
return [
- Math.max(0, Math.min(1, inputColor[0]/255 * slopes[0] + intercepts[0])) * 255,
- Math.max(0, Math.min(1, inputColor[1]/255 * slopes[1] + intercepts[1])) * 255,
- Math.max(0, Math.min(1, inputColor[2]/255 * slopes[2] + intercepts[2])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[0]/255 * slopes[0] + intercepts[0])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[1]/255 * slopes[1] + intercepts[1])) * 255,
+ Math.max(0, Math.min(1,
+ inputColor[2]/255 * slopes[2] + intercepts[2])) * 255,
];
}
const slopes = [0.5, 1.2, -0.2];
const intercepts = [0.25, 0, 0.5];
- ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'linear', slope: slopes[0], intercept: intercepts[0]},
- funcG: {type: 'linear', slope: slopes[1], intercept: intercepts[1]},
- funcB: {type: 'linear', slope: slopes[2], intercept: intercepts[2]},
- });
const inputColors = [
[255, 255, 255],
@@ -195,21 +315,35 @@
[50, 68, 87],
];
- for (const color of inputColors) {
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
let outputColor = getColor(color, slopes, intercepts);
- ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
-
-- name: 2d.filter.canvasFilterObject.componentTransfer.identity.tentative
+ {{ close_layer }}
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter: param})
+ close_layer: ctx.endLayer();
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(param)
+ tentative: .tentative
+
+- name: >-
+ 2d.filter.{{ variant_names[0] }}.componentTransfer.identity{{ tentative }}
desc: Test pixels on CanvasFilter() componentTransfer with identity type
+ size: [100, 100]
code: |
- ctx.filter = new CanvasFilter({name: 'componentTransfer',
+ {{ filter_declaration | replace("param", "{name: 'componentTransfer',
funcR: {type: 'identity'},
funcG: {type: 'identity'},
funcB: {type: 'identity'},
- });
+ }") }};
const inputColors = [
[255, 255, 255],
@@ -219,32 +353,86 @@
[50, 68, 87],
];
- for (const color of inputColors) {
- ctx.fillStyle = `rgba(${color[0]}, ${color[1]}, ${color[2]}, 1)`,
- ctx.fillRect(0, 0, 10, 10);
- _assertPixel(canvas, 5, 5, color[0],color[1],color[2],255);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
+ {{ close_layer }}
+ reference: |
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
-- name: 2d.filter.canvasFilterObject.componentTransfer.gamma.tentative
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ let outputColor = inputColors[i];
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter: param})
+ close_layer: ctx.endLayer();
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(param)
+ tentative: .tentative
+
+- name: >-
+ 2d.filter.{{ variant_names[0] }}.componentTransfer.gamma{{ tentative }}
desc: Test pixels on CanvasFilter() componentTransfer with gamma type
+ size: [100, 100]
+ fuzzy: maxDifference=0-2; totalPixels=0-500
code: |
+ const amplitudes = [2, 1.1, 0.5];
+ const exponents = [5, 3, 1];
+ const offsets = [0.25, 0, 0.5];
+ {{ filter_declaration | replace("param", "{name: 'componentTransfer',
+ funcR: {type: 'gamma', amplitude: amplitudes[0],
+ exponent: exponents[0], offset: offsets[0]},
+ funcG: {type: 'gamma', amplitude: amplitudes[1],
+ exponent: exponents[1], offset: offsets[1]},
+ funcB: {type: 'gamma', amplitude: amplitudes[2],
+ exponent: exponents[2], offset: offsets[2]},
+ }") }};
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ {{ close_layer }}
+ reference: |
// From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
function getColor(inputColor, amplitude, exponent, offset) {
return [
- Math.max(0, Math.min(1, Math.pow(inputColor[0]/255, exponent[0]) * amplitude[0] + offset[0])) * 255,
- Math.max(0, Math.min(1, Math.pow(inputColor[1]/255, exponent[1]) * amplitude[1] + offset[1])) * 255,
- Math.max(0, Math.min(1, Math.pow(inputColor[2]/255, exponent[2]) * amplitude[2] + offset[2])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[0]/255,
+ exponent[0]) * amplitude[0] + offset[0])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[1]/255,
+ exponent[1]) * amplitude[1] + offset[1])) * 255,
+ Math.max(0, Math.min(1, Math.pow(inputColor[2]/255,
+ exponent[2]) * amplitude[2] + offset[2])) * 255,
];
}
const amplitudes = [2, 1.1, 0.5];
const exponents = [5, 3, 1];
const offsets = [0.25, 0, 0.5];
- ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'gamma', amplitude: amplitudes[0], exponent: exponents[0], offset: offsets[0]},
- funcG: {type: 'gamma', amplitude: amplitudes[1], exponent: exponents[1], offset: offsets[1]},
- funcB: {type: 'gamma', amplitude: amplitudes[2], exponent: exponents[2], offset: offsets[2]},
- });
const inputColors = [
[255, 255, 255],
@@ -254,16 +442,54 @@
[50, 68, 87],
];
- for (const color of inputColors) {
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
let outputColor = getColor(color, amplitudes, exponents, offsets);
- ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
-
-- name: 2d.filter.canvasFilterObject.componentTransfer.table.tentative
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter: param})
+ close_layer: ctx.endLayer();
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(param)
+ tentative: .tentative
+
+- name: >-
+ 2d.filter.{{ variant_names[0] }}.componentTransfer.table{{ tentative }}
desc: Test pixels on CanvasFilter() componentTransfer with table type
+ size: [100, 100]
+ fuzzy: maxDifference=0-2; totalPixels=0-500
code: |
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ {{ filter_declaration | replace("param", "{name: 'componentTransfer',
+ funcR: {type: 'table', tableValues: tableValuesR},
+ funcG: {type: 'table', tableValues: tableValuesG},
+ funcB: {type: 'table', tableValues: tableValuesB},
+ }") }};
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ {{ close_layer }}
+ reference: |
// From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
function getTransformedValue(C, V) {
// Get the right interval
@@ -285,11 +511,6 @@
tableValuesR = [0, 0, 1, 1];
tableValuesG = [2, 0, 0.5, 3];
tableValuesB = [1, -1, 5, 0];
- ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'table', tableValues: tableValuesR},
- funcG: {type: 'table', tableValues: tableValuesG},
- funcB: {type: 'table', tableValues: tableValuesB},
- });
const inputColors = [
[255, 255, 255],
@@ -299,16 +520,55 @@
[50, 68, 87],
];
- for (const color of inputColors) {
- let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]);
- ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(
+ color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
-
-- name: 2d.filter.canvasFilterObject.componentTransfer.discrete.tentative
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter: param})
+ close_layer: ctx.endLayer();
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(param)
+ tentative: .tentative
+
+- name: >-
+ 2d.filter.{{ variant_names[0] }}.componentTransfer.discrete{{ tentative }}
desc: Test pixels on CanvasFilter() componentTransfer with discrete type
+ size: [100, 100]
+ fuzzy: maxDifference=0-2; totalPixels=0-500
code: |
+ tableValuesR = [0, 0, 1, 1];
+ tableValuesG = [2, 0, 0.5, 3];
+ tableValuesB = [1, -1, 5, 0];
+ {{ filter_declaration | replace("param", "{name: 'componentTransfer',
+ funcR: {type: 'discrete', tableValues: tableValuesR},
+ funcG: {type: 'discrete', tableValues: tableValuesG},
+ funcB: {type: 'discrete', tableValues: tableValuesB},
+ }") }};
+
+ const inputColors = [
+ [255, 255, 255],
+ [0, 0, 0],
+ [127, 0, 34],
+ [252, 186, 3],
+ [50, 68, 87],
+ ];
+
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
+ }
+ {{ close_layer }}
+ reference: |
// From https://www.w3.org/TR/SVG11/filters.html#feComponentTransferElement
function getTransformedValue(C, V) {
// Get the right interval
@@ -330,11 +590,6 @@
tableValuesR = [0, 0, 1, 1];
tableValuesG = [2, 0, 0.5, 3];
tableValuesB = [1, -1, 5, 0];
- ctx.filter = new CanvasFilter({name: 'componentTransfer',
- funcR: {type: 'discrete', tableValues: tableValuesR},
- funcG: {type: 'discrete', tableValues: tableValuesG},
- funcB: {type: 'discrete', tableValues: tableValuesB},
- });
const inputColors = [
[255, 255, 255],
@@ -343,24 +598,38 @@
[252, 186, 3],
[50, 68, 87],
];
-
- for (const color of inputColors) {
- let outputColor = getColor(color, [tableValuesR, tableValuesG, tableValuesB]);
- ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
- ctx.fillRect(0, 0, 10, 10);
- _assertPixelApprox(canvas, 5, 5, outputColor[0],outputColor[1],outputColor[2],255, 2);
+ for (let i = 0 ; i < inputColors.length ; ++i) {
+ const color = inputColors[i];
+ let outputColor = getColor(
+ color, [tableValuesR, tableValuesG, tableValuesB]);
+ ctx.fillStyle = `rgb(${outputColor[0]}, ${outputColor[1]},
+ ${outputColor[2]})`;
+ ctx.fillRect(i * 10, i * 10, 10, 10);
}
-
-- name: 2d.filter.canvasFilterObject.gaussianBlur.tentative
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter: param})
+ close_layer: ctx.endLayer();
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(param)
+ tentative: .tentative
+
+- name: >-
+ 2d.filter.{{ variant_names[0] }}.gaussianBlur.{{ variant_names[1] }}{{
+ tentative }}
desc: Test CanvasFilter() with gaussianBlur.
size: [100, 100]
code: |
ctx.fillStyle = 'teal';
- ctx.filter = new CanvasFilter({
+ {{ filter_declaration | replace("param", "{
name: 'gaussianBlur',
stdDeviation: [{{ blur_x }}, {{blur_y}}],
- });
+ }") }}
ctx.fillRect(25, 25, 50, 50);
+ {{ close_layer }}
html_reference: |
<svg xmlns="http://www.w3.org/2000/svg"
width="{{ size[0] }}" height="{{ size[1] }}"
@@ -371,24 +640,33 @@
<rect x="25" y="25" width="50" height="50"
fill="teal" filter="url(#blur)" />
</svg>
- variants:
- x-only:
- blur_x: 4
- blur_y: 0
- mostly-x:
- blur_x: 4
- blur_y: 1
- isotropic:
- blur_x: 4
- blur_y: 4
- mostly-y:
- blur_x: 1
- blur_y: 4
- y-only:
- blur_x: 0
- blur_y: 4
-
-- name: 2d.filter.canvasFilterObject.dropShadow.tentative
+ append_variants_to_name: false
+ variant_matrix:
+ - layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter: param});
+ close_layer: ctx.endLayer();
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(param);
+ tentative: .tentative
+ - x-only:
+ blur_x: 4
+ blur_y: 0
+ mostly-x:
+ blur_x: 4
+ blur_y: 1
+ isotropic:
+ blur_x: 4
+ blur_y: 4
+ mostly-y:
+ blur_x: 1
+ blur_y: 4
+ y-only:
+ blur_x: 0
+ blur_y: 4
+
+- name: 2d.filter.{{ variant_names[0] }}.dropShadow{{ tentative }}
desc: Test CanvasFilter() dropShadow object.
size: [520, 420]
code: |
@@ -401,90 +679,91 @@
ctx.fillStyle = 'crimson';
// Parameter defaults.
- ctx.filter = new CanvasFilter({name: 'dropShadow'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow'}") }}
ctx.fillRect(10, 10, 80, 80);
+ {{ close_layer -}}
// All parameters specified.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
- floodColor: 'purple', floodOpacity: 0.7});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ floodColor: 'purple', floodOpacity: 0.7}") }}
ctx.fillRect(110, 10, 80, 80);
+ {{ close_layer -}}
// Named color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
- floodColor: 'purple'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'purple'}") }}
ctx.fillRect(10, 110, 80, 80);
+ {{ close_layer -}}
// System color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
- floodColor: 'LinkText'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'LinkText'}") }}
ctx.fillRect(110, 110, 80, 80);
+ {{ close_layer -}}
// Numerical color.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
- floodColor: 'rgba(20, 50, 130, 1)'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 1)'}") }}
ctx.fillRect(210, 110, 80, 80);
+ {{ close_layer -}}
// Transparent floodColor.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
- floodColor: 'rgba(20, 50, 130, 0.7)'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 0.7)'}") }}
ctx.fillRect(310, 110, 80, 80);
+ {{ close_layer -}}
// Transparent floodColor and floodOpacity.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
- floodColor: 'rgba(20, 50, 130, 0.7)', floodOpacity: 0.7});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 3,
+ floodColor: 'rgba(20, 50, 130, 0.7)', floodOpacity: 0.7}") }}
ctx.fillRect(410, 110, 80, 80);
+ {{ close_layer -}}
// No blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
- floodColor: 'purple'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 0,
+ floodColor: 'purple'}") }}
ctx.fillRect(10, 210, 80, 80);
+ {{ close_layer -}}
// Single float blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
- floodColor: 'purple'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: 5,
+ floodColor: 'purple'}") }}
ctx.fillRect(110, 210, 80, 80);
+ {{ close_layer -}}
// Single negative float blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
- floodColor: 'purple'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: -5,
+ floodColor: 'purple'}") }}
ctx.fillRect(210, 210, 80, 80);
+ {{ close_layer -}}
// Two floats (X&Y) blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
- floodColor: 'purple'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [3, 5],
+ floodColor: 'purple'}") }}
ctx.fillRect(310, 210, 80, 80);
+ {{ close_layer -}}
// Two negative floats (X&Y) blur.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
- floodColor: 'purple'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: 9, dy: 12, stdDeviation: [-3, -5],
+ floodColor: 'purple'}") }}
ctx.fillRect(410, 210, 80, 80);
+ {{ close_layer -}}
// Degenerate parameter values.
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
- floodColor: 'purple', floodOpacity: [2]});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: [-5], dy: [], stdDeviation: null,
+ floodColor: 'purple', floodOpacity: [2]}") }}
ctx.fillRect(10, 310, 80, 80);
+ {{ close_layer -}}
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
- floodColor: 'purple', floodOpacity: '0.8'});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: null, dy: '5', stdDeviation: [[-5], ['3']],
+ floodColor: 'purple', floodOpacity: '0.8'}") }}
ctx.fillRect(110, 310, 80, 80);
+ {{ close_layer -}}
- ctx.filter = new CanvasFilter(
- {name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
- floodColor: 'purple', floodOpacity: ['0.4']});
+ {{ filter_declaration | replace("param", "{name: 'dropShadow', dx: true, dy: ['10'], stdDeviation: false,
+ floodColor: 'purple', floodOpacity: ['0.4']}") }}
ctx.fillRect(210, 310, 80, 80);
+ {{ close_layer -}}
html_reference: |
<svg xmlns="http://www.w3.org/2000/svg"
width={{ size[0] }} height={{ size[1] }}
@@ -537,41 +816,70 @@
<rect x=210 y=310 width=80 height=80 fill="crimson"
filter="drop-shadow(1px 10px 0px rgba(128, 0, 128, 0.4))"/>
</svg>
-
-- name: 2d.filter.canvasFilterObject.dropShadow.exceptions.tentative
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter: param});
+ close_layer: |
+ ctx.endLayer();
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(param);
+ tentative: .tentative
+
+- name: 2d.filter.{{ variant_names[0] }}.dropShadow.exceptions{{ tentative }}
desc: Test exceptions on CanvasFilter() dropShadow object
code: |
- @unroll @assert new CanvasFilter({\-
+ // Should not throw an error.
+ @unroll {{ filter_declaration | replace("param", "{\-
name: 'dropShadow', \-
<dx | dy | floodOpacity>: \-
- <10 | -1 | 0.5 | null | true | false | [] | [20] | '30'>});
- @unroll @assert new CanvasFilter({\-
+ <10 | -1 | 0.5 | null | true | false | [] | [20] | '30'>}") }};
+ @unroll {{ filter_declaration | replace("param", "{\-
+ name: 'dropShadow', \-
+ <dx | dy | floodOpacity>: \-
+ <10 | -1 | 0.5 | null | true | false | [] | [20] | '30'>}") }};
+ @unroll {{ filter_declaration | replace("param", "{\-
name: 'dropShadow', \-
<stdDeviation>: \-
<10 | -1 | 0.5 | null | true | false | [] | [20] | '30' | \-
[10, -1] | [0.5, null] | [true, false] | [[], [20]] | \-
- ['30', ['40']]>});
- @unroll @assert new CanvasFilter({\-
+ ['30', ['40']]>}") }};
+ @unroll {{ filter_declaration | replace("param", "{\-
name: 'dropShadow', \-
<floodColor>: \-
- <'red' | 'canvas' | 'rgba(4, -3, 0.5, 1)' | '#aabbccdd' | '#abcd'>});
+ <'red' | 'canvas' | 'rgba(4, -3, 0.5, 1)' | '#aabbccdd' |
+ '#abcd'>}") }};
- @unroll @assert throws TypeError new CanvasFilter({\-
- name: 'dropShadow', \-
+ // Should throw a TypeError.
+ @unroll @assert throws TypeError {{ filter_declaration | replace("param", \-
+ "{name: 'dropShadow', \-
<dx | dy | floodOpacity>: \-
- <NaN | Infinity | -Infinity | undefined | 'test' | {} | [1, 2]>});
- @unroll @assert throws TypeError new CanvasFilter({\-
- name: 'dropShadow', \-
+ <NaN | Infinity | -Infinity | undefined | 'test' | {} | [1, 2]>}") }};
+ @unroll @assert throws TypeError {{ filter_declaration | replace("param", \-
+ "{name: 'dropShadow', \-
<stdDeviation>: \-
<NaN | Infinity | -Infinity | undefined | 'test' | {} | [1, 2, 3] | \-
[1, NaN] | [1, Infinity] | [1, -Infinity] | [1, undefined] | \-
- [1, 'test'] | [1, {}] | [1, [2, 3]]>});
- @unroll @assert throws TypeError new CanvasFilter({\-
- name: 'dropShadow', \-
+ [1, 'test'] | [1, {}] | [1, [2, 3]]>}") }};
+ @unroll @assert throws TypeError {{ filter_declaration | replace("param", \-
+ "{name: 'dropShadow', \-
<floodColor>: \-
- <'test' | 'rgba(NaN, 3, 2, 1)' | 10 | undefined | null | NaN>});
-
-- name: 2d.filter.canvasFilterObject.turbulence.inputTypes.tentative
+ <'test' | 'rgba(NaN, 3, 2, 1)' | 10 | undefined | null | NaN>}") }};
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter:
+ param}); ctx.endLayer()
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(
+ param)
+ tentative: .tentative
+
+- name: 2d.filter.{{ variant_names[0] }}.turbulence.inputTypes{{ tentative }}
desc: Test exceptions on CanvasFilter() turbulence object
code: |
const errorTestCases = [
@@ -671,10 +979,22 @@
for (testCase of errorTestCases) {
const filterOptions = {...{name: 'turbulence'}, ...testCase};
- @assert throws TypeError new CanvasFilter(filterOptions);
+ @assert throws TypeError {{ filter_declaration |
+ replace("param", "filterOptions") }};
}
for (testCase of workingTestCases) {
const filterOptions = {...{name: 'turbulence'}, ...testCase};
- @assert new CanvasFilter(filterOptions) != null;
+ {{ filter_declaration | replace("param", "filterOptions") }};
+ {{- close_layer }}
}
+ append_variants_to_name: false
+ variants:
+ layers:
+ filter_declaration: |-
+ ctx.beginLayer({filter: param})
+ close_layer: "\n ctx.endLayer();"
+ canvasFilterObject:
+ filter_declaration: |-
+ ctx.filter = new CanvasFilter(param)
+ tentative: .tentative
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 a44cb2ea2c..437a70c3f7 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
@@ -44,7 +44,7 @@
variants: &global-state-variants
no-global-states:
render_states: // No global states.
- alpha:
+ alpha: &global-state-alpha
render_states: ctx.globalAlpha = 0.6;
blending:
render_states: ctx.globalCompositeOperation = 'multiply';
@@ -56,15 +56,15 @@
ctx.shadowOffsetY = 10;
ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
ctx.shadowBlur = 3;
- alpha.blending:
+ alpha.blending: &global-state-alpha-blending
render_states: |-
ctx.globalAlpha = 0.6;
ctx.globalCompositeOperation = 'multiply';
- alpha.composite:
+ alpha.composite: &global-state-alpha-composite
render_states: |-
ctx.globalAlpha = 0.6;
ctx.globalCompositeOperation = 'source-in';
- alpha.shadow:
+ alpha.shadow: &global-state-alpha-shadow
render_states: |-
ctx.globalAlpha = 0.5;
ctx.shadowOffsetX = -10;
@@ -167,7 +167,20 @@
ctx.drawImage(img, 0, 0);
};
img.src = 'data:image/svg+xml;base64,' + btoa(svg);
- variants: *global-state-variants
+ variants:
+ <<: *global-state-variants
+ alpha:
+ <<: *global-state-alpha
+ fuzzy: maxDifference=0-2; totalPixels=0-6766
+ alpha.blending:
+ <<: *global-state-alpha-blending
+ fuzzy: maxDifference=0-1; totalPixels=0-2453
+ alpha.composite:
+ <<: *global-state-alpha-composite
+ fuzzy: maxDifference=0-1; totalPixels=0-5204
+ alpha.shadow:
+ <<: *global-state-alpha-shadow
+ fuzzy: maxDifference=0-2; totalPixels=0-6311
- name: 2d.layer.global-filter
desc: Tests that layers ignore the global context filter.
@@ -334,6 +347,144 @@
ctx.drawImage(canvas2, 0, 0);
+- name: 2d.layer.ctm.filter
+ desc: Checks that parent transforms affect layer filters.
+ size: [200, 200]
+ code: |
+ // Transforms inside the layer should not apply to the layer's filter.
+ ctx.beginLayer({filter: 'drop-shadow(5px 5px 0px grey)'});
+ ctx.translate(30, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+ ctx.fillRect(-30, -5, 60, 10);
+ ctx.endLayer();
+
+ // Transforms in the layer's parent should apply to the layer's filter.
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+ ctx.beginLayer({filter: 'drop-shadow(5px 5px 0px grey)'});
+ ctx.fillRect(-30, -5, 60, 10);
+ ctx.endLayer();
+ html_reference: |
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="{{ size[0] }}" height="{{ size[1] }}"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="5" dy="5" stdDeviation="0" flood-color="grey" />
+ </filter>
+
+ <g filter="url(#filter)">
+ <g transform="translate(30, 90) scale(2) rotate(90)">
+ <rect x="-30" y="-5" width=60 height=10></rect>
+ </g>
+ </g>
+
+ <g transform="translate(80, 90) scale(2) rotate(90)">
+ <g filter="url(#filter)">
+ <rect x="-30" y="-5" width=60 height=10></rect>
+ </g>
+ </g>
+ </svg>
+
+- name: 2d.layer.ctm.shadow-in-transformed-layer
+ desc: Check shadows inside of a transformed layer.
+ size: [200, 200]
+ code: |
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+
+ ctx.beginLayer();
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'grey';
+ ctx.fillRect(-30, -5, 60, 10);
+
+ const canvas2 = new OffscreenCanvas(100, 100);
+ const ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(0, 0, 40, 10);
+ ctx.drawImage(canvas2, -30, -30);
+
+ ctx.endLayer();
+ reference: |
+ ctx.translate(80, 90);
+ ctx.scale(2, 2);
+ ctx.rotate(Math.PI / 2);
+
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'grey';
+ ctx.fillRect(-30, -5, 60, 10);
+
+ const canvas2 = new OffscreenCanvas(100, 100);
+ const ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(0, 0, 40, 10);
+ ctx.drawImage(canvas2, -30, -30);
+
+- name: 2d.layer.ctm.getTransform
+ desc: Tests getTransform inside layers.
+ code: |
+ ctx.translate(10, 20);
+ ctx.beginLayer();
+ ctx.scale(2, 3);
+ const m = ctx.getTransform();
+ assert_array_equals([m.a, m.b, m.c, m.d, m.e, m.f], [2, 0, 0, 3, 10, 20]);
+ ctx.endLayer();
+
+- name: 2d.layer.ctm.setTransform
+ desc: Tests setTransform inside layers.
+ code: |
+ ctx.translate(80, 0);
+
+ ctx.beginLayer();
+ ctx.rotate(2);
+ ctx.beginLayer();
+ ctx.scale(5, 6);
+ ctx.setTransform(4, 0, 0, 2, 20, 10);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 10, 10);
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+ reference: |
+ ctx.translate(80, 0);
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+
+ ctx.setTransform(4, 0, 0, 2, 20, 10);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 10, 10);
+
+- name: 2d.layer.ctm.resetTransform
+ desc: Tests resetTransform inside layers.
+ code: |
+ ctx.translate(40, 0);
+
+ ctx.beginLayer();
+ ctx.rotate(2);
+ ctx.beginLayer();
+ ctx.scale(5, 6);
+ ctx.resetTransform();
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 20, 20);
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+ reference: |
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 20, 20);
+
+ ctx.translate(40, 0);
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 20, 20);
+
- name: 2d.layer.clip-inside
desc: Check clipping set inside the layer
size: [100, 100]
@@ -627,6 +778,49 @@
ctx.fillStyle = 'blue';
ctx.fillRect(10, 10, 80, 50);
+- name: 2d.layer.drawImage
+ size: [200, 200]
+ desc: >-
+ Checks that drawImage writes the image to the layer and not the parent
+ directly.
+ code: |
+ ctx.fillStyle = 'skyblue';
+ ctx.fillRect(0, 0, 100, 100);
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
+ stdDeviation: 0, floodColor: 'navy'}});
+
+ ctx.fillStyle = 'maroon';
+ ctx.fillRect(20, 20, 50, 50);
+
+ ctx.globalCompositeOperation = 'xor';
+
+ // The image should xor only with the layer content, not the parents'.
+ const canvas_image = new OffscreenCanvas(200,200);
+ const ctx_image = canvas_image.getContext("2d");
+ ctx_image.fillStyle = 'pink';
+ ctx_image.fillRect(40, 40, 50, 50);
+ ctx.drawImage(canvas_image, 0, 0);
+
+ ctx.endLayer();
+ reference: |
+ ctx.fillStyle = 'skyblue';
+ ctx.fillRect(0, 0, 100, 100);
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: -10,
+ stdDeviation: 0, floodColor: 'navy'}});
+
+ ctx.fillStyle = 'maroon';
+ ctx.fillRect(20, 20, 50, 50);
+
+ ctx.globalCompositeOperation = 'xor';
+
+ // Should xor only with the layer content, not the parents'.
+ ctx.fillStyle = 'pink';
+ ctx.fillRect(40, 40, 50, 50);
+
+ ctx.endLayer();
+
- name: 2d.layer.valid-calls
desc: No exception raised on {{ variant_desc }}.
variants:
diff --git a/testing/web-platform/tests/html/dom/elements/global-attributes/dir-assorted.window.js b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-assorted.window.js
index 0d4e4b82d9..2017269f0b 100644
--- a/testing/web-platform/tests/html/dom/elements/global-attributes/dir-assorted.window.js
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-assorted.window.js
@@ -90,10 +90,11 @@ for (const bdi_test of [
{ markup: "<bdi dir=rtl></bdi>", expected: "rtl", desc: "dir=rtl empty" },
{ markup: "<bdi dir=auto>A</bdi>", expected: "ltr", desc: "dir=auto with LTR contents" },
{ markup: "<bdi dir=auto>\u05d0</bdi>", expected: "rtl", desc: "dir=auto with RTL contents" },
- { markup: "<bdi dir=auto></bdi>", expected: "parent", desc: "dir=auto empty" },
+ { markup: "<bdi dir=auto></bdi>", expected: "ltr", desc: "dir=auto empty" },
+ { markup: "<bdi dir=auto>123</bdi>", expected: "ltr", desc: "dir=auto numbers" },
{ markup: "<bdi>A</bdi>", expected: "ltr", desc: "no dir attribute with LTR contents" },
{ markup: "<bdi>\u05d0</bdi>", expected: "rtl", desc: "no dir attribute with RTL contents" },
- { markup: "<bdi></bdi>", expected: "parent", desc: "no dir attribute empty" },
+ { markup: "<bdi></bdi>", expected: "ltr", desc: "no dir attribute empty" },
]) {
for (const parent_dir of [ "ltr", "rtl" ]) {
test(() => {
diff --git a/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-dataChange.html b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-dataChange.html
new file mode 100644
index 0000000000..ded136a3ae
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-dataChange.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Dynamic changes with textContent and dir=auto</title>
+<link rel="match" href="dir-auto-dynamic-simple-ref.html">
+<div>Test for elements with dir="auto" whose content changes between directional and neutral</div>
+<div dir="auto" id="from_ltr_to_ltr">abc</div>
+<div dir="auto" id="from_ltr_to_rtl">abc</div>
+<div dir="auto" id="from_ltr_to_neutral">abc</div>
+<div dir="auto" id="from_rtl_to_ltr">אבג</div>
+<div dir="auto" id="from_rtl_to_rtl">אבג</div>
+<div dir="auto" id="from_rtl_to_neutral">אבג</div>
+<div dir="auto" id="from_neutral_to_ltr">123</div>
+<div dir="auto" id="from_neutral_to_rtl">123</div>
+<div dir="auto" id="from_neutral_to_neutral">123</div>
+<script>
+function changeContent() {
+ var directionalTexts = {ltr:"xyz", rtl:"ابج", neutral:"456"};
+
+ for (var dirFrom in directionalTexts) {
+ for (var dirTo in directionalTexts) {
+ var element = document.getElementById("from_" + dirFrom +
+ "_to_" + dirTo);
+ element.firstChild.data = directionalTexts[dirTo];
+ }
+ }
+ document.documentElement.removeAttribute("class");
+}
+
+document.addEventListener("TestRendered", changeContent);
+</script>
diff --git a/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-ref.html b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-ref.html
new file mode 100644
index 0000000000..5a9a2f2484
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Dynamic changes and dir=auto</title>
+<div>Test for elements with dir="auto" whose content changes between directional and neutral</div>
+<div dir="auto">xyz</div>
+<div dir="auto">ابج</div>
+<div dir="auto">456</div>
+<div dir="auto">xyz</div>
+<div dir="auto">ابج</div>
+<div dir="auto">456</div>
+<div dir="auto">xyz</div>
+<div dir="auto">ابج</div>
+<div dir="auto">456</div>
diff --git a/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-replace.html b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-replace.html
new file mode 100644
index 0000000000..6d785f08b8
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-replace.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Dynamic changes with textContent and dir=auto</title>
+<link rel="match" href="dir-auto-dynamic-simple-ref.html">
+<div>Test for elements with dir="auto" whose content changes between directional and neutral</div>
+<div dir="auto" id="from_ltr_to_ltr">abc</div>
+<div dir="auto" id="from_ltr_to_rtl">abc</div>
+<div dir="auto" id="from_ltr_to_neutral">abc</div>
+<div dir="auto" id="from_rtl_to_ltr">אבג</div>
+<div dir="auto" id="from_rtl_to_rtl">אבג</div>
+<div dir="auto" id="from_rtl_to_neutral">אבג</div>
+<div dir="auto" id="from_neutral_to_ltr">123</div>
+<div dir="auto" id="from_neutral_to_rtl">123</div>
+<div dir="auto" id="from_neutral_to_neutral">123</div>
+<script>
+function changeContent() {
+ var directionalTexts = {ltr:"xyz", rtl:"ابج", neutral:"456"};
+
+ for (var dirFrom in directionalTexts) {
+ for (var dirTo in directionalTexts) {
+ var element = document.getElementById("from_" + dirFrom +
+ "_to_" + dirTo);
+ element.firstChild.remove();
+ element.appendChild(document.createTextNode(directionalTexts[dirTo]));
+ }
+ }
+ document.documentElement.removeAttribute("class");
+}
+
+document.addEventListener("TestRendered", changeContent);
+</script>
diff --git a/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-textContent.html b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-textContent.html
new file mode 100644
index 0000000000..3b644908ab
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-auto-dynamic-simple-textContent.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Dynamic changes with textContent and dir=auto</title>
+<link rel="match" href="dir-auto-dynamic-simple-ref.html">
+<div>Test for elements with dir="auto" whose content changes between directional and neutral</div>
+<div dir="auto" id="from_ltr_to_ltr">abc</div>
+<div dir="auto" id="from_ltr_to_rtl">abc</div>
+<div dir="auto" id="from_ltr_to_neutral">abc</div>
+<div dir="auto" id="from_rtl_to_ltr">אבג</div>
+<div dir="auto" id="from_rtl_to_rtl">אבג</div>
+<div dir="auto" id="from_rtl_to_neutral">אבג</div>
+<div dir="auto" id="from_neutral_to_ltr">123</div>
+<div dir="auto" id="from_neutral_to_rtl">123</div>
+<div dir="auto" id="from_neutral_to_neutral">123</div>
+<script>
+function changeContent() {
+ var directionalTexts = {ltr:"xyz", rtl:"ابج", neutral:"456"};
+
+ for (var dirFrom in directionalTexts) {
+ for (var dirTo in directionalTexts) {
+ var element = document.getElementById("from_" + dirFrom +
+ "_to_" + dirTo);
+ element.textContent = directionalTexts[dirTo];
+ }
+ }
+ document.documentElement.removeAttribute("class");
+}
+
+document.addEventListener("TestRendered", changeContent);
+</script>
diff --git a/testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-41-ref.html b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-41-ref.html
index b52e08df20..79b844edbe 100644
--- a/testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-41-ref.html
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-41-ref.html
@@ -18,7 +18,7 @@ span {border: 1px solid silver;}
<p>`dir=rtl` on a div in the shadow tree, `dir=ltr` on the shadow host, no slotted text in the light or dark trees</p>
<div id="host" dir="ltr"><div dir="rtl"><span></span></div></div>
-<p id="result">The HTML direction / computed CSS `direction` value is: rtl / rtl (on the slot).</p>
+<p id="result">The HTML direction / computed CSS `direction` value is: ltr / ltr (on the slot).</p>
</body>
</html>
diff --git a/testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-42-ref.html b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-42-ref.html
new file mode 100644
index 0000000000..8ea1100246
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-42-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>[dir] and shadow slots: dir=ltr on a div in the shadow tree, dir=rtl on the shadow host, no slotted text in the light or dark trees</title>
+<link rel="author" title="Eric Meyer" href="mailto:emeyer@igalia.com">
+<link rel="author" title="L. David Baron" href="mailto:dbaron@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/C#the-dir-attribute">
+<link rel="help" href="https://github.com/whatwg/html/issues/3699">
+<link rel="help" href="https://github.com/whatwg/html/pull/9796">
+<style type="text/css">
+body {width: 600px;}
+#host {border: 1px solid gray; margin: 1em; padding: 0.25em;}
+span {border: 1px solid silver;}
+
+</style>
+</head>
+<body>
+
+<p>`dir=ltr` on a div in the shadow tree, `dir=rtl` on the shadow host, no slotted text in the light or dark trees</p>
+<div id="host" dir="rtl"><div dir="ltr"><span></span></div></div>
+<p id="result">The HTML direction / computed CSS `direction` value is: ltr / ltr (on the slot).</p>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-42.html b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-42.html
new file mode 100644
index 0000000000..b9697678cb
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dir-shadow-42.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>[dir] and shadow slots: dir=ltr on a div in the shadow tree, dir=rtl on the shadow host, no slotted text in the light or dark trees</title>
+<link rel="author" title="Eric Meyer" href="mailto:emeyer@igalia.com">
+<link rel="author" title="L. David Baron" href="mailto:dbaron@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/C#the-dir-attribute">
+<link rel="help" href="https://github.com/whatwg/html/issues/3699">
+<link rel="help" href="https://github.com/whatwg/html/pull/9796">
+<link rel="match" href="dir-shadow-42-ref.html">
+<style type="text/css">
+body {width: 600px;}
+#host {border: 1px solid gray; margin: 1em; padding: 0.25em;}
+span {border: 1px solid silver;}
+
+</style>
+<script src="dir-shadow-utils.js"></script>
+</head>
+<body>
+
+<p>`dir=ltr` on a div in the shadow tree, `dir=rtl` on the shadow host, no slotted text in the light or dark trees</p>
+<div id="host" dir="rtl"><span slot="x1"></span></div>
+<p id="result">The HTML direction / computed CSS `direction` value is: </p>
+
+<script type="text/javascript">
+ let root = host.attachShadow({mode:"open"});
+ root.innerHTML = `<div dir="ltr"><slot dir="auto" name="x1"></slot></div>`;
+ result.innerHTML += html_direction(root.querySelector("div[dir=ltr]").firstChild) + " / " + getComputedStyle(root.querySelector("div[dir=ltr]").firstChild).direction + " (on the " + root.querySelector("div[dir=ltr]").firstChild.localName + ').';
+</script>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/dom/elements/global-attributes/dir_auto-N-EN-ref.html b/testing/web-platform/tests/html/dom/elements/global-attributes/dir_auto-N-EN-ref.html
index 0d938b2e16..496d699d73 100644
--- a/testing/web-platform/tests/html/dom/elements/global-attributes/dir_auto-N-EN-ref.html
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dir_auto-N-EN-ref.html
@@ -10,7 +10,7 @@
<meta name="assert" content="
When dir='auto', the direction is set according to the first strong character
of the text, ignoring neutrals and numbers.
- If there is no strong character, as in this test, the direction defaults to the parent." />
+ If there is no strong character, as in this test, the direction defaults to LTR." />
<style>
input, textarea {
font-size:1em;
@@ -35,7 +35,7 @@
<p dir="ltr">@123!</p>
</div>
<div dir="rtl">
- <p dir="rtl">@123!</p>
+ <p dir="ltr">@123!</p>
</div>
</div>
<div class="ref">
@@ -43,7 +43,7 @@
<p dir="ltr">@123!</p>
</div>
<div dir="rtl">
- <p dir="rtl">@123!</p>
+ <p dir="ltr">@123!</p>
</div>
</div>
</body>
diff --git a/testing/web-platform/tests/html/dom/elements/global-attributes/dir_auto-N-EN.html b/testing/web-platform/tests/html/dom/elements/global-attributes/dir_auto-N-EN.html
index 467b4d0939..5d948d3456 100644
--- a/testing/web-platform/tests/html/dom/elements/global-attributes/dir_auto-N-EN.html
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dir_auto-N-EN.html
@@ -11,7 +11,7 @@
<meta name="assert" content="
When dir='auto', the direction is set according to the first strong character
of the text, ignoring neutrals and numbers.
- If there is no strong character, as in this test, the direction defaults to the parent." />
+ If there is no strong character, as in this test, the direction defaults to LTR." />
<style>
input, textarea {
font-size:1em;
@@ -44,7 +44,7 @@
<p dir="ltr">@123!</p>
</div>
<div dir="rtl">
- <p dir="rtl">@123!</p>
+ <p dir="ltr">@123!</p>
</div>
</div>
</body>
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-001.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-001.html
index 36567f9d54..36567f9d54 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-001.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-001.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-002.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-002.html
index 3c907597f7..3c907597f7 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-002.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-002.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-003.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-003.html
index 2858798a35..2858798a35 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-003.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-003.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-004.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-004.html
index f45f558720..f45f558720 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-004.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-004.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-005.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-005.html
index 098a3c5767..098a3c5767 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-005.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-005.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-006.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-006.html
index 223e42109e..223e42109e 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-006.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-006.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-007.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-007.html
index 9aa0aeea79..9aa0aeea79 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-007.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-007.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-008.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-008.html
index e671dda19c..e671dda19c 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-008.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-008.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-009.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-009.html
index 8498816ea5..8498816ea5 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-009.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-009.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-010.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-010.html
index ef6f709012..ef6f709012 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-010.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-010.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-011.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-011.html
index dee82d8c59..dee82d8c59 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-011.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-011.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-012.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-012.html
index 4110e54c5f..4110e54c5f 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-012.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-012.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-013.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-013.html
index ecd97be86a..ecd97be86a 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-013.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-013.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-014.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-014.html
index ea8948de42..ea8948de42 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-014.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-014.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-015.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-015.html
index a775ee4174..a775ee4174 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-015.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-015.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-016.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-016.html
index 8968c5dacd..8968c5dacd 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-016.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-016.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-017.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-017.html
index 2d3b574721..2d3b574721 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-017.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-017.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-018.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-018.html
index 76e6394b5b..76e6394b5b 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-018.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-018.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-019.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-019.html
index 80a7019edc..80a7019edc 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-019.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-019.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-020.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-020.html
index 10019c943f..10019c943f 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-020.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-020.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-021.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-021.html
index 1ca2114689..1ca2114689 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-021.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-021.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-022.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-022.html
index 5dfbcac30a..5dfbcac30a 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-022.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-022.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-023.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-023.html
index 8fe8b6a8c8..8fe8b6a8c8 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-023.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-023.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-024.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-024.html
index 19e4020fb7..19e4020fb7 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-024.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-024.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-025.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-025.html
index 689ae69f45..689ae69f45 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-025.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-025.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-026.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-026.html
index 6abfc43b8b..6abfc43b8b 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-026.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-026.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-027.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-027.html
index 56f88e0fc2..56f88e0fc2 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-027.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-027.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-028.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-028.html
index a64d542c4a..a64d542c4a 100644
--- a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-028.tentative.html
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-028.html
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-029.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-029.html
new file mode 100644
index 0000000000..44dff3cb84
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-029.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/utils.js"></script>
+<title>`link rel=expect` supports &lt;a name&gt;</title>
+
+<link rel=expect href="#second" blocking="render">
+<script>
+async_test((t) => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_true(!!document.getElementsByName("second")), "the second element should unblock rendering");
+ t.step(() => assert_false(!!document.getElementById("last")));
+ t.done();
+ });
+}, "blocking defers frames until full parsing");
+</script>
+</head>
+<body>
+ <div id="first"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <a name="second"></a>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="last"></div>
+</body>
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-030.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-030.html
new file mode 100644
index 0000000000..307c2d303d
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-030.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/utils.js"></script>
+<title>&lt;a name&gt; should only unblock when finished parsing children</title>
+
+<link rel=expect href="#fold" blocking="render">
+<script>
+async_test((t) => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_true(!!document.getElementsByName("second")));
+ t.step(() => assert_false(!!document.getElementById("last")), "the second element should already unblock rendering");
+ t.done();
+ });
+}, "blocking defers frames until full parsing");
+</script>
+</head>
+<body>
+ <div id="first"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <a name="fold">
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="second"></div>
+ </a>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="last"></div>
+</body>
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-031.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-031.html
new file mode 100644
index 0000000000..2098483a06
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-031.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/utils.js"></script>
+<title>`link rel=expect` supports dynamically changed &lt;a name&gt;</title>
+
+<link rel=expect href="#second" blocking="render">
+<script>
+async_test((t) => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_true(!!document.getElementsByName("second")));
+ t.step(() => assert_false(!!document.getElementById("last")), "the second element should already unblock rendering");
+ t.done();
+ });
+}, "blocking defers frames until full parsing");
+</script>
+</head>
+<body>
+ <div id="first"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <a id="fold"></a>
+ <script>
+ document.getElementById("fold").setAttribute("name", "second");
+ </script>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="last"></div>
+</body>
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-032.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-032.html
new file mode 100644
index 0000000000..307c2d303d
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-032.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/utils.js"></script>
+<title>&lt;a name&gt; should only unblock when finished parsing children</title>
+
+<link rel=expect href="#fold" blocking="render">
+<script>
+async_test((t) => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_true(!!document.getElementsByName("second")));
+ t.step(() => assert_false(!!document.getElementById("last")), "the second element should already unblock rendering");
+ t.done();
+ });
+}, "blocking defers frames until full parsing");
+</script>
+</head>
+<body>
+ <div id="first"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <a name="fold">
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="second"></div>
+ </a>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="last"></div>
+</body>
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-033.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-033.html
new file mode 100644
index 0000000000..59d41c08c0
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-033.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/utils.js"></script>
+<title>link rel=expect should support percent encoding</title>
+
+<link rel=expect href="#se%F0%9F%98%8Fcond" blocking="render">
+<script>
+async_test((t) => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_true(!!document.getElementById("se😏cond")));
+ t.step(() => assert_false(!!document.getElementById("last")), "the second element should already unblock rendering");
+ t.done();
+ });
+}, "blocking defers frames until full parsing");
+</script>
+</head>
+<body>
+ <div id="first"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="se😏cond"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="last"></div>
+</body>
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-034.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-034.html
new file mode 100644
index 0000000000..a505de4875
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-034.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/utils.js"></script>
+<title>link rel=expect should allow relative URLs</title>
+
+<link rel=expect href="../render-blocking/element-render-blocking-034.html#second" blocking="render">
+<script>
+async_test((t) => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_true(!!document.getElementById("second")));
+ t.step(() => assert_false(!!document.getElementById("last")), "the second element should already unblock rendering");
+ t.done();
+ });
+}, "relative URLs that match this document are OK");
+</script>
+</head>
+<body>
+ <div id="first"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="second">
+ </div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="last"></div>
+</body>
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-035.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-035.html
new file mode 100644
index 0000000000..050244c7a6
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-035.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/utils.js"></script>
+<title>link rel=expect: base URL should be OK with relative URLs</title>
+
+<base href="dummy.html">
+<link rel=expect href="../render-blocking/element-render-blocking-035.html#second" blocking="render">
+<script>
+async_test((t) => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_true(!!document.getElementById("second")));
+ t.step(() => assert_false(!!document.getElementById("last")), "the second element should already unblock rendering");
+ t.done();
+ });
+}, "relative URLs that match this document are OK, regarless of <base>");
+</script>
+</head>
+<body>
+ <div id="first"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="second">
+ </div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="last"></div>
+</body>
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-036.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-036.html
new file mode 100644
index 0000000000..83637b3a08
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-036.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/utils.js"></script>
+<title>link rel=expect: base URL mismatch causes link to not block</title>
+
+<base href="dummy.html">
+<link rel=expect href="#second" blocking="render">
+<script>
+async_test((t) => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_true(!!document.getElementById("first")));
+ t.step(() => assert_false(!!document.getElementById("second")), "the first element should already unblock rendering");
+ t.done();
+ });
+}, "link URLs are relative to base URL, not to document URL");
+</script>
+</head>
+<body>
+ <div id="first"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="second">
+ </div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="last"></div>
+</body>
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-037.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-037.html
new file mode 100644
index 0000000000..5fe469a2fd
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-037.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/utils.js"></script>
+<title>link rel=expect: base URL should be OK with relative URLs</title>
+
+<base href="dummy.html">
+<link rel=expect href="../render-blocking/element-render-blocking-037.html#second" blocking="render">
+<script>
+async_test((t) => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_true(!!document.getElementById("second")));
+ t.step(() => assert_false(!!document.getElementById("last")), "the second element should already unblock rendering");
+ t.done();
+ });
+}, "relative URLs that match this document are OK, regarless of <base>");
+</script>
+</head>
+<body>
+ <div id="first"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="second">
+ </div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="last"></div>
+</body>
diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-038.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-038.html
new file mode 100644
index 0000000000..c7fabe7f32
--- /dev/null
+++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-038.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/utils.js"></script>
+<title>link rel=expect: only connected elements are eligible</title>
+
+<link rel=expect href="#second" blocking="render">
+<script>
+async_test((t) => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_true(!!document.getElementById("second"), "The second element should be there"));
+ t.step(() => assert_false(!!document.getElementById("last"), "The last element should not be there yet, even though it's created (in a shadow root)"));
+ t.done();
+ });
+}, "");
+</script>
+</head>
+<body>
+ <div id="first"></div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="second">
+ <custom-element>
+ <template shadowrootmode="open">
+ <div id="last"></div>
+ </template>
+ </custom-element>
+ </div>
+ <script>
+ generateParserDelay();
+ </script>
+ <div id="last"></div>
+</body>
diff --git a/testing/web-platform/tests/html/editing/editing-0/writing-suggestions/writingsuggestions.html b/testing/web-platform/tests/html/editing/editing-0/writing-suggestions/writingsuggestions.html
index 49e75000d3..664659d90a 100644
--- a/testing/web-platform/tests/html/editing/editing-0/writing-suggestions/writingsuggestions.html
+++ b/testing/web-platform/tests/html/editing/editing-0/writing-suggestions/writingsuggestions.html
@@ -29,13 +29,33 @@ test(function() {
assert_true('writingSuggestions' in document.createElement('test-custom-element'));
}, 'Test that the writingsuggestions attribute is available on custom elements.');
+test(function() {
+ let input = document.createElement('input');
+ input.type = 'color';
+ assert_true('writingSuggestions' in input);
+}, 'Test that the writingsuggestions attribute is available on an input type which the attribute doesn\'t apply. The User Agent is responsible that writing suggestions are not applied to the element.');
+
+test(function() {
+ let textarea = document.createElement('textarea');
+ textarea.disabled = true;
+ assert_true('writingSuggestions' in textarea);
+}, 'Test that the writingsuggestions attribute is available on a disabled element. The User Agent is responsible that writing suggestions are not applied to the element.');
+
function testSetAttributeDirectly(IDLValue, contentValue, expectedIDLValue, expectedContentValue, testDescription) {
test(function() {
+ let input_color = document.createElement('input');
+ input_color.type = 'color';
+
+ let disabled_textarea = document.createElement('textarea');
+ disabled_textarea.disabled = true;
+
const elements = [document.createElement('input'),
document.createElement('textarea'),
document.createElement('div'),
document.createElement('span'),
- document.createElement('test-custom-element') ];
+ document.createElement('test-custom-element'),
+ disabled_textarea,
+ input_color ];
elements.forEach(function(element) {
if (IDLValue != undefined) {
@@ -55,7 +75,7 @@ testSetAttributeDirectly('true', undefined, 'true', 'true', 'Test setting the `w
testSetAttributeDirectly(undefined, 'true', 'true', 'true', 'Test setting the `writingsuggestions` content attribute to `true` directly on the target element.');
testSetAttributeDirectly(true, undefined, 'true', 'true', 'Test setting the `writingsuggestions` IDL attribute to boolean `true` directly on the target element.');
testSetAttributeDirectly(undefined, true, 'true', 'true', 'Test setting the `writingsuggestions` content attribute to boolean `true` directly on the target element.');
-testSetAttributeDirectly('TrUe', undefined, 'true', 'true', 'Test setting the `writingsuggestions` IDL attribute to `TrUe` directly on the target element.');
+testSetAttributeDirectly('TrUe', undefined, 'true', 'TrUe', 'Test setting the `writingsuggestions` IDL attribute to `TrUe` directly on the target element.');
testSetAttributeDirectly(undefined, 'TrUe', 'true', 'TrUe', 'Test setting the `writingsuggestions` content attribute to `TrUe` directly on the target element.');
// Test setting either the `writingsuggestions` IDL or content attribute to some variation of 'false' directly on the target element.
@@ -63,15 +83,15 @@ testSetAttributeDirectly('false', undefined, 'false', 'false', 'Test setting the
testSetAttributeDirectly(undefined, 'false', 'false', 'false', 'Test setting the `writingsuggestions` content attribute to `false` directly on the target element.');
testSetAttributeDirectly(false, undefined, 'false', 'false', 'Test setting the `writingsuggestions` IDL attribute to boolean `false` directly on the target element.');
testSetAttributeDirectly(undefined, false, 'false', 'false', 'Test setting the `writingsuggestions` content attribute to boolean `false` directly on the target element.');
-testSetAttributeDirectly('FaLsE', undefined, 'false', 'false', 'Test setting the `writingsuggestions` IDL attribute to `FaLsE` directly on the target element.');
+testSetAttributeDirectly('FaLsE', undefined, 'false', 'FaLsE', 'Test setting the `writingsuggestions` IDL attribute to `FaLsE` directly on the target element.');
testSetAttributeDirectly(undefined, 'FaLsE', 'false', 'FaLsE', 'Test setting the `writingsuggestions` content attribute to `FaLsE` directly on the target element.');
// Test setting either the `writingsuggestions` IDL or content attribute to the empty string directly on the target element.
-testSetAttributeDirectly('', undefined, 'true', 'true', 'Test setting the `writingsuggestions` IDL attribute to the empty string directly on the target element.');
+testSetAttributeDirectly('', undefined, 'true', '', 'Test setting the `writingsuggestions` IDL attribute to the empty string directly on the target element.');
testSetAttributeDirectly(undefined, '', 'true', '', 'Test setting the `writingsuggestions` content attribute to the empty string directly on the target element.');
// Test setting either the `writingsuggestions` IDL or content attribute to an invalid value directly on the target element.
-testSetAttributeDirectly('foo', undefined, 'true', 'true', 'Test setting the `writingsuggestions` IDL attribute to an invalid value directly on the target element.');
+testSetAttributeDirectly('foo', undefined, 'true', 'foo', 'Test setting the `writingsuggestions` IDL attribute to an invalid value directly on the target element.');
testSetAttributeDirectly(undefined, 'foo', 'true', 'foo', 'Test setting the `writingsuggestions` content attribute to an invalid value directly on the target element.');
// Test setting neither the `writingsuggestions` IDL nor content attribute directly on the target element.
@@ -98,7 +118,9 @@ test(function() {
const elements = [ new DOMParser().parseFromString('<input writingsuggestions />', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<textarea writingsuggestions></textarea>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<div writingsuggestions></div>', 'text/html').body.firstElementChild,
- new DOMParser().parseFromString('<span writingsuggestions></span>', 'text/html').body.firstElementChild ];
+ new DOMParser().parseFromString('<span writingsuggestions></span>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<input type="color" writingsuggestions />', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<textarea disabled writingsuggestions></textarea>', 'text/html').body.firstElementChild ];
elements.forEach(function(element) {
assert_equals(element.writingSuggestions, 'true');
@@ -110,7 +132,9 @@ test(function() {
const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="true"><input /></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="true"><textarea></textarea></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="true"><div></div></body></html>', 'text/html').body.firstElementChild,
- new DOMParser().parseFromString('<html><body writingsuggestions="true"><span></span></body></html>', 'text/html').body.firstElementChild ];
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><span></span></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><input type="color"/></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><textarea disabled></textarea></body></html>', 'text/html').body.firstElementChild ];
elements.forEach(function(element) {
assert_equals(element.parentElement.writingSuggestions, 'true');
@@ -124,7 +148,9 @@ test(function() {
const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions=""><input /></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions=""><textarea></textarea></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions=""><div></div></body></html>', 'text/html').body.firstElementChild,
- new DOMParser().parseFromString('<html><body writingsuggestions=""><span></span></body></html>', 'text/html').body.firstElementChild ];
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><span></span></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><input type="color"/></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><textarea disabled></textarea></body></html>', 'text/html').body.firstElementChild ];
elements.forEach(function(element) {
assert_equals(element.parentElement.writingSuggestions, 'true');
@@ -138,7 +164,9 @@ test(function() {
const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input /></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea></textarea></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="false"><div></div></body></html>', 'text/html').body.firstElementChild,
- new DOMParser().parseFromString('<html><body writingsuggestions="false"><span></span></body></html>', 'text/html').body.firstElementChild ];
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><span></span></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input type="color"/></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea disabled></textarea></body></html>', 'text/html').body.firstElementChild ];
elements.forEach(function(element) {
assert_equals(element.parentElement.writingSuggestions, 'false');
@@ -152,7 +180,9 @@ test(function() {
const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="foo"><input /></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="foo"><textarea></textarea></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="foo"><div></div></body></html>', 'text/html').body.firstElementChild,
- new DOMParser().parseFromString('<html><body writingsuggestions="foo"><span></span></body></html>', 'text/html').body.firstElementChild ];
+ new DOMParser().parseFromString('<html><body writingsuggestions="foo"><span></span></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="foo"><input type="color"/></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="foo"><textarea disabled></textarea></body></html>', 'text/html').body.firstElementChild ];
elements.forEach(function(element) {
assert_equals(element.parentElement.writingSuggestions, 'true');
@@ -163,10 +193,12 @@ test(function() {
}, 'Test setting the `writingsuggestions` attribute to an invalid value on a parent element.');
test(function() {
- const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="true"><input writingsuggestions="false" /></body></html>', 'text/html').body.firstElementChild,
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="true"><input writingsuggestions="false"/></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="true"><textarea writingsuggestions="false"></textarea></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="true"><div writingsuggestions="false"></div></body></html>', 'text/html').body.firstElementChild,
- new DOMParser().parseFromString('<html><body writingsuggestions="true"><span writingsuggestions="false"></span></body></html>', 'text/html').body.firstElementChild ];
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><span writingsuggestions="false"></span></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><input type="color" writingsuggestions="false"/></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><textarea disabled writingsuggestions="false"></textarea></body></html>', 'text/html').body.firstElementChild ];
elements.forEach(function(element) {
assert_equals(element.parentElement.writingSuggestions, 'true');
@@ -177,10 +209,12 @@ test(function() {
}, 'Test overriding the parent element\'s `writingsuggestions` attribute from "true" to "false".');
test(function() {
- const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions=""><input writingsuggestions="false" /></body></html>', 'text/html').body.firstElementChild,
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions=""><input writingsuggestions="false"/></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions=""><textarea writingsuggestions="false"></textarea></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions=""><div writingsuggestions="false"></div></body></html>', 'text/html').body.firstElementChild,
- new DOMParser().parseFromString('<html><body writingsuggestions=""><span writingsuggestions="false"></span></body></html>', 'text/html').body.firstElementChild ];
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><span writingsuggestions="false"></span></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><input type="color" writingsuggestions="false"/></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><textarea disabled writingsuggestions="false"></textarea></body></html>', 'text/html').body.firstElementChild ];
elements.forEach(function(element) {
assert_equals(element.parentElement.writingSuggestions, 'true');
@@ -194,7 +228,9 @@ test(function() {
const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input writingsuggestions="true" /></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea writingsuggestions="true"></textarea></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="false"><div writingsuggestions="true"></div></body></html>', 'text/html').body.firstElementChild,
- new DOMParser().parseFromString('<html><body writingsuggestions="false"><span writingsuggestions="true"></span></body></html>', 'text/html').body.firstElementChild ];
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><span writingsuggestions="true"></span></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input type="color" writingsuggestions="true"/></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea disabled writingsuggestions="true"></textarea></body></html>', 'text/html').body.firstElementChild, ];
elements.forEach(function(element) {
assert_equals(element.parentElement.writingSuggestions, 'false');
@@ -208,7 +244,9 @@ test(function() {
const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input writingsuggestions="foo" /></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea writingsuggestions="foo"></textarea></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="false"><div writingsuggestions="foo"></div></body></html>', 'text/html').body.firstElementChild,
- new DOMParser().parseFromString('<html><body writingsuggestions="false"><span writingsuggestions="foo"></span></body></html>', 'text/html').body.firstElementChild ];
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><span writingsuggestions="foo"></span></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input type="color" writingsuggestions="foo"/></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea disabled writingsuggestions="foo"></textarea></body></html>', 'text/html').body.firstElementChild ];
elements.forEach(function(element) {
assert_equals(element.parentElement.writingSuggestions, 'false');
@@ -222,7 +260,9 @@ test(function() {
const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input writingsuggestions="" /></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea writingsuggestions=""></textarea></body></html>', 'text/html').body.firstElementChild,
new DOMParser().parseFromString('<html><body writingsuggestions="false"><div writingsuggestions=""></div></body></html>', 'text/html').body.firstElementChild,
- new DOMParser().parseFromString('<html><body writingsuggestions="false"><span writingsuggestions=""></span></body></html>', 'text/html').body.firstElementChild ];
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><span writingsuggestions=""></span></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input type="color" writingsuggestions=""/></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea disabled writingsuggestions=""></textarea></body></html>', 'text/html').body.firstElementChild ];
elements.forEach(function(element) {
assert_equals(element.parentElement.writingSuggestions, 'false');
@@ -233,13 +273,15 @@ test(function() {
}, 'Test overriding the parent element\'s `writingsuggestions` attribute from "false" to the empty string.');
test(function() {
- const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input /><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input /><textarea></textarea><div></div><span></span><input type="color"/><textarea disabled></textarea></body></html>', 'text/html');
assert_equals(doc.documentElement.writingSuggestions, 'false');
assert_equals(doc.body.writingSuggestions, 'false');
- assert_equals(doc.querySelector('input').writingSuggestions, 'false');
- assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelectorAll('input')[0].writingSuggestions, 'false');
+ assert_equals(doc.querySelectorAll('textarea')[0].writingSuggestions, 'false');
assert_equals(doc.querySelector('div').writingSuggestions, 'false');
assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+ assert_equals(doc.querySelectorAll('input')[1].writingSuggestions, 'false');
+ assert_equals(doc.querySelectorAll('textarea')[1].writingSuggestions, 'false');
}, 'Test turning off writing suggestions for an entire document.');
test(function() {
@@ -283,6 +325,26 @@ test(function() {
}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a span element from "false" to "true".');
test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input type="color" writingsuggestions="true"><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on an input type which the attribute doesn\'t apply from "false" to "true". The User Agent is responsible that writing suggestions are not applied to the element');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input><textarea disabled writingsuggestions="true"></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a disabled textarea element from "false" to "true". The User Agent is responsible that writing suggestions are not applied to the element');
+
+test(function() {
const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input writingsuggestions=""><textarea></textarea><div></div><span></span></body></html>', 'text/html');
assert_equals(doc.documentElement.writingSuggestions, 'false');
assert_equals(doc.body.writingSuggestions, 'false');
@@ -323,6 +385,26 @@ test(function() {
}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a span element from "false" to the empty string.');
test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input type="color" writingsuggestions=""><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on an input type which the attribute doesn\'t apply from "false" to the empty string. The User Agent is responsible that writing suggestions are not applied to the element.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input><textarea disabled writingsuggestions=""></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a disabled textarea element from "false" to the empty string. The User Agent is responsible that writing suggestions are not applied to the element.');
+
+test(function() {
const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input writingsuggestions="foo"><textarea></textarea><div></div><span></span></body></html>', 'text/html');
assert_equals(doc.documentElement.writingSuggestions, 'false');
assert_equals(doc.body.writingSuggestions, 'false');
@@ -363,6 +445,26 @@ test(function() {
}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a span element from "false" to an invalid value.');
test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input type="color" writingsuggestions="foo"><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on an input type which the attribute doesn\'t apply from "false" to an invalid value. The User Agent is responsible that writing suggestions are not applied to the element.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input><textarea disabled writingsuggestions="foo"></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a disabled textarea element from "false" to an invalid value. The User Agent is responsible that writing suggestions are not applied to the element.');
+
+test(function() {
const doc = new DOMParser().parseFromString('<html writingsuggestions="true"><body><input writingsuggestions="false"><textarea></textarea><div></div><span></span></body></html>', 'text/html');
assert_equals(doc.documentElement.writingSuggestions, 'true');
assert_equals(doc.body.writingSuggestions, 'true');
@@ -403,6 +505,26 @@ test(function() {
}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a span element from "true" to "false".');
test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="true"><body><input type="color" writingsuggestions="false"><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on an input type which the attribute doesn\'t apply from "true" to "false". The User Agent is responsible that writing suggestions are not applied to the element.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="true"><body><input><textarea disabled writingsuggestions="false"></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a disabled textarea element from "true" to "false". The User Agent is responsible that writing suggestions are not applied to the element.');
+
+test(function() {
const doc = new DOMParser().parseFromString('<html writingsuggestions=""><body><input writingsuggestions="false"><textarea></textarea><div></div><span></span></body></html>', 'text/html');
assert_equals(doc.documentElement.writingSuggestions, 'true');
assert_equals(doc.body.writingSuggestions, 'true');
@@ -443,6 +565,26 @@ test(function() {
}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a span element from the empty string to "false".');
test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions=""><body><input type="color" writingsuggestions="false"><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on an input type which the attribute doesn\'t apply from the empty string to "false". The User Agent is responsible that writing suggestions are not applied to the element.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions=""><body><input><textarea disabled writingsuggestions="false"></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a disabled textarea element from the empty string to "false". The User Agent is responsible that writing suggestions are not applied to the element.');
+
+test(function() {
const doc = new DOMParser().parseFromString('<html writingsuggestions="true"><body><div contenteditable="true"><span>Writing suggestions allowed.</span> <span writingsuggestions="false">Writing suggestions not allowed.</span></div></body></html>', 'text/html');
const div = doc.querySelector('div');
const span1 = doc.querySelector('span');
diff --git a/testing/web-platform/tests/html/rendering/bidi-rendering/unicode-bidi-ua-rules.html b/testing/web-platform/tests/html/rendering/bidi-rendering/unicode-bidi-ua-rules.html
index 78bfb80e6f..00f4c96317 100644
--- a/testing/web-platform/tests/html/rendering/bidi-rendering/unicode-bidi-ua-rules.html
+++ b/testing/web-platform/tests/html/rendering/bidi-rendering/unicode-bidi-ua-rules.html
@@ -4,22 +4,104 @@
<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#bidi-rendering">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
+<script src='../../resources/common.js'></script>
<body>
<script>
- const elements = ['address', 'blockquote', 'center', 'div', 'figure',
+ function getUnicodeBidi(el) {
+ return window.getComputedStyle(el, "").unicodeBidi;
+ }
+
+ // These elements should have `unicode-bidi: isolate` in the UA stylesheet:
+ const isolateElements = ['address', 'blockquote', 'center', 'div', 'figure',
'figcaption', 'footer', 'form', 'header', 'hr', 'legend', 'listing',
'main', 'p', 'plaintext', 'pre', 'summary', 'xmp', 'article', 'aside',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hgroup', 'nav', 'section', 'search',
'table', 'caption', 'colgroup', 'col', 'thead', 'tbody', 'tfoot', 'tr',
'td', 'th', 'dir', 'dd', 'dl', 'dt', 'menu', 'ol', 'ul', 'li', 'bdi',
'output'];
- for(let tagname of elements) {
+ const allButSeparateTests = HTML5_ELEMENTS.filter(el => (!['bdo','input','textarea','pre'].includes(el)));
+ for(let tagname of allButSeparateTests) {
+ test((t) => {
+ const element = document.createElement(tagname);
+ t.add_cleanup(() => element.remove());
+ document.body.appendChild(element);
+ const expectation = isolateElements.includes(tagname) ? 'isolate' : 'normal';
+ assert_equals(getUnicodeBidi(element),expectation);
+
+ element.setAttribute('dir','ltr');
+ assert_equals(getUnicodeBidi(element),'isolate','with dir=ltr');
+ element.setAttribute('dir','LtR');
+ assert_equals(getUnicodeBidi(element),'isolate','with dir=LtR (case insensitive)');
+ element.setAttribute('dir','rtl');
+ assert_equals(getUnicodeBidi(element),'isolate','with dir=rtl');
+ element.setAttribute('dir','auto');
+ assert_equals(getUnicodeBidi(element),'isolate','with dir=auto');
+ element.setAttribute('dir','INVALID');
+ assert_equals(getUnicodeBidi(element),expectation,'invalid dir value goes back to normal defaults');
+ },`UA stylesheet rule for unicode-bidi, for <${tagname}>`);
+ }
+
+ test((t) => {
+ const element = document.createElement('bdo');
+ t.add_cleanup(() => element.remove());
+ document.body.appendChild(element);
+ assert_equals(getUnicodeBidi(element),'isolate-override');
+ element.setAttribute('dir','ltr');
+ assert_equals(getUnicodeBidi(element),'isolate-override','with dir=ltr');
+ element.setAttribute('dir','LtR');
+ assert_equals(getUnicodeBidi(element),'isolate-override','with dir=LtR (case insensitive)');
+ element.setAttribute('dir','rtl');
+ assert_equals(getUnicodeBidi(element),'isolate-override','with dir=rtl');
+ element.setAttribute('dir','auto');
+ assert_equals(getUnicodeBidi(element),'isolate-override','with dir=auto');
+ element.setAttribute('dir','INVALID');
+ assert_equals(getUnicodeBidi(element),'isolate-override','invalid dir value');
+ },`UA stylesheet rule for unicode-bidi, for <bdo>`);
+
+ const shouldBePlaintext = ['search','tel','url','email'];
+ for(let type of HTML5_INPUT_TYPES) {
+ test((t) => {
+ const element = document.createElement('input');
+ t.add_cleanup(() => element.remove());
+ element.type = type;
+ document.body.appendChild(element);
+ const autoExpectation = shouldBePlaintext.includes(type) ? 'plaintext' : 'isolate';
+ assert_equals(getUnicodeBidi(element),'normal');
+ element.setAttribute('dir','ltr');
+ assert_equals(getUnicodeBidi(element),'isolate','with dir=ltr');
+ element.setAttribute('dir','LtR');
+ assert_equals(getUnicodeBidi(element),'isolate','with dir=LtR (case insensitive)');
+ element.setAttribute('dir','rtl');
+ assert_equals(getUnicodeBidi(element),'isolate','with dir=rtl');
+ element.setAttribute('dir','auto');
+ assert_equals(getUnicodeBidi(element),autoExpectation,'with dir=auto');
+ element.setAttribute('dir','AuTo');
+ assert_equals(getUnicodeBidi(element),autoExpectation,'with dir=auto (case insensitive)');
+ element.setAttribute('dir','INVALID');
+ assert_equals(getUnicodeBidi(element),'normal','invalid dir value');
+ },`UA stylesheet rule for unicode-bidi, for <input type=${type}>`);
+ }
+
+ for(let tagname of ['textarea','pre']) {
test((t) => {
const element = document.createElement(tagname);
t.add_cleanup(() => element.remove());
document.body.appendChild(element);
- assert_equals(window.getComputedStyle(element, "").unicodeBidi,'isolate');
+ const expectation = tagname === 'textarea' ? 'normal' : 'isolate';
+ assert_equals(getUnicodeBidi(element),expectation);
+ element.setAttribute('dir','ltr');
+ assert_equals(getUnicodeBidi(element),'isolate','with dir=ltr');
+ element.setAttribute('dir','LtR');
+ assert_equals(getUnicodeBidi(element),'isolate','with dir=LtR (case insensitive)');
+ element.setAttribute('dir','rtl');
+ assert_equals(getUnicodeBidi(element),'isolate','with dir=rtl');
+ element.setAttribute('dir','auto');
+ assert_equals(getUnicodeBidi(element),'plaintext','with dir=auto');
+ element.setAttribute('dir','AuTo');
+ assert_equals(getUnicodeBidi(element),'plaintext','with dir=auto (case insensitive)');
+ element.setAttribute('dir','INVALID');
+ assert_equals(getUnicodeBidi(element),expectation,'invalid dir value');
},`UA stylesheet rule for unicode-bidi, for <${tagname}>`);
}
</script>
diff --git a/testing/web-platform/tests/html/rendering/non-replaced-elements/sections-and-headings/headings-styles-no-h1-in-section.tentative.html b/testing/web-platform/tests/html/rendering/non-replaced-elements/sections-and-headings/headings-styles-no-h1-in-section.tentative.html
new file mode 100644
index 0000000000..61610c2fd6
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/non-replaced-elements/sections-and-headings/headings-styles-no-h1-in-section.tentative.html
@@ -0,0 +1,147 @@
+<!doctype html>
+<title>default styles for h1..h6, hgroup, article, aside, nav, section (no h1 in section UA styles)</title>
+<meta name="viewport" content="width=device-width">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/rendering/support/test-ua-stylesheet.js"></script>
+<link rel="help" href="https://github.com/whatwg/html/issues/7867">
+<style>
+/* Specify this bogus namespace, so the rules in this stylesheet only apply to the `fakeClone`d elements in #refs, not the HTML elements in #tests. */
+@namespace url(urn:not-html);
+
+article, aside, h1, h2, h3, h4, h5, h6, hgroup, nav, section {
+ display: block;
+}
+
+h1 { margin-block: 0.67em; font-size: 2.00em; font-weight: bold; }
+h2 { margin-block: 0.83em; font-size: 1.50em; font-weight: bold; }
+h3 { margin-block: 1.00em; font-size: 1.17em; font-weight: bold; }
+h4 { margin-block: 1.33em; font-size: 1.00em; font-weight: bold; }
+h5 { margin-block: 1.67em; font-size: 0.83em; font-weight: bold; }
+h6 { margin-block: 2.33em; font-size: 0.67em; font-weight: bold; }
+
+</style>
+
+<div id="log"></div>
+
+<div id="tests">
+ <h1></h1>
+ <h2></h2>
+ <h3></h3>
+ <h4></h4>
+ <h5></h5>
+ <h6></h6>
+ <hgroup></hgroup>
+ <article></article>
+ <aside></aside>
+ <nav></nav>
+ <section></section>
+ <article data-skip>
+ <h1></h1>
+ <article data-skip>
+ <h1></h1>
+ <article data-skip>
+ <h1></h1>
+ <article data-skip>
+ <h1></h1>
+ <article data-skip>
+ <h1></h1>
+ <hgroup data-skip>
+ <h1></h1>
+ <h2></h2>
+ <h3></h3>
+ <h4></h4>
+ <h5></h5>
+ </hgroup>
+ </article>
+ </article>
+ </article>
+ </article>
+ </article>
+ <aside data-skip>
+ <h1></h1>
+ <aside data-skip>
+ <h1></h1>
+ <aside data-skip>
+ <h1></h1>
+ <aside data-skip>
+ <h1></h1>
+ <aside data-skip>
+ <h1></h1>
+ <hgroup data-skip>
+ <h1></h1>
+ <h2></h2>
+ <h3></h3>
+ <h4></h4>
+ <h5></h5>
+ </hgroup>
+ </aside>
+ </aside>
+ </aside>
+ </aside>
+ </aside>
+ <nav data-skip>
+ <h1></h1>
+ <nav data-skip>
+ <h1></h1>
+ <nav data-skip>
+ <h1></h1>
+ <nav data-skip>
+ <h1></h1>
+ <nav data-skip>
+ <h1></h1>
+ <hgroup data-skip>
+ <h1></h1>
+ <h2></h2>
+ <h3></h3>
+ <h4></h4>
+ <h5></h5>
+ </hgroup>
+ </nav>
+ </nav>
+ </nav>
+ </nav>
+ </nav>
+ <section data-skip>
+ <h1></h1>
+ <section data-skip>
+ <h1></h1>
+ <section data-skip>
+ <h1></h1>
+ <section data-skip>
+ <h1></h1>
+ <section data-skip>
+ <h1></h1>
+ <hgroup data-skip>
+ <h1></h1>
+ <h2></h2>
+ <h3></h3>
+ <h4></h4>
+ <h5></h5>
+ </hgroup>
+ </section>
+ </section>
+ </section>
+ </section>
+ </section>
+</div>
+
+<div id="refs"></div>
+
+<script>
+ const props = [
+ 'display',
+ 'margin-top',
+ 'margin-right',
+ 'margin-bottom',
+ 'margin-left',
+ 'padding-top',
+ 'padding-right',
+ 'padding-bottom',
+ 'padding-left',
+ 'font-size',
+ 'font-weight',
+ ];
+ runUAStyleTests(props);
+
+</script>
diff --git a/testing/web-platform/tests/html/rendering/non-replaced-elements/sections-and-headings/headings-styles.html b/testing/web-platform/tests/html/rendering/non-replaced-elements/sections-and-headings/headings-styles.html
index 63e6a83e88..be531adfcf 100644
--- a/testing/web-platform/tests/html/rendering/non-replaced-elements/sections-and-headings/headings-styles.html
+++ b/testing/web-platform/tests/html/rendering/non-replaced-elements/sections-and-headings/headings-styles.html
@@ -12,18 +12,18 @@ article, aside, h1, h2, h3, h4, h5, h6, hgroup, nav, section {
display: block;
}
-h1 { margin-block-start: 0.67em; margin-block-end: 0.67em; font-size: 2.00em; font-weight: bold; }
-h2 { margin-block-start: 0.83em; margin-block-end: 0.83em; font-size: 1.50em; font-weight: bold; }
-h3 { margin-block-start: 1.00em; margin-block-end: 1.00em; font-size: 1.17em; font-weight: bold; }
-h4 { margin-block-start: 1.33em; margin-block-end: 1.33em; font-size: 1.00em; font-weight: bold; }
-h5 { margin-block-start: 1.67em; margin-block-end: 1.67em; font-size: 0.83em; font-weight: bold; }
-h6 { margin-block-start: 2.33em; margin-block-end: 2.33em; font-size: 0.67em; font-weight: bold; }
+h1 { margin-block: 0.67em; font-size: 2.00em; font-weight: bold; }
+h2 { margin-block: 0.83em; font-size: 1.50em; font-weight: bold; }
+h3 { margin-block: 1.00em; font-size: 1.17em; font-weight: bold; }
+h4 { margin-block: 1.33em; font-size: 1.00em; font-weight: bold; }
+h5 { margin-block: 1.67em; font-size: 0.83em; font-weight: bold; }
+h6 { margin-block: 2.33em; font-size: 0.67em; font-weight: bold; }
-:is(article, aside, nav, section) h1 { margin-block-start: 0.83em; margin-block-end: 0.83em; font-size: 1.50em; }
-:is(article, aside, nav, section) :is(article, aside, nav, section) h1 { margin-block-start: 1.00em; margin-block-end: 1.00em; font-size: 1.17em; }
-:is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) h1 { margin-block-start: 1.33em; margin-block-end: 1.33em; font-size: 1.00em; }
-:is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) h1 { margin-block-start: 1.67em; margin-block-end: 1.67em; font-size: 0.83em; }
-:is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) h1 { margin-block-start: 2.33em; margin-block-end: 2.33em; font-size: 0.67em; }
+:is(article, aside, nav, section) h1 { margin-block: 0.83em; font-size: 1.50em; }
+:is(article, aside, nav, section) :is(article, aside, nav, section) h1 { margin-block: 1.00em; font-size: 1.17em; }
+:is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) h1 { margin-block: 1.33em; font-size: 1.00em; }
+:is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) h1 { margin-block: 1.67em; font-size: 0.83em; }
+:is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) :is(article, aside, nav, section) h1 { margin-block: 2.33em; font-size: 0.67em; }
</style>
diff --git a/testing/web-platform/tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-overflow.html b/testing/web-platform/tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-overflow.html
index 83813f9020..089b0d9300 100644
--- a/testing/web-platform/tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-overflow.html
+++ b/testing/web-platform/tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-overflow.html
@@ -1,5 +1,6 @@
<!DOCTYPE HTML>
<title>fieldset overflow</title>
+<meta name="fuzzy" content="1;0-50">
<link rel=match href=fieldset-overflow-ref.html>
<style>
fieldset, legend {
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-button-min-height-001-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-button-min-height-001-ref.html
new file mode 100644
index 0000000000..c35ad5fc42
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-button-min-height-001-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<style>
+ select, input, button { height: 100px; }
+</style>
+<div>
+ <select><option>Select</option></select>
+ <button>Button</button>
+ <input type="button" value="Input">
+</div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-button-min-height-001.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-button-min-height-001.html
new file mode 100644
index 0000000000..c099105076
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-button-min-height-001.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>min-height and height both trigger same rendering for select and buttons by default</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1362907">
+<link rel="match" href="select-button-min-height-001-ref.html">
+<style>
+ select, input, button { min-height: 100px; }
+</style>
+<div>
+ <select><option>Select</option></select>
+ <button>Button</button>
+ <input type="button" value="Input">
+</div>
diff --git a/testing/web-platform/tests/html/rendering/widgets/field-sizing-textarea.html b/testing/web-platform/tests/html/rendering/widgets/field-sizing-textarea.html
index f8d90dc659..114d60c72d 100644
--- a/testing/web-platform/tests/html/rendering/widgets/field-sizing-textarea.html
+++ b/testing/web-platform/tests/html/rendering/widgets/field-sizing-textarea.html
@@ -3,6 +3,10 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
+textarea {
+ font-family: monospace;
+}
+
.disable-default {
field-sizing: content;
}
diff --git a/testing/web-platform/tests/html/resources/common.js b/testing/web-platform/tests/html/resources/common.js
index 4f9ec54dde..fd4529e80a 100644
--- a/testing/web-platform/tests/html/resources/common.js
+++ b/testing/web-platform/tests/html/resources/common.js
@@ -49,6 +49,12 @@ const HTML5_DEPRECATED_ELEMENTS = [
'rtc', 'shadow', 'spacer', 'strike', 'tt', 'xmp'
];
+const HTML5_INPUT_TYPES = [
+ 'hidden', 'text', 'search', 'tel', 'url', 'email', 'password', 'date',
+ 'time', 'datetime-local', 'number', 'range', 'color', 'checkbox', 'radio',
+ 'file', 'submit', 'image', 'reset', 'button'
+];
+
function newDocument() {
var d = document.implementation.createDocument();
return d;
diff --git a/testing/web-platform/tests/html/semantics/disabled-elements/event-propagate-disabled.tentative.html b/testing/web-platform/tests/html/semantics/disabled-elements/event-propagate-disabled.tentative.html
index e3dcd43a17..2be6dc72fe 100644
--- a/testing/web-platform/tests/html/semantics/disabled-elements/event-propagate-disabled.tentative.html
+++ b/testing/web-platform/tests/html/semantics/disabled-elements/event-propagate-disabled.tentative.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<meta charset="utf8">
<meta name="timeout" content="long">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event propagation on disabled form elements</title>
<link rel="author" href="mailto:krosylight@mozilla.com">
<link rel="help" href="https://github.com/whatwg/html/issues/2368">
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/302-no-Location-header-text-css.asis b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/302-no-Location-header-text-css.asis
new file mode 100644
index 0000000000..ddf4898d3f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/302-no-Location-header-text-css.asis
@@ -0,0 +1,4 @@
+HTTP/1.1 302 Found
+Content-Type: text/css
+
+body { background-color: red; }
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css.headers b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css.headers
new file mode 100644
index 0000000000..156209f9c8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type-empty.css.headers
@@ -0,0 +1 @@
+Content-Type: text/html
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css
new file mode 100644
index 0000000000..e1b2552ffe
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css
@@ -0,0 +1,3 @@
+body {
+ background-color: green;
+}
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css.headers b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css.headers
new file mode 100644
index 0000000000..156209f9c8
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet-bad-mime-type.css.headers
@@ -0,0 +1 @@
+Content-Type: text/html
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-bad-mime-type.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-bad-mime-type.html
new file mode 100644
index 0000000000..08176d6cd2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-bad-mime-type.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>stylesheets served with bad MIME types</title>
+<link rel="author" title="Michael[tm] Smith" href="mailto:mike@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/#link-type-stylesheet:process-the-linked-resource">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ async_test((t) => {
+ const link = document.createElement("link");
+ link.rel = "stylesheet";
+ link.href = "resources/stylesheet-bad-mime-type.css";
+ link.onload = t.unreached_func();
+ link.onerror = t.step_func_done();
+ document.head.append(link);
+ }, "'load' event does not fire at link@rel=stylesheet having non-empty resource with bad MIME type");
+ async_test((t) => {
+ t.step_timeout(() => {
+ const link = document.createElement("link");
+ link.rel = "stylesheet";
+ link.href = "resources/stylesheet-bad-mime-type-empty.css";
+ link.onload = t.unreached_func();
+ link.onerror = t.step_func_done();
+ document.head.append(link);
+ }, 2000);
+ }, "'load' event does not fire at link@rel=stylesheet having empty resource with bad MIME type");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-non-OK-status.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-non-OK-status.html
new file mode 100644
index 0000000000..28ac55ff1a
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-non-OK-status.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>stylesheet served with non-OK status</title>
+<link rel="author" title="Michael[tm] Smith" href="mailto:mike@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/#fetching-and-processing-a-resource-from-a-link-element:processresponseconsumebody">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ async_test((t) => {
+ const link = document.createElement("link");
+ link.rel = "stylesheet";
+ link.href = "resources/302-no-Location-header-text-css.asis";
+ link.onload = t.unreached_func();
+ link.onerror = t.step_func_done();
+ document.head.append(link);
+ }, "'load' event does not fire at link@rel=stylesheet having resource with non-OK response status");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime-move-within-document.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime-move-within-document.html
new file mode 100644
index 0000000000..22b579d720
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime-move-within-document.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>playback should not reset when moving within a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<video autoplay muted hidden></video>
+<div id="elsewhere"></div>
+<script>
+async_test(t => {
+ const v = document.querySelector('video');
+ v.src = getVideoURI('/media/movie_300');
+ v.currentTime = 0;
+ v.onplaying = t.step_func(() => {
+ v.currentTime = 10;
+ t.step_timeout(() => {
+ assert_greater_than_equal(v.currentTime, 10);
+ document.getElementById('elsewhere').appendChild(v);
+ assert_false(v.paused, 'paused after moving');
+ assert_greater_than_equal(v.currentTime, 10);
+ t.step_timeout(() => {
+ assert_greater_than_equal(v.currentTime, 10);
+ t.done();
+ }, 0);
+ }, 0);
+
+ });
+ v.play();
+ v.onpause = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-scroller-nested-2.html b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-scroller-nested-2.html
index d080831175..9eec621c89 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-scroller-nested-2.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-scroller-nested-2.html
@@ -31,7 +31,7 @@
<div id=scroller2>
<div id="spacer"></div>
<div id="scroller">
- <iframe>
+ <iframe
id="target"
src="resources/subframe.html"
loading="lazy"
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.https.html
index 6b3b3104ef..6b3b3104ef 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads.sub.tentative.https.html
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.html b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.https.html
index 158fc4f947..158fc4f947 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_window_open_download_allow_downloads.tentative.https.html
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.sub.js
index 413f392dfc..bec8f6a64a 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.js
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/resources/sandbox-top-navigation-helper.sub.js
@@ -5,7 +5,7 @@
// // META: script=/resources/testdriver.js
// // META: script=/resources/testdriver-vendor.js
// // META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
-// // META: script=./resources/sandbox-top-navigation-helper.js
+// // META: script=./resources/sandbox-top-navigation-helper.sub.js
// Helper file that provides various functions to test top-level navigation
// with various frame and sandbox flag configurations.
@@ -27,18 +27,28 @@ async function createNestedIframe(parent, origin, frame_sandbox, header_sandbox)
origin: origin,
scripts: [
'/resources/testdriver.js',
- '/resources/testdriver-driver.js',
- '/resources/testdriver-vendor.js'
+ '/resources/testdriver-vendor.js',
],
headers: headers,
}, iframe_attributes);
}
+async function navigateFrameTo(frame, origin) {
+ return frame.navigateToNew({
+ origin: origin,
+ scripts: [
+ '/resources/testdriver.js',
+ '/resources/testdriver-vendor.js',
+ ],
+ });
+}
+
async function attemptTopNavigation(iframe, should_succeed) {
let did_succeed;
try {
await iframe.executeScript(() => {
- window.top.location.href = "https://google.com";
+ window.top.location.href =
+ 'http://{{hosts[alt][www2]}}:{{ports[http][0]}}';
});
did_succeed = true;
} catch (e) {
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin.tentative.sub.window.js
new file mode 100644
index 0000000000..95d53e1fe3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-cross-origin.tentative.sub.window.js
@@ -0,0 +1,28 @@
+// META: title=Top-level navigation tests with cross origin & user activated child frames
+// META: script=/common/dispatcher/dispatcher.js
+// META: script=/common/get-host-info.sub.js
+// META: script=/common/utils.js
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
+
+'use strict';
+
+// /* ---------------------- CROSS ORIGIN (A -> B) TESTS ---------------------- */
+
+promise_test(async t => {
+ const main = await setupTest();
+ const iframe_1 = await createNestedIframe(main,
+ "HTTP_REMOTE_ORIGIN", "allow-top-navigation", "");
+
+ await attemptTopNavigation(iframe_1, true);
+}, "A cross-origin frame with frame sandbox flags can navigate top");
+
+promise_test(async t => {
+ const main = await setupTest();
+ const iframe_1 = await createNestedIframe(main,
+ "HTTP_REMOTE_ORIGIN", "", "allow-top-navigation");
+
+ await attemptTopNavigation(iframe_1, false);
+}, "A cross-origin frame with delivered sandbox flags can not navigate top");
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js
index 53faa99a40..1d5ea93830 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js
@@ -5,7 +5,7 @@
// META: script=/resources/testdriver.js
// META: script=/resources/testdriver-vendor.js
// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
-// META: script=./resources/sandbox-top-navigation-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
'use strict';
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-site.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-site.tentative.sub.window.js
new file mode 100644
index 0000000000..26db4eeaca
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-cross-site.tentative.sub.window.js
@@ -0,0 +1,43 @@
+// META: title=Top-level navigation tests with cross origin & user activated child frames
+// META: script=/common/dispatcher/dispatcher.js
+// META: script=/common/get-host-info.sub.js
+// META: script=/common/utils.js
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-actions.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
+
+'use strict';
+
+promise_test(async t => {
+ const main = await setupTest();
+
+ const iframe = await createNestedIframe(main, "HTTP_ORIGIN", "", "");
+ await activate(iframe);
+
+ const new_iframe = await navigateFrameTo(iframe, "HTTPS_REMOTE_ORIGIN");
+ await attemptTopNavigation(new_iframe, false);
+}, "A cross-site unsandboxed iframe navigation consumes user activation and " +
+ "disallows top-level navigation.");
+
+promise_test(async t => {
+ const main = await setupTest();
+
+ const iframe = await createNestedIframe(main, "HTTP_ORIGIN", "", "");
+ await activate(iframe);
+
+ const new_iframe = await navigateFrameTo(iframe, "HTTP_REMOTE_ORIGIN");
+ await attemptTopNavigation(new_iframe, true);
+}, "A same-site unsandboxed iframe navigation does not consume user " +
+ "activation and allows top-level navigation.");
+
+promise_test(async t => {
+ const main = await setupTest();
+
+ const iframe = await createNestedIframe(main, "HTTP_ORIGIN", "", "");
+
+ const new_iframe = await navigateFrameTo(iframe, "HTTP_REMOTE_ORIGIN");
+ await attemptTopNavigation(new_iframe, false);
+}, "A same-site unsandboxed iframe navigation without sticky user activation " +
+ "does not allow top-level navigation.");
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js
index a5cda9b0b9..2ea0ba606e 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js
@@ -5,7 +5,7 @@
// META: script=/resources/testdriver.js
// META: script=/resources/testdriver-vendor.js
// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
-// META: script=./resources/sandbox-top-navigation-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
'use strict';
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js
index a07148f802..326c1dd54a 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js
@@ -5,7 +5,7 @@
// META: script=/resources/testdriver.js
// META: script=/resources/testdriver-vendor.js
// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
-// META: script=./resources/sandbox-top-navigation-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
'use strict';
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation.tentative.sub.window.js
index 8681411dd7..5079c8ad14 100644
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-user-activation.tentative.sub.window.js
@@ -3,9 +3,10 @@
// META: script=/common/get-host-info.sub.js
// META: script=/common/utils.js
// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-actions.js
// META: script=/resources/testdriver-vendor.js
// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
-// META: script=./resources/sandbox-top-navigation-helper.js
+// META: script=./resources/sandbox-top-navigation-helper.sub.js
'use strict';
@@ -27,21 +28,3 @@ promise_test(async t => {
await attemptTopNavigation(iframe_1, false);
}, "allow-top-navigation-by-user-activation set but no sticky activation");
-
-/* ---------------------- CROSS ORIGIN (A -> B) TESTS ---------------------- */
-
-promise_test(async t => {
- const main = await setupTest();
- const iframe_1 = await createNestedIframe(main,
- "HTTP_REMOTE_ORIGIN", "allow-top-navigation", "");
-
- await attemptTopNavigation(iframe_1, true);
-}, "A cross-origin frame with frame sandbox flags can navigate top");
-
-promise_test(async t => {
- const main = await setupTest();
- const iframe_1 = await createNestedIframe(main,
- "HTTP_REMOTE_ORIGIN", "", "allow-top-navigation");
-
- await attemptTopNavigation(iframe_1, false);
-}, "A cross-origin frame with delivered sandbox flags can not navigate top");
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-attribute-crash.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-attribute-crash.html
new file mode 100644
index 0000000000..5330411a5d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-attribute-crash.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html class=test-wait>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://issues.chromium.org/324325525">
+
+<!-- Attempting to slot a child of <select> after initial slot assignment should not crash. -->
+
+<select size=1>
+ <optgroup></optgroup>
+</select>
+<script>
+requestAnimationFrame(() => {
+ document.querySelector('optgroup').setAttribute('slot', 'slot1');
+ requestAnimationFrame(() => {
+ document.documentElement.classList.remove('test-wait');
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-invalidation.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-invalidation.tentative.html
new file mode 100644
index 0000000000..f71c1e52fc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist-invalidation.tentative.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://github.com/whatwg/html/issues/9799">
+<link rel=match href="select-child-button-and-datalist-ref.html">
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<select>
+ <button type=popover>button</button>
+ <datalist>
+ <option>one</option>
+ <option>two</option>
+ </datalist>
+</select>
+
+<script>
+requestAnimationFrame(() => {
+ document.querySelector('select').style = 'appearance:bikeshed';
+ document.querySelector('button').click();
+ document.documentElement.classList.remove('reftest-wait');
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist.tentative.html
index b74957feed..54785ace95 100644
--- a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist.tentative.html
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-child-button-and-datalist.tentative.html
@@ -5,7 +5,7 @@
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
-<select>
+<select style="appearance:bikeshed">
<button type=popover>button</button>
<datalist>
<option>one</option>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-datalist-options-idl.tentative.html b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-datalist-options-idl.tentative.html
new file mode 100644
index 0000000000..993f6e126c
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-datalist-options-idl.tentative.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://github.com/whatwg/html/issues/9799">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<select>
+ <datalist>
+ <option class=one>one</option>
+ <div>
+ <option class=two>two</option>
+ </div>
+ <option class=three>three</option>
+ </datalist>
+</select>
+
+<script>
+const select = document.querySelector('select');
+
+function runTest() {
+ const datalist = select.querySelector('datalist');
+ const firstOption = select.querySelector('option.one');
+ const secondOption = select.querySelector('option.two');
+ const thirdOption = select.querySelector('option.three');
+ const datalistChildDiv = datalist.querySelector('div');
+
+ let selectChildDiv = document.querySelector('select > div');
+ if (!selectChildDiv) {
+ selectChildDiv = document.createElement('div');
+ select.appendChild(selectChildDiv);
+ }
+
+ assert_equals(select.length, 3, 'select.length');
+ assert_equals(select.options.length, 3, 'select.options.length');
+ assert_equals(select.options[0], firstOption, 'select.options[0]');
+ assert_equals(select.options[1], secondOption, 'select.options[1]');
+ assert_equals(select.options[2], thirdOption, 'select.options[2]');
+
+ assert_equals(select.value, 'one', 'initial select.value');
+ select.value = 'two';
+ assert_equals(select.value, 'two', 'select.value after modifying');
+
+ secondOption.remove();
+ assert_equals(select.length, 2, 'select.length after removing an option');
+ assert_equals(select.options.length, 2, 'select.options.length after removing an option');
+ assert_equals(select.options[0], firstOption, 'select.options[0] after removing an option');
+ assert_equals(select.options[1], thirdOption, 'select.options[1] after removing an option');
+
+ datalist.appendChild(secondOption);
+ assert_equals(select.length, 3, 'select.length after re-adding an option');
+ assert_equals(select.options.length, 3, 'select.options.length after re-adding an option');
+ assert_equals(select.options[0], firstOption, 'select.options[0] after re-adding an option');
+ assert_equals(select.options[1], thirdOption, 'select.options[1] after re-adding an option');
+ assert_equals(select.options[2], secondOption, 'select.options[2] after re-adding an option');
+
+ selectChildDiv.appendChild(secondOption);
+ assert_equals(select.length, 2, 'select.length after moving option to child div');
+ assert_equals(select.options.length, 2, 'select.options.length after moving option to child div');
+ assert_equals(select.options[0], firstOption, 'select.options[0] after moving option to child div');
+ assert_equals(select.options[1], thirdOption, 'select.options[1] after moving option to child div');
+
+ // reset back to normal for the next test
+ datalistChildDiv.appendChild(secondOption);
+ select.value = 'one';
+}
+
+test(() => {
+ runTest();
+}, 'Option elements should work if they are a descendant of a selects datalist.');
+
+test(() => {
+ select.setAttribute('multiple', '');
+ runTest();
+}, 'Options in datalist should still work when the multiple attribute is added.');
+
+test(() => {
+ select.innerHTML = select.innerHTML;
+ select.value = 'one';
+ runTest();
+}, 'Options in datalist in multiple should work after re-parsing and re-attaching.');
+</script>
diff --git a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html
index e368bde6fb..db757861e7 100644
--- a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html
+++ b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html
@@ -66,6 +66,7 @@ promise_test(async () => {
event.preventDefault();
});
+ await test_driver.bless();
bottomDialog.showModal();
await blessTopLayer(bottomDialog);
topDialog.showModal();
diff --git a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-open.html b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-open.html
index e1f4c6ab82..bcd6ebebc1 100644
--- a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-open.html
+++ b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/dialog-open.html
@@ -37,7 +37,9 @@
// close event is async, give it a chance to be fired
t.step_timeout(function() {
- t.done();
+ requestAnimationFrame(() => {
+ t.done();
+ });
}, 0);
}, "On setting it to false, the close event should not be fired");
</script>
diff --git a/testing/web-platform/tests/html/semantics/interactive-elements/the-summary-element/interactive-content.html b/testing/web-platform/tests/html/semantics/interactive-elements/the-summary-element/interactive-content.html
new file mode 100644
index 0000000000..94869dc9b6
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/interactive-elements/the-summary-element/interactive-content.html
@@ -0,0 +1,232 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>summary element: interactive content</title>
+<link rel="author" title="Michael[tm] Smith" href="mailto:mike@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interactive-elements.html#the-summary-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<details>
+ <summary id=summary>
+ <a id=a href="#">anchor element</a>
+ <svg style="width: 160px; height: 100px" viewBox="0 0 100 100">
+ <a href="#" id="svg_a"><text id="svg_text" x="50" y="90" text-anchor="middle">SVG anchor element</text></a>
+ </svg>
+ <svg style="width: 100px; height: 200px" viewBox="0 0 100 100">
+ <foreignObject x="0" y="60" width="100" height="200" text-anchor="middle">
+ <a xmlns="http://www.w3.org/1999/xhtml" href="#" id="svg_foreignObject_a">SVG foreignObject with HTML anchor element</a>
+ </foreignObject>
+ </svg>
+ <audio id="audio" controls src=/media/sound_5.mp3></audio>
+ <button id=button>button element</button>
+ <embed id=embed src="/images/blue.png" height="100" width="100">
+ <iframe id=iframe srcdoc="iframe element"></iframe>
+ <img id=img_usemap usemap src=/media/poster.png></img>
+ <img id=img src=/media/poster.png></img>
+ <input type="text" value="input@type=text" id="input_text">
+ <input type="search" value="input@type=search" id="input_search">
+ <input type="tel" value="input@type=tel" id="input_tel">
+ <input type="url" value="input@type=url" id="input_url">
+ <input type="email" value="input@type=email" id="input_email">
+ <input type="password" value="input@type=password" id="input_password">
+ <input type="button" value="input@type=button" id="input_button">
+ <input type="reset" id="input_reset">
+ <input type="submit" id="input_submit">
+ <input type="date" value="input@type=date" id="input_date">
+ <input type="month" value="input@type=month" id="input_month">
+ <input type="week" value="input@type=week" id="input_week">
+ <input type="time" id="input_time">
+ <input type="datetime-local" id="input_datetime-local">
+ <input type="color" id="input_color">
+ <input type="number" value="1337" id="input_number">
+ <input type="range" id="input_range">
+ <input type="checkbox" id="input_checkbox">
+ <input type="radio" id="input_radio" disabled>
+ <input type="file" id="input_file">
+ <input type="image" id="input_image" src=/media/poster.png>
+ <label id=label style="display: block">label element</label>
+ <textarea value="textarea" id="textarea">textarea element</textarea>
+ <video id="video" controls>
+ <source src="/media/test-1s.mp4" type="video/mp4">
+ <source src="/media/test-1s.webm" type="video/webm">
+ </video>
+ <div id="non-interactive">This is clickable summary text</div>
+ </summary>
+</details>
+
+<script>
+const details = document.querySelector("details");
+
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("non-interactive"));
+ assert_true(details.open)
+}, "Clicking on non-interactive child of a <summary> opens its <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("a"));
+ assert_false(details.open)
+}, "Clicking an <a> link doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("svg_a"));
+ assert_false(details.open)
+}, "Clicking an SVG <a> link doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("svg_foreignObject_a"));
+ assert_false(details.open)
+}, "Clicking an HTML <a> link in an SVG <foreignObject> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("audio"));
+ assert_false(details.open)
+}, "Clicking an <audio> element doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("button"));
+ assert_false(details.open)
+}, "Clicking a <button> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("embed"));
+ assert_false(details.open)
+}, "Clicking the content of an <embed> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("iframe"));
+ assert_false(details.open)
+}, "Clicking in an <iframe> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("img_usemap"));
+ assert_false(details.open)
+}, "Clicking an <img> with a 'usemap' attribute doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("img"));
+ assert_true(details.open)
+}, "Clicking an <img> without a 'usemap' attribute opens <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_button"));
+ assert_false(details.open)
+}, "Clicking an <input type=button> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_reset"));
+ assert_false(details.open)
+}, "Clicking an <input type=reset> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_submit"));
+ assert_false(details.open)
+}, "Clicking an <input type=submit> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_text"));
+ assert_false(details.open)
+}, "Clicking an <input type=text> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_search"));
+ assert_false(details.open)
+}, "Clicking an <input type=search> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_tel"));
+ assert_false(details.open)
+}, "Clicking an <input type=tel> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_url"));
+ assert_false(details.open)
+}, "Clicking an <input type=url> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_email"));
+ assert_false(details.open)
+}, "Clicking an <input type=email> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_password"));
+ assert_false(details.open)
+}, "Clicking an <input type=password> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_date"));
+ assert_false(details.open)
+}, "Clicking an <input type=date> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_month"));
+ assert_false(details.open)
+}, "Clicking an <input type=month> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_week"));
+ assert_false(details.open)
+}, "Clicking an <input type=week> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_time"));
+ assert_false(details.open)
+}, "Clicking an <input type=time> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_datetime-local"));
+ assert_false(details.open)
+}, "Clicking an <input type=datetime-local> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_number"));
+ assert_false(details.open)
+}, "Clicking an <input type=number> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_range"));
+ assert_false(details.open)
+}, "Clicking an <input type=range> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_color"));
+ assert_false(details.open)
+}, "Clicking an <input type=color> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_checkbox"));
+ assert_false(details.open)
+}, "Clicking an <input type=checkbox> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_radio"));
+ assert_false(details.open)
+}, "Clicking an <input type=radio> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_file"));
+ assert_false(details.open)
+}, "Clicking an <input type=file> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("input_image"));
+ assert_false(details.open)
+}, "Clicking an <input type=image> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("label"));
+ assert_false(details.open)
+}, "Clicking a <label> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("textarea"));
+ assert_false(details.open)
+}, "Clicking in a <textarea> doesn't open <details>");
+promise_test(async () => {
+ details.open = false;
+ await test_driver.click(document.getElementById("video"));
+ assert_false(details.open)
+}, "Clicking a <video> doesn't open <details>");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/invokers/interestelement-interface.tentative.html b/testing/web-platform/tests/html/semantics/invokers/interestelement-interface.tentative.html
new file mode 100644
index 0000000000..dc119de833
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/invokers/interestelement-interface.tentative.html
@@ -0,0 +1,164 @@
+<!doctype html>
+<meta charset="utf-8" />
+<meta name="author" title="Luke Warlow" href="mailto:lwarlow@igalia.com" />
+<link rel="help" href="https://open-ui.org/components/interest-invokers.explainer/" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<button id="buttonInvoker" interesttarget="interestee"></button>
+<a id="aInvoker" interesttarget="interestee"></a>
+<input type="button" id="inputInvoker" interesttarget="interestee" />
+<div id="interestee"></div>
+
+<script>
+ test(function () {
+ assert_equals(buttonInvoker.interestTargetElement, interestee);
+ assert_equals(aInvoker.interestTargetElement, interestee);
+ assert_equals(inputInvoker.interestTargetElement, interestee);
+ }, "interestTargetElement reflects interestee HTML element");
+
+ test(function () {
+ const div = document.body.appendChild(document.createElement("div"));
+ buttonInvoker.interestTargetElement = div;
+ aInvoker.interestTargetElement = div;
+ inputInvoker.interestTargetElement = div;
+ assert_equals(buttonInvoker.interestTargetElement, div);
+ assert_equals(buttonInvoker.getAttribute("interesttarget"), "");
+ assert_equals(aInvoker.interestTargetElement, div);
+ assert_equals(aInvoker.getAttribute("interesttarget"), "");
+ assert_equals(inputInvoker.interestTargetElement, div);
+ assert_equals(inputInvoker.getAttribute("interesttarget"), "");
+ }, "interestTargetElement reflects set value");
+
+ test(function () {
+ const host = document.body.appendChild(document.createElement("div"));
+ const shadow = host.attachShadow({ mode: "open" });
+ const button = shadow.appendChild(document.createElement("button"));
+ button.interestTargetElement = interestee;
+ assert_equals(button.interestTargetElement, interestee);
+ assert_equals(buttonInvoker.getAttribute("interesttarget"), "");
+ }, "interestTargetElement reflects set value across shadow root into light dom");
+
+ test(function () {
+ const host = document.body.appendChild(document.createElement("div"));
+ const shadow = host.attachShadow({ mode: "open" });
+ const div = shadow.appendChild(document.createElement("div"));
+ buttonInvoker.interestTargetElement = div;
+ assert_equals(buttonInvoker.interestTargetElement, null);
+ assert_equals(buttonInvoker.getAttribute("interesttarget"), "");
+ }, "interestTargetElement does not reflect set value inside shadowroot");
+
+ test(function () {
+ buttonInvoker.setAttribute('interesttarget', 'invalid');
+ assert_equals(buttonInvoker.interestTargetElement, null);
+ assert_equals(buttonInvoker.getAttribute("interesttarget"), "invalid");
+ aInvoker.setAttribute('interesttarget', 'invalid');
+ assert_equals(aInvoker.interestTargetElement, null);
+ assert_equals(aInvoker.getAttribute("interesttarget"), "invalid");
+ inputInvoker.setAttribute('interesttarget', 'invalid');
+ assert_equals(inputInvoker.interestTargetElement, null);
+ assert_equals(inputInvoker.getAttribute("interesttarget"), "invalid");
+ }, "interestTargetElement does not reflect invalid value");
+
+ test(function () {
+ assert_throws_js(
+ TypeError,
+ function () {
+ buttonInvoker.interestTargetElement = {};
+ },
+ "interestTargetElement attribute value must be an instance of Element",
+ );
+ assert_throws_js(
+ TypeError,
+ function () {
+ aInvoker.interestTargetElement = {};
+ },
+ "interestTargetElement attribute value must be an instance of Element",
+ );
+ assert_throws_js(
+ TypeError,
+ function () {
+ inputInvoker.interestTargetElement = {};
+ },
+ "interestTargetElement attribute value must be an instance of Element",
+ );
+ }, "interestTargetElement throws error on assignment of non Element");
+
+ test(function () {
+ assert_false(buttonInvoker.hasAttribute("interestaction"));
+ assert_equals(buttonInvoker.interestAction, "");
+ assert_false(aInvoker.hasAttribute("interestaction"));
+ assert_equals(aInvoker.interestAction, "");
+ assert_false(inputInvoker.hasAttribute("interestaction"));
+ assert_equals(inputInvoker.interestAction, "");
+ }, "interestAction reflects '' when attribute not present");
+
+ test(function () {
+ buttonInvoker.setAttribute("interestaction", "");
+ assert_equals(buttonInvoker.getAttribute("interestaction"), "");
+ assert_equals(buttonInvoker.interestAction, "");
+ aInvoker.setAttribute("interestaction", "");
+ assert_equals(aInvoker.getAttribute("interestaction"), "");
+ assert_equals(aInvoker.interestAction, "");
+ inputInvoker.setAttribute("interestaction", "");
+ assert_equals(inputInvoker.getAttribute("interestaction"), "");
+ assert_equals(inputInvoker.interestAction, "");
+ }, "interestAction reflects '' when attribute empty, setAttribute version");
+
+ test(function () {
+ buttonInvoker.interestAction = "";
+ assert_equals(buttonInvoker.getAttribute("interestaction"), "");
+ assert_equals(buttonInvoker.interestAction, "");
+ aInvoker.interestAction = "";
+ assert_equals(aInvoker.getAttribute("interestaction"), "");
+ assert_equals(aInvoker.interestAction, "");
+ inputInvoker.interestAction = "";
+ assert_equals(inputInvoker.getAttribute("interestaction"), "");
+ assert_equals(inputInvoker.interestAction, "");
+ }, "interestAction reflects '' when attribute empty, IDL setter version");
+
+ test(function () {
+ buttonInvoker.interestAction = "fooBarBaz";
+ assert_equals(buttonInvoker.getAttribute("interestaction"), "fooBarBaz");
+ assert_equals(buttonInvoker.interestAction, "fooBarBaz");
+ aInvoker.interestAction = "fooBarBaz";
+ assert_equals(aInvoker.getAttribute("interestaction"), "fooBarBaz");
+ assert_equals(aInvoker.interestAction, "fooBarBaz");
+ inputInvoker.interestAction = "fooBarBaz";
+ assert_equals(inputInvoker.getAttribute("interestaction"), "fooBarBaz");
+ assert_equals(inputInvoker.interestAction, "fooBarBaz");
+ }, "interestAction reflects same casing");
+
+ test(function () {
+ buttonInvoker.interestAction = [];
+ assert_equals(buttonInvoker.getAttribute("interestaction"), "");
+ assert_equals(buttonInvoker.interestAction, "");
+ aInvoker.interestAction = [];
+ assert_equals(aInvoker.getAttribute("interestaction"), "");
+ assert_equals(aInvoker.interestAction, "");
+ inputInvoker.interestAction = [];
+ assert_equals(inputInvoker.getAttribute("interestaction"), "");
+ assert_equals(inputInvoker.interestAction, "");
+ }, "interestAction reflects '' when attribute set to []");
+
+ test(function () {
+ buttonInvoker.interestAction = [1, 2, 3];
+ assert_equals(buttonInvoker.getAttribute("interestaction"), "1,2,3");
+ assert_equals(buttonInvoker.interestAction, "1,2,3");
+ aInvoker.interestAction = [1, 2, 3];
+ assert_equals(aInvoker.getAttribute("interestaction"), "1,2,3");
+ assert_equals(aInvoker.interestAction, "1,2,3");
+ inputInvoker.interestAction = [1, 2, 3];
+ assert_equals(inputInvoker.getAttribute("interestaction"), "1,2,3");
+ assert_equals(inputInvoker.interestAction, "1,2,3");
+ }, "interestAction reflects tostring value");
+
+ test(function () {
+ buttonInvoker.interestAction = {};
+ assert_equals(buttonInvoker.interestAction, "[object Object]");
+ aInvoker.interestAction = {};
+ assert_equals(aInvoker.interestAction, "[object Object]");
+ inputInvoker.interestAction = {};
+ assert_equals(inputInvoker.interestAction, "[object Object]");
+ }, "interestAction reflects tostring value 2");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/invokers/invokeelement-interface.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invokeelement-interface.tentative.html
index b003daf20d..5a2854fe31 100644
--- a/testing/web-platform/tests/html/semantics/invokers/invokeelement-interface.tentative.html
+++ b/testing/web-platform/tests/html/semantics/invokers/invokeelement-interface.tentative.html
@@ -53,14 +53,14 @@
test(function () {
assert_false(invoker.hasAttribute("invokeaction"));
- assert_equals(invoker.invokeAction, "auto");
- }, "invokeAction reflects 'auto' when attribute not present");
+ assert_equals(invoker.invokeAction, "");
+ }, "invokeAction reflects '' when attribute not present");
test(function () {
invoker.setAttribute("invokeaction", "");
assert_equals(invoker.getAttribute("invokeaction"), "");
- assert_equals(invoker.invokeAction, "auto");
- }, "invokeAction reflects 'auto' when attribute empty");
+ assert_equals(invoker.invokeAction, "");
+ }, "invokeAction reflects '' when attribute empty, setAttribute version");
test(function () {
invoker.invokeAction = "fooBarBaz";
@@ -71,8 +71,8 @@
test(function () {
invoker.invokeAction = "";
assert_equals(invoker.getAttribute("invokeaction"), "");
- assert_equals(invoker.invokeAction, "auto");
- }, "invokeAction reflects 'auto' when attribute empty 2");
+ assert_equals(invoker.invokeAction, "");
+ }, "invokeAction reflects '' when attribute empty, IDL version");
test(function () {
invoker.invokeAction = [1, 2, 3];
@@ -83,8 +83,8 @@
test(function () {
invoker.invokeAction = [];
assert_equals(invoker.getAttribute("invokeaction"), "");
- assert_equals(invoker.invokeAction, "auto");
- }, "invokeAction reflects 'auto' when attribute set to []");
+ assert_equals(invoker.invokeAction, "");
+ }, "invokeAction reflects '' when attribute set to []");
test(function () {
invoker.invokeAction = {};
diff --git a/testing/web-platform/tests/html/semantics/invokers/invokeevent-interface.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invokeevent-interface.tentative.html
index 82910b3d44..382f808071 100644
--- a/testing/web-platform/tests/html/semantics/invokers/invokeevent-interface.tentative.html
+++ b/testing/web-platform/tests/html/semantics/invokers/invokeevent-interface.tentative.html
@@ -15,9 +15,9 @@
<script>
test(function () {
const event = new InvokeEvent("test");
- assert_equals(event.action, "auto");
+ assert_equals(event.action, "");
assert_readonly(event, "action", "readonly attribute value");
- }, "action is a readonly defaulting to 'auto'");
+ }, "action is a readonly defaulting to ''");
test(function () {
const event = new InvokeEvent("test");
@@ -32,7 +32,7 @@
test(function () {
const event = new InvokeEvent("test", { action: undefined });
- assert_equals(event.action, "auto");
+ assert_equals(event.action, "");
}, "action set to undefined");
test(function () {
diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html
index b19c1d3adc..d8d9c04022 100644
--- a/testing/web-platform/tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html
+++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html
@@ -22,7 +22,7 @@
assert_equals(event.bubbles, false, "bubbles");
assert_equals(event.composed, true, "composed");
assert_equals(event.isTrusted, true, "isTrusted");
- assert_equals(event.action, "auto", "action");
+ assert_equals(event.action, "", "action");
assert_equals(event.target, invokee, "target");
assert_equals(event.invoker, invokerbutton, "invoker");
}, "event dispatches on click");
@@ -107,6 +107,7 @@
"invoke",
(event) => {
eventInvoker = event.invoker;
+ eventTarget = event.target;
called = true;
},
{ once: true },
@@ -114,6 +115,7 @@
invokerbutton.invokeTargetElement = svgInvokee;
await clickOn(invokerbutton);
assert_true(called, "event was called");
- assert_true(eventInvoker == svgInvokee, "event invoker is set to right element");
- }, "event dispatches if invoker is non-HTML Element");
+ assert_equals(eventInvoker, invokerbutton, "event.invoker is set to right element");
+ assert_equals(eventTarget, svgInvokee, "event.target is set to right element");
+ }, "event dispatches if invokee is non-HTML Element");
</script>
diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-behavior.tentative.html
new file mode 100644
index 0000000000..774d308703
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-dialog-behavior.tentative.html
@@ -0,0 +1,455 @@
+<!doctype html>
+<meta charset="utf-8" />
+<meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" />
+<meta name="timeout" content="long">
+<link rel="help" href="https://open-ui.org/components/invokers.explainer/" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/invoker-utils.js"></script>
+
+<dialog id="invokee">
+ <button id="containedinvoker" invoketarget="invokee"></button>
+</dialog>
+<button id="invokerbutton" invoketarget="invokee"></button>
+
+<script>
+ function resetState() {
+ invokee.close();
+ try { invokee.hidePopover(); } catch {}
+ invokee.removeAttribute("popover");
+ invokerbutton.removeAttribute("invokeaction");
+ containedinvoker.removeAttribute("invokeaction");
+ }
+
+ // opening a dialog
+
+ [null, "", "showmodal", /* test case sensitivity */ "sHoWmOdAl"].forEach(
+ (action) => {
+ ["property", "attribute"].forEach((setType) => {
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ invokerbutton.invokeaction = action;
+ } else {
+ invokerbutton.setAttribute("invokeaction", action);
+ }
+ }
+ await clickOn(invokerbutton);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) closed dialog opens as modal`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener("invoke", (e) => e.preventDefault(), {
+ once: true,
+ });
+ if (typeof action === "string") {
+ if (setType === "property") {
+ invokerbutton.invokeaction = action;
+ } else {
+ invokerbutton.setAttribute("invokeaction", action);
+ }
+ }
+ await clickOn(invokerbutton);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) closed dialog with preventDefault is noop`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ invokerbutton.setAttribute("invokeaction", "close");
+ },
+ { once: true },
+ );
+ if (typeof action === "string") {
+ if (setType === "property") {
+ invokerbutton.invokeaction = action;
+ } else {
+ invokerbutton.setAttribute("invokeaction", action);
+ }
+ }
+ await clickOn(invokerbutton);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) while changing action still opens as modal`,
+ );
+ });
+ },
+ );
+
+ // closing an already open dialog
+
+ [null, "", "close", /* test case sensitivity */ "cLoSe"].forEach((action) => {
+ ["property", "attribute"].forEach((setType) => {
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.show();
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ containedinvoker.invokeaction = action;
+ } else {
+ containedinvoker.setAttribute("invokeaction", action);
+ }
+ }
+ await clickOn(containedinvoker);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking to close (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) open dialog closes`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.show();
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ containedinvoker.invokeaction = action;
+ } else {
+ containedinvoker.setAttribute("invokeaction", action);
+ }
+ }
+ invokee.addEventListener("invoke", (e) => e.preventDefault(), {
+ once: true,
+ });
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking to close (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) open dialog with preventDefault is no-op`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.showModal();
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ containedinvoker.invokeaction = action;
+ } else {
+ containedinvoker.setAttribute("invokeaction", action);
+ }
+ }
+ invokee.addEventListener("invoke", (e) => e.preventDefault(), {
+ once: true,
+ });
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking to close (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) open modal dialog with preventDefault is no-op`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.show();
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ containedinvoker.invokeaction = action;
+ } else {
+ containedinvoker.setAttribute("invokeaction", action);
+ }
+ }
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ containedinvoker.setAttribute("invokeaction", "show");
+ },
+ { once: true },
+ );
+ await clickOn(containedinvoker);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking to close (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) open dialog while changing action still closes`,
+ );
+
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.showModal();
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ if (typeof action === "string") {
+ if (setType === "property") {
+ containedinvoker.invokeaction = action;
+ } else {
+ containedinvoker.setAttribute("invokeaction", action);
+ }
+ }
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ containedinvoker.setAttribute("invokeaction", "show");
+ },
+ { once: true },
+ );
+ await clickOn(containedinvoker);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking to close (with invokeaction ${setType} as ${
+ action == null ? "auto" : action || "explicit empty"
+ }) open modal dialog while changing action still closes`,
+ );
+ });
+ });
+
+ // showmodal explicit behaviours
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ containedinvoker.setAttribute("invokeaction", "showModal");
+ invokee.show();
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ }, "invoking (as showmodal) open dialog is noop");
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ containedinvoker.setAttribute("invokeaction", "showmodal");
+ invokee.showModal();
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ containedinvoker.setAttribute("invokeaction", "close");
+ },
+ { once: true },
+ );
+ await clickOn(invokerbutton);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ }, "invoking (as showmodal) open modal, while changing action still a no-op");
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ invokerbutton.setAttribute("invokeaction", "showmodal");
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ invokee.setAttribute("popover", "auto");
+ await clickOn(invokerbutton);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ }, "invoking (as showmodal) closed popover dialog opens as modal");
+
+ // close explicit behaviours
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ invokerbutton.setAttribute("invokeaction", "close");
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(containedinvoker);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ }, "invoking (as close) already closed dialog is noop");
+
+ // invalid
+ [
+ "foo",
+ "foo-bar",
+ "auto",
+ "showpopover",
+ "hidepopover",
+ "togglepopover",
+ "showpicker",
+ ].forEach((action) => {
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ invokerbutton.setAttribute("invokeaction", action);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(invokerbutton);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ }, `invoking (as ${action}) on dialog does nothing`);
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ containedinvoker.setAttribute("invokeaction", action);
+ invokee.show();
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ }, `invoking (as ${action}) on open dialog does nothing`);
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ containedinvoker.setAttribute("invokeaction", action);
+ invokee.showModal();
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ }, `invoking (as ${action}) on open modal dialog does nothing`);
+
+ promise_test(async function (t) {
+ t.add_cleanup(resetState);
+ containedinvoker.setAttribute("invokeaction", action);
+ invokee.showModal();
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ containedinvoker.setAttribute("invokeaction", "");
+ },
+ { once: true },
+ );
+ await clickOn(containedinvoker);
+ assert_true(invokee.open, "invokee.open");
+ assert_true(invokee.matches(":modal"), "invokee :modal");
+ }, `invoking (as ${action}) on open modal while changing the attributer does nothing`);
+ });
+
+ // Open Popovers using Dialog actions
+ ["showmodal", "close", ""].forEach((action) => {
+ ["manual", "auto"].forEach((popoverState) => {
+ promise_test(
+ async function (t) {
+ t.add_cleanup(resetState);
+ invokee.setAttribute("popover", popoverState);
+ invokee.showPopover();
+ containedinvoker.setAttribute("invokeaction", action);
+ assert_true(
+ invokee.matches(":popover-open"),
+ "invokee :popover-open",
+ );
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener("invoke", (e) => e.preventDefault(), {
+ once: true,
+ });
+ await clickOn(containedinvoker);
+ assert_true(
+ invokee.matches(":popover-open"),
+ "invokee :popover-open",
+ );
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (as ${
+ action || "explicit empty"
+ }) dialog as open popover=${popoverState} is noop`,
+ );
+ });
+ });
+
+ // Elements being disconnected during invoke steps
+ ["showmodal", "close", ""].forEach((action) => {
+ promise_test(
+ async function (t) {
+ t.add_cleanup(() => {
+ document.body.prepend(invokee);
+ resetState();
+ });
+ const invokee = document.querySelector("#invokee");
+ invokerbutton.setAttribute("invokeaction", action);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ invokee.addEventListener(
+ "invoke",
+ (e) => {
+ invokee.remove();
+ },
+ {
+ once: true,
+ },
+ );
+ await clickOn(invokerbutton);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (as ${
+ action || "explicit empty"
+ }) dialog that is removed is noop`,
+ );
+
+ promise_test(
+ async function (t) {
+ const invokerbutton = document.createElement("button");
+ invokerbutton.invokeTargetElement = invokee;
+ invokerbutton.setAttribute("invokeaction", action);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(invokerbutton);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (as ${
+ action || "explicit empty"
+ }) dialog from a detached invoker`,
+ );
+
+ promise_test(
+ async function (t) {
+ const invokerbutton = document.createElement("button");
+ const invokee = document.createElement("dialog");
+ invokerbutton.invokeTargetElement = invokee;
+ invokerbutton.setAttribute("invokeaction", action);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ await clickOn(invokerbutton);
+ assert_false(invokee.open, "invokee.open");
+ assert_false(invokee.matches(":modal"), "invokee :modal");
+ },
+ `invoking (as ${
+ action || "explicit empty"
+ }) detached dialog from a detached invoker`,
+ );
+ });
+</script>
diff --git a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html
index 03eba22285..2bddfa7621 100644
--- a/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html
+++ b/testing/web-platform/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html
@@ -10,7 +10,7 @@
<script src="resources/invoker-utils.js"></script>
<div id="invokee" popover>
- <button id="invokerbutton2" invoketarget="invokee"></button>
+ <button id="containedinvoker" invoketarget="invokee"></button>
</div>
<button id="invokerbutton" invoketarget="invokee"></button>
@@ -44,7 +44,7 @@
promise_test(async function (t) {
invokee.showPopover();
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
assert_false(invokee.matches(":popover-open"));
}, "invoking (as auto) from within open popover closes");
@@ -55,7 +55,7 @@
once: true,
});
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
assert_true(invokee.matches(":popover-open"));
}, "invoking (as auto) open popover with preventDefault does not close");
@@ -93,8 +93,8 @@
promise_test(async function (t) {
invokee.showPopover();
- invokerbutton2.setAttribute("invokeaction", "togglepopover");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "togglepopover");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
assert_true(invokee.matches(":popover-open"));
await clickOn(invokerbutton);
assert_false(invokee.matches(":popover-open"));
@@ -102,23 +102,23 @@
promise_test(async function (t) {
invokee.showPopover();
- invokerbutton2.setAttribute("invokeaction", "togglepopover");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "togglepopover");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
assert_false(invokee.matches(":popover-open"));
}, "invoking (as togglepopover) from within open popover closes");
promise_test(async function (t) {
invokee.showPopover();
t.add_cleanup(() => invokee.hidePopover());
- invokerbutton2.setAttribute("invokeaction", "togglepopover");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "togglepopover");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
invokee.addEventListener("invoke", (e) => e.preventDefault(), {
once: true,
});
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
assert_true(invokee.matches(":popover-open"));
}, "invoking (as togglepopover) open popover with preventDefault does not close");
@@ -175,35 +175,59 @@
}, "invoking (as hidepopover) closed popover is noop");
promise_test(async function (t) {
- invokerbutton2.setAttribute("invokeaction", "hidepopover");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "hidepopover");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
invokee.showPopover();
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
t.add_cleanup(() => invokee.hidePopover());
assert_false(invokee.matches(":popover-open"));
}, "invoking (as hidepopover) open popover closes");
promise_test(async function (t) {
- invokerbutton2.setAttribute("invokeaction", "hIdEpOpOvEr");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "hIdEpOpOvEr");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
invokee.showPopover();
assert_true(invokee.matches(":popover-open"));
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
t.add_cleanup(() => invokee.hidePopover());
assert_false(invokee.matches(":popover-open"));
}, "invoking (as hidepopover - case insensitive) open popover closes");
promise_test(async function (t) {
- invokerbutton2.setAttribute("invokeaction", "hidepopover");
- t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction"));
+ containedinvoker.setAttribute("invokeaction", "hidepopover");
+ t.add_cleanup(() => containedinvoker.removeAttribute("invokeaction"));
invokee.showPopover();
t.add_cleanup(() => invokee.hidePopover());
assert_true(invokee.matches(":popover-open"));
invokee.addEventListener("invoke", (e) => e.preventDefault(), {
once: true,
});
- await clickOn(invokerbutton2);
+ await clickOn(containedinvoker);
assert_true(invokee.matches(":popover-open"));
}, "invoking (as hidepopover) open popover with preventDefault does not close");
+
+ // invalid
+
+ ["foo", "togglemodal", "showpicker", "toggle", "open", "close"].forEach(action => {
+ promise_test(async function (t) {
+ invokerbutton.setAttribute("invokeaction", action);
+ t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction"));
+ assert_false(invokee.matches(":popover-open"));
+ await clickOn(invokerbutton);
+ assert_false(invokee.matches(":popover-open"));
+ }, `invoking (as ${action}) on popover does nothing`);
+
+ promise_test(async function (t) {
+ invokerbutton.setAttribute("invokeaction", action);
+ t.add_cleanup(() => {
+ invokerbutton.removeAttribute("invokeaction")
+ invokee.hidePopover();
+ });
+ invokee.showPopover()
+ assert_true(invokee.matches(":popover-open"));
+ await clickOn(invokerbutton);
+ assert_true(invokee.matches(":popover-open"));
+ }, `invoking (as ${action}) on open popover does nothing`);
+ })
</script>
diff --git a/testing/web-platform/tests/html/semantics/invokers/resources/invoker-utils.js b/testing/web-platform/tests/html/semantics/invokers/resources/invoker-utils.js
index 317945502d..8420f24b6f 100644
--- a/testing/web-platform/tests/html/semantics/invokers/resources/invoker-utils.js
+++ b/testing/web-platform/tests/html/semantics/invokers/resources/invoker-utils.js
@@ -2,9 +2,13 @@ function waitForRender() {
return new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
}
async function clickOn(element) {
- const actions = new test_driver.Actions();
await waitForRender();
- await actions.pointerMove(0, 0, {origin: element})
+ let rect = element.getBoundingClientRect();
+ let actions = new test_driver.Actions();
+ // FIXME: Switch to pointerMove(0, 0, {origin: element}) once
+ // https://github.com/web-platform-tests/wpt/issues/41257 is fixed.
+ await actions
+ .pointerMove(Math.round(rect.x + rect.width / 2), Math.round(rect.y + rect.height / 2), {})
.pointerDown({button: actions.ButtonType.LEFT})
.pointerUp({button: actions.ButtonType.LEFT})
.send();
diff --git a/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.html b/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.html
new file mode 100644
index 0000000000..98c3d70e98
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/permission-element/bounded-css-properties.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<!--The permission element should have some limits for specific properties:
+ * font-weight is adjusted to be at least 200.
+ * font-style should only have "normal" or "italic" values.
+-->
+<style>
+ #id1 {
+ font-weight: 100;
+ font-style: oblique 30deg;
+ }
+ #id2 {
+ font-weight: 300;
+ font-style: italic;
+ }
+</style>
+
+
+<permission id="id1" type="geolocation">
+<permission id="id2" type="camera">
+
+<script>
+ test(function(){
+ var el_outside_bounds = document.getElementById("id1");
+ assert_equals(getComputedStyle(el_outside_bounds).fontWeight, "200", "font-weight");
+ assert_equals(getComputedStyle(el_outside_bounds).fontStyle, "normal", "font-style");
+ }, "Properties with out-of-bounds values should be corrected");
+
+ test(function(){
+ var el_inside_bounds = document.getElementById("id2");
+ assert_equals(getComputedStyle(el_inside_bounds).fontWeight, "300", "font-weight");
+ assert_equals(getComputedStyle(el_inside_bounds).fontStyle, "italic", "font-style");
+ }, "Properties with values in bounds should not be modified");
+</script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/permission-element/invalid-css-properties.html b/testing/web-platform/tests/html/semantics/permission-element/invalid-css-properties.html
new file mode 100644
index 0000000000..c7186563f0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/permission-element/invalid-css-properties.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<!--The permission element does not allow certain CSS properties
+-->
+<style>
+ #id1 {
+ border-image: url('test-url');
+ background-image: url('test-url');
+ clip-path: circle(10px);
+ filter: blur(10px);
+ mask: url('test-url');
+ padding-left: 10px;
+ transform: rotate(10);
+ }
+</style>
+
+<permission id="id1" type="geolocation">
+
+<script>
+ test(function(){
+ var el_with_negatives = document.getElementById("id1");
+ assert_equals(getComputedStyle(el_with_negatives).borderImage, "none", "border-image");
+ assert_equals(getComputedStyle(el_with_negatives).backgroundImage, "none", "background-image");
+ assert_equals(getComputedStyle(el_with_negatives).clipPath, "none", "clip-path");
+ assert_equals(getComputedStyle(el_with_negatives).filter, "none", "filter");
+ assert_equals(getComputedStyle(el_with_negatives).mask, "none", "mask");
+ assert_equals(getComputedStyle(el_with_negatives).paddingLeft, "0px", "padding-left");
+ assert_equals(getComputedStyle(el_with_negatives).transform, "none", "transform");
+ }, "None of the listed properties should be applied");
+</script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/permission-element/negative-offset-and-margin.html b/testing/web-platform/tests/html/semantics/permission-element/negative-offset-and-margin.html
new file mode 100644
index 0000000000..97290bb4df
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/permission-element/negative-offset-and-margin.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<!--The permission element should not allow setting negative margins or outline-offset
+-->
+<style>
+ #id1 {
+ outline-offset: -50px;
+ margin-top: -50px;
+ margin-left: -50px;
+ margin-bottom: -50px;
+ margin-right: -50px;
+ }
+ #id2 {
+ outline-offset: 50px;
+ margin-top: 50px;
+ margin-left: 50px;
+ margin-bottom: 50px;
+ margin-right: 50px;
+ }
+
+ /* These various expressions all result in a negative value when calculated */
+ #id3 {
+ outline-offset: min(-50px, 50px);
+ margin-top: min(10%, -50px);
+ margin-left: clamp(-100px, 1vw, -50px);
+ margin-bottom: 1% - 10000px;
+ margin-right: max(min(-1em, 10em), -5%);
+ }
+</style>
+
+
+<permission id="id1" type="geolocation">
+<permission id="id2" type="camera">
+<permission id="id3" type="microphone">
+
+<script>
+ test(function(){
+ var el_with_negatives = document.getElementById("id1");
+ assert_equals(getComputedStyle(el_with_negatives).outlineOffset, "0px", "outline-offset");
+ assert_equals(getComputedStyle(el_with_negatives).marginLeft, "0px", "margin-left");
+ assert_equals(getComputedStyle(el_with_negatives).marginRight, "0px", "margin-right");
+ assert_equals(getComputedStyle(el_with_negatives).marginTop, "0px", "margin-top");
+ assert_equals(getComputedStyle(el_with_negatives).marginBottom, "0px", "margin-bottom");
+ }, "Negative margins/offset should be changed to 0px");
+
+ test(function(){
+ var el_with_positives = document.getElementById("id2");
+ assert_equals(getComputedStyle(el_with_positives).outlineOffset, "50px", "outline-offset");
+ assert_equals(getComputedStyle(el_with_positives).marginLeft, "50px", "margin-left");
+ assert_equals(getComputedStyle(el_with_positives).marginRight, "50px", "margin-right");
+ assert_equals(getComputedStyle(el_with_positives).marginTop, "50px", "margin-top");
+ assert_equals(getComputedStyle(el_with_positives).marginBottom, "50px", "margin-bottom");
+ }, "Positive margins/offset are unaffected");
+
+ test(function(){
+ var el_with_negative_expr = document.getElementById("id3");
+ assert_equals(getComputedStyle(el_with_negative_expr).outlineOffset, "0px", "outline-offset");
+ assert_equals(getComputedStyle(el_with_negative_expr).marginLeft, "0px", "margin-left");
+ assert_equals(getComputedStyle(el_with_negative_expr).marginRight, "0px", "margin-right");
+ assert_equals(getComputedStyle(el_with_negative_expr).marginTop, "0px", "margin-top");
+ assert_equals(getComputedStyle(el_with_negative_expr).marginBottom, "0px", "margin-bottom");
+ }, "Expressions margins/offset should always return at least 0px");
+</script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html b/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html
new file mode 100644
index 0000000000..7c87d2d039
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="author" href="mailto:masonf@chromium.org">
+<link rel=help href="https://open-ui.org/components/popover.research.explainer">
+<link rel=help href="https://html.spec.whatwg.org/multipage/popover.html">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/popover-utils.js"></script>
+
+<!-- Once anchor positioning lands in the spec, the tests in this file can
+ be re-inserted into popover-shadow-dom.html. -->
+
+<script>
+ function findPopovers(root) {
+ let popovers = [];
+ if (!root)
+ return popovers;
+ if (root instanceof Element && root.matches('[popover]'))
+ popovers.push(root);
+ popovers.push(...findPopovers(root.shadowRoot));
+ root.childNodes.forEach(child => {
+ popovers.push(...findPopovers(child));
+ })
+ return popovers;
+ }
+ function getPopoverReferences(testId) {
+ const testRoot = document.querySelector(`#${testId}`);
+ assert_true(!!testRoot);
+ return findPopovers(testRoot);
+ }
+</script>
+
+<div id=test1>
+ <button id=t2b1>Test 1 Popover 1</button>
+ <div popover anchor=t2b1 style="top: 200px;">
+ <p>Popover 1</p>
+ <button id=t2b2>Test 1 Popover 2</button>
+ </div>
+ <my-element>
+ <template shadowrootmode=open>
+ <div popover anchor=t2b2 style="top: 400px;">
+ <p>Hiding this popover will hide *all* open popovers,</p>
+ <p>because t2b2 doesn't exist in this context.</p>
+ </div>
+ </template>
+ </my-element>
+</div>
+
+<script>
+ test(function() {
+ const [popover1,popover2] = getPopoverReferences('test1');
+ popover1.showPopover();
+ assert_true(popover1.matches(':popover-open'));
+ assert_true(isElementVisible(popover1));
+ popover2.showPopover();
+ assert_false(popover1.matches(':popover-open'), 'popover1 open'); // P1 was closed by P2
+ assert_false(isElementVisible(popover1), 'popover1 visible');
+ assert_true(popover2.matches(':popover-open'), 'popover2 open'); // P2 is open
+ assert_true(isElementVisible(popover2), 'popover2 visible');
+ popover2.hidePopover(); // Cleanup
+ }, "anchor references do not cross shadow boundaries");
+</script>
+
+
+<div id=test2>
+ <my-element>
+ <template shadowrootmode=open>
+ <button id=t3b1>Test 2 Popover 1</button>
+ <div popover anchor=t3b1>
+ <p>This popover will stay open when popover2 shows.</p>
+ <slot></slot>
+ </div>
+ </template>
+ <button id=t3b2>Test 2 Popover 2</button>
+ </my-element>
+ <div popover anchor=t3b2>Popover 2</div>
+</div>
+
+<script>
+ promise_test(async function() {
+ const [popover1,popover2] = getPopoverReferences('test2');
+ popover1.showPopover();
+ assert_true(popover1.matches(':popover-open'));
+ assert_true(isElementVisible(popover1));
+ // Showing popover2 should not close popover1, since it is a flat
+ // tree ancestor of popover2's anchor button.
+ popover2.showPopover();
+ assert_true(popover2.matches(':popover-open'));
+ assert_true(isElementVisible(popover2));
+ assert_true(popover1.matches(':popover-open'));
+ assert_true(isElementVisible(popover1));
+ popover1.hidePopover();
+ await waitForRender();
+ assert_false(popover1.matches(':popover-open'));
+ assert_false(isElementVisible(popover1));
+ assert_false(popover2.matches(':popover-open'));
+ assert_false(isElementVisible(popover2));
+ }, "anchor references use the flat tree not the DOM tree");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html b/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html
index 62aa135b56..18ac500270 100644
--- a/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html
+++ b/testing/web-platform/tests/html/semantics/popovers/popover-shadow-dom.html
@@ -8,17 +8,6 @@
<script src="resources/popover-utils.js"></script>
<script>
- function ensureShadowDom(host) {
- host.querySelectorAll('my-element').forEach(host => {
- if (host.shadowRoot)
- return; // Declarative Shadow DOM is enabled
- const template = host.firstElementChild;
- assert_true(template instanceof HTMLTemplateElement);
- const shadow = host.attachShadow({mode: 'open'});
- shadow.appendChild(template.content);
- template.remove();
- })
- }
function findPopovers(root) {
let popovers = [];
if (!root)
@@ -34,16 +23,12 @@
function getPopoverReferences(testId) {
const testRoot = document.querySelector(`#${testId}`);
assert_true(!!testRoot);
- ensureShadowDom(testRoot);
return findPopovers(testRoot);
}
- function showTestPopover(testId,popoverNum) {
- getPopoverReferences(testId)[popoverNum].showPopover();
- }
</script>
<div id=test1>
- <button onclick='showTestPopover("test1",0)'>Test1 Popover</button>
+ <button>Test1 Popover</button>
<my-element>
<template shadowrootmode=open>
<div popover>
@@ -64,83 +49,14 @@
</script>
-<div id=test2>
- <button id=t2b1 onclick='showTestPopover("test2",0)'>Test 2 Popover 1</button>
- <div popover anchor=t2b1 style="top: 200px;">
- <p>Popover 1</p>
- <button id=t2b2 onclick='showTestPopover("test2",1)'>Test 2 Popover 2</button>
- </div>
- <my-element>
- <template shadowrootmode=open>
- <div popover anchor=t2b2 style="top: 400px;">
- <p>Hiding this popover will hide *all* open popovers,</p>
- <p>because t2b2 doesn't exist in this context.</p>
- </div>
- </template>
- </my-element>
-</div>
-
-<script>
- test(function() {
- const [popover1,popover2] = getPopoverReferences('test2');
- popover1.showPopover();
- assert_true(popover1.matches(':popover-open'));
- assert_true(isElementVisible(popover1));
- popover2.showPopover();
- assert_false(popover1.matches(':popover-open'), 'popover1 open'); // P1 was closed by P2
- assert_false(isElementVisible(popover1), 'popover1 visible');
- assert_true(popover2.matches(':popover-open'), 'popover2 open'); // P2 is open
- assert_true(isElementVisible(popover2), 'popover2 visible');
- popover2.hidePopover(); // Cleanup
- }, "anchor references do not cross shadow boundaries");
-</script>
-
-
-<div id=test3>
- <my-element>
- <template shadowrootmode=open>
- <button id=t3b1 onclick='showTestPopover("test3",0)'>Test 3 Popover 1</button>
- <div popover anchor=t3b1>
- <p>This popover will stay open when popover2 shows.</p>
- <slot></slot>
- </div>
- </template>
- <button id=t3b2 onclick='showTestPopover("test3",1)'>Test 3 Popover 2</button>
- </my-element>
- <div popover anchor=t3b2>Popover 2</div>
-</div>
-
-<script>
- promise_test(async function() {
- const [popover1,popover2] = getPopoverReferences('test3');
- popover1.showPopover();
- assert_true(popover1.matches(':popover-open'));
- assert_true(isElementVisible(popover1));
- // Showing popover2 should not close popover1, since it is a flat
- // tree ancestor of popover2's anchor button.
- popover2.showPopover();
- assert_true(popover2.matches(':popover-open'));
- assert_true(isElementVisible(popover2));
- assert_true(popover1.matches(':popover-open'));
- assert_true(isElementVisible(popover1));
- popover1.hidePopover();
- await waitForRender();
- assert_false(popover1.matches(':popover-open'));
- assert_false(isElementVisible(popover1));
- assert_false(popover2.matches(':popover-open'));
- assert_false(isElementVisible(popover2));
- }, "anchor references use the flat tree not the DOM tree");
-</script>
-
-
<div id=test4>
- <button id=t4b1 onclick='showTestPopover("test4",0)'>Test 4 Popover 1</button>
- <div popover anchor=t4b1>
+ <button>Test 4 Popover 1</button>
+ <div popover>
<p>This should not get hidden when popover2 opens.</p>
<my-element>
<template shadowrootmode=open>
- <button id=t4b2 onclick='showTestPopover("test4",1)'>Test 4 Popover 2</button>
- <div popover anchor=t4b2>
+ <button id=t4b2>Test 4 Popover 2</button>
+ <div popover>
<p>This should not hide popover1.</p>
</div>
</template>
diff --git a/testing/web-platform/tests/html/semantics/popovers/popovertarget-reflection.html b/testing/web-platform/tests/html/semantics/popovers/popovertarget-reflection.html
index d0750fdd4c..b4f99631ab 100644
--- a/testing/web-platform/tests/html/semantics/popovers/popovertarget-reflection.html
+++ b/testing/web-platform/tests/html/semantics/popovers/popovertarget-reflection.html
@@ -11,7 +11,7 @@
<script>
test(() => {
- assert_equals(mybutton.popoverTargetElement.id, "mypopover",
+ assert_equals(mybutton.popoverTargetElement.id, "mypopover",
'Setting element.popoverTargetElement to a valid element should work');
mybutton.popoverTargetElement = null;
@@ -33,13 +33,13 @@ test(() => {
'Assigning to element.popoverTargetElement should set the popovertarget attribute.');
mybutton.setAttribute("popovertarget", 'invalid');
- assert_equals(mybutton.popoverTargetElement, null,
+ assert_equals(mybutton.popoverTargetElement, null,
'Setting the popovertarget attribute to a localName that is not attr should remove the existing element from element.popoverTargetElement.');
mybutton.popoverTargetElement = mypopover;
mybutton.setAttribute("popovertarget", "");
- assert_equals(mybutton.popoverTargetElement.id, "mypopover",
- 'Setting the popovertarget attribute to empty string right after explicitly setting attribute element should have no effect.');
+ assert_equals(mybutton.popoverTargetElement, null,
+ 'Setting the popovertarget attribute to empty string right after setting explicit element does remove the explicit element.');
mybutton.setAttribute("popovertarget", "mypopover");
assert_equals(mybutton.popoverTargetElement.id, "mypopover",
diff --git a/testing/web-platform/tests/html/semantics/popovers/resources/popover-utils.js b/testing/web-platform/tests/html/semantics/popovers/resources/popover-utils.js
index bfc1f89ec1..96ac7e03f0 100644
--- a/testing/web-platform/tests/html/semantics/popovers/resources/popover-utils.js
+++ b/testing/web-platform/tests/html/semantics/popovers/resources/popover-utils.js
@@ -7,9 +7,13 @@ function waitForTick() {
}
async function clickOn(element) {
- const actions = new test_driver.Actions();
await waitForRender();
- await actions.pointerMove(0, 0, {origin: element})
+ let rect = element.getBoundingClientRect();
+ let actions = new test_driver.Actions();
+ // FIXME: Switch to pointerMove(0, 0, {origin: element}) once
+ // https://github.com/web-platform-tests/wpt/issues/41257 is fixed.
+ await actions
+ .pointerMove(Math.round(rect.x + rect.width / 2), Math.round(rect.y + rect.height / 2), {})
.pointerDown({button: actions.ButtonType.LEFT})
.pointerUp({button: actions.ButtonType.LEFT})
.send();
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html
index 50933da2c1..3645279d61 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Parse errors in different files should be reported " +
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html
index 51adb09d11..d40aaba8df 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Instantiation errors in different files should be reported " +
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html
index bc52119bfe..2d74af864b 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Evaluation errors are cached in intermediate module scripts");
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html
index 2480a60d6d..0484b614ab 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"network error has higher priority than parse error");
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html
index 673bf28ca2..7303a838a5 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"parse error has higher priority than instantiation error");
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html
index 8a16266f4c..f80f74cbe4 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"instantiation error has higher priority than evaluation error");
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html
index 3f2bb35f4e..b12d178fb5 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Test that exceptions during evaluation lead to error events on " +
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html
index 4f2b3c5a74..a890ca6457 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Test that ill-founded cyclic dependencies cause ReferenceError " +
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html
index 9bfb5df2cf..4062bc8a3a 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Test that exceptions during evaluation lead to error events on " +
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html
index 0b4b7d1662..256aea508e 100644
--- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html
+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html
@@ -9,7 +9,7 @@
window.log = [];
window.addEventListener("error", ev => log.push(ev.error));
- window.addEventListener("onunhandledrejection", unreachable);
+ window.addEventListener("unhandledrejection", unreachable);
const test_load = async_test(
"Test that exceptions during evaluation lead to error events on " +
diff --git a/testing/web-platform/tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html b/testing/web-platform/tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html
index 3a9d90c76b..e658500a4e 100644
--- a/testing/web-platform/tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html
+++ b/testing/web-platform/tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html
@@ -30,13 +30,13 @@
&#x202D; - The LRO (left-to-right override) formatting character.
&#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
In each DIV of the test:
- - the first BDI, having no characters with strong direction, should inherit the parent direction;
+ - the first BDI, having no characters with strong direction, should be LTR by default;
- the second BDI, having an LTR character first, should be LTR by default;
- the third BDI, having an RTL character first, should be RTL by default.
</div>
<div class="test">
<div dir="ltr"><bdi>[:)]</bdi>, <bdi>[+- a &#x05D1;]</bdi>, <bdi>[1 &#x05D2; d]</bdi>...</div>
- <div dir="rtl"><bdi>[(:]</bdi>, <bdi>[+- a &#x05D1;]</bdi>, <bdi>[1 &#x05D2; d]</bdi>...</div>
+ <div dir="rtl"><bdi>[:)]</bdi>, <bdi>[+- a &#x05D1;]</bdi>, <bdi>[1 &#x05D2; d]</bdi>...</div>
</div>
<div class="ref">
<div dir="ltr">&#x202D;[:)], [+- a &#x05D1;], [d &#x05D2; 1]...&#x202C;</div>
diff --git a/testing/web-platform/tests/html/syntax/speculative-parsing/tools/generate.py b/testing/web-platform/tests/html/syntax/speculative-parsing/tools/generate.py
index 3457f94d70..f0db885814 100755
--- a/testing/web-platform/tests/html/syntax/speculative-parsing/tools/generate.py
+++ b/testing/web-platform/tests/html/syntax/speculative-parsing/tools/generate.py
@@ -680,7 +680,7 @@ def generate_tests(testcase, tentative):
html_testcase_markup = template_testcase_markup.format(url_wptserve_sub)
html_nonspeculative_testcase_markup = template_nonspeculative_testcase_markup.format(url_wptserve_sub)
- js_testcase_markup = template_testcase_markup.format(url_js_sub).replace(u"</script>", u"<\/script>").replace(u"<meta charset", u"<meta\ charset")
+ js_testcase_markup = template_testcase_markup.format(url_js_sub).replace(u"</script>", u"<\\/script>").replace(u"<meta charset", u"<meta\\ charset")
if test_nonspeculative == u'true':
nonspeculative = template_nonspeculative.format(preamble=preamble, encoding_decl=encoding_decl, title=title, nonspeculative_testcase_markup=html_nonspeculative_testcase_markup, delay=delay)
diff --git a/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.https.html b/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.https.html
index 10b3dd2249..3fbe3eaa62 100644
--- a/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.https.html
+++ b/testing/web-platform/tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.https.html
@@ -20,14 +20,14 @@
assert_equals(typeof uaData.mobile, "boolean", "mobile should be a boolean");
const highEntropyData = await uaData.getHighEntropyValues([
- "platformVersion", "architecture", "model", "uaFullVersion", "fullVersionList", "formFactor"]);
+ "platformVersion", "architecture", "model", "uaFullVersion", "fullVersionList", "formFactors"]);
assert_equals(typeof highEntropyData["platform"], "string", "Platform brand should be a string");
assert_equals(typeof highEntropyData["platformVersion"], "string", "Platform version should be a string");
assert_equals(typeof highEntropyData["architecture"], "string", "Architecture should be a string");
assert_equals(typeof highEntropyData["model"], "string", "Model should be a string");
assert_equals(typeof highEntropyData["uaFullVersion"], "string", "UAFullVersion should be a string");
- for (formFactor of highEntropyData['formFactor']) {
- assert_equals(typeof formFactor, "string", "Each FormFactor should be a string");
+ for (formFactor of highEntropyData['formFactors']) {
+ assert_equals(typeof formFactor, "string", "Each FormFactors value should be a string");
}
for (brandVersionPair of highEntropyData['fullVersionList']) {
assert_equals(typeof brandVersionPair.brand, "string", "brand should be a string");
@@ -40,7 +40,7 @@
assert_false("architecture" in highEntropyData2, "Architecture should be an empty string");
assert_false("model" in highEntropyData2, "Model should be an empty string");
assert_false("uaFullVersion" in highEntropyData2, "UAFullVersion should be an empty string");
- assert_false("formFactor" in highEntropyData2, "FormFactor should be an empty string");
+ assert_false("formFactors" in highEntropyData2, "FormFactors should be an empty array");
assert_false("fullVersionList" in highEntropyData2, "fullVersionList should not be present");
let finalPromise = uaData.getHighEntropyValues([]).then(() => {
assert_true(didMicrotaskRun, "getHighEntropyValues queued on a task");