Test outside of IDL conversions for CanvasFilter

From the discussion here (https://github.com/whatwg/html/pull/6763) we
need to explicitly test all possible types of inputs for filter
attributes.

Bug: 1201359
Change-Id: I5ef5905298a17310e4eb54c3c01ab8d6b7973737
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3320960
Reviewed-by: Yi Xu <yiyix@chromium.org>
Reviewed-by: Domenic Denicola <domenic@chromium.org>
Commit-Queue: Aaron Krajeski <aaronhk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#951163}
diff --git a/html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.html b/html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.html
index 22dac93..e0c9393 100644
--- a/html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.html
+++ b/html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.html
@@ -20,8 +20,11 @@
 _addTest(function(canvas, ctx) {
 
 assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur"}); });
-assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDevation: null}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: undefined}); });
 assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: "foo"}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: [1,2]}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: NaN}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: {}}); });
 
 
 });
diff --git a/html/canvas/element/manual/filters/idl-conversions/canvas-filter-boolean-conversion-expected.html b/html/canvas/element/manual/filters/idl-conversions/canvas-filter-boolean-conversion-expected.html
new file mode 100644
index 0000000..f79cdd1
--- /dev/null
+++ b/html/canvas/element/manual/filters/idl-conversions/canvas-filter-boolean-conversion-expected.html
@@ -0,0 +1,30 @@
+<body>
+  <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+  var ctx = document.getElementById('canvas').getContext('2d');
+
+  // preserveAlpha for convolveMatrix is the only boolean so far implemented
+  function drawWithConvolveFilter(x, y, preserveAlphaValue) {
+    ctx.filter = new CanvasFilter({
+      filter: "convolveMatrix",
+      kernelMatrix: [[1, 0], [0, 1]],
+      preserveAlpha: preserveAlphaValue,
+    });
+    ctx.fillRect(x, y, 30, 30);
+  }
+
+  ctx.fillStyle = "rgba(255,0,255,0.5)";
+  let x = 10;
+  let y = 10;
+  for (var i = 0; i < 6; i++) {
+    drawWithConvolveFilter(x, y, true);
+    x += 40;
+  }
+  y = 50;
+  x = 10;
+  for (var i = 0; i < 5; i++) {
+    drawWithConvolveFilter(x, y, false);
+    x += 40;
+  }
+</script>
diff --git a/html/canvas/element/manual/filters/idl-conversions/canvas-filter-boolean-conversion.html b/html/canvas/element/manual/filters/idl-conversions/canvas-filter-boolean-conversion.html
new file mode 100644
index 0000000..16c40e4
--- /dev/null
+++ b/html/canvas/element/manual/filters/idl-conversions/canvas-filter-boolean-conversion.html
@@ -0,0 +1,58 @@
+<head>
+    <link rel="match" href="canvas-filter-boolean-conversion-expected.html">
+</head>
+<body>
+  <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+  // Test the built-in ECMAScript types Undefined, Null, Boolean, String, Number, and Object
+  // as input to the CanvasFilter resolver when a bool is the intended result.
+  var ctx = document.getElementById('canvas').getContext('2d');
+
+  // preserveAlpha for convolveMatrix is the only boolean so far implemented
+  function drawWithConvolveFilter(x, y, preserveAlphaValue) {
+    ctx.filter = new CanvasFilter({
+      filter: "convolveMatrix",
+      kernelMatrix: [[1, 0], [0, 1]],
+      preserveAlpha: preserveAlphaValue,
+    });
+    ctx.fillRect(x, y, 30, 30);
+  }
+
+  const trueTestCases = [
+    true,
+    { valueOf() { return false; }},
+    "foo",
+    1,
+    {},
+    []
+  ];
+
+  const falseTestCases = [
+    false,
+    "",
+    0,
+    null,
+    undefined,
+  ];
+
+  ctx.fillStyle = "rgba(255,0,255,0.5)";
+  let x = 10;
+  let y = 10;
+  for (tc of trueTestCases) {
+    drawWithConvolveFilter(x, y, tc);
+    x += 40;
+  }
+  y = 50;
+  x = 10;
+  for (tc of falseTestCases) {
+    drawWithConvolveFilter(x, y, tc);
+    x += 40;
+  }
+
+  ctx.filter = new CanvasFilter({
+    filter: "componentTransfer",
+    funcR: {type: "discrete", tableValues: 0.5},
+  });
+  ctx.fillRect(10, 10, 100, 100);
+</script>
diff --git a/html/canvas/element/manual/filters/idl-conversions/canvas-filter-long-conversion-expected.html b/html/canvas/element/manual/filters/idl-conversions/canvas-filter-long-conversion-expected.html
new file mode 100644
index 0000000..8b4262e
--- /dev/null
+++ b/html/canvas/element/manual/filters/idl-conversions/canvas-filter-long-conversion-expected.html
@@ -0,0 +1,26 @@
+<body>
+  <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+  var ctx = document.getElementById('canvas').getContext('2d');
+  // Null and False both evaluate to zero
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 0});
+  ctx.fillRect(10, 10, 30, 30);
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 0});
+  ctx.fillRect(50, 10, 30, 30);
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 0});
+  ctx.fillRect(90, 10, 30, 30);
+  // True evaluates to one
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 1});
+  ctx.fillRect(130, 10, 30, 30);
+  // String, Number and Object should all work
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5});
+  ctx.fillRect(10, 50, 30, 30);
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5});
+  ctx.fillRect(50, 50, 30, 30);
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5});
+  ctx.fillRect(90, 50, 30, 30);
+  // Valid sequence
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5});
+  ctx.fillRect(130, 50, 30, 30);
+</script>
diff --git a/html/canvas/element/manual/filters/idl-conversions/canvas-filter-long-conversion.html b/html/canvas/element/manual/filters/idl-conversions/canvas-filter-long-conversion.html
new file mode 100644
index 0000000..c742633
--- /dev/null
+++ b/html/canvas/element/manual/filters/idl-conversions/canvas-filter-long-conversion.html
@@ -0,0 +1,35 @@
+<head>
+    <link rel="match" href="canvas-filter-long-conversion-expected.html">
+</head>
+<body>
+  <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+  // Test the built-in ECMAScript types Undefined, Null, Boolean, String, Number, and Object
+  // as input to the CanvasFilter resolver when a long is the intended result.
+  var ctx = document.getElementById('canvas').getContext('2d');
+
+  // Null, False and [] evaluate to zero
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: null});
+  ctx.fillRect(10, 10, 30, 30);
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: false});
+  ctx.fillRect(50, 10, 30, 30);
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: []});
+  ctx.fillRect(90, 10, 30, 30);
+  // True evaluates to one
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: true});
+  ctx.fillRect(130, 10, 30, 30);
+  // String, Number and Object should all work
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: "5"});
+  ctx.fillRect(10, 50, 30, 30);
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5});
+  ctx.fillRect(50, 50, 30, 30);
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: { valueOf() { return 5; }}});
+  ctx.fillRect(90, 50, 30, 30);
+  // Valid sequence
+  ctx.filter  = new CanvasFilter({filter: "gaussianBlur", stdDeviation: [5]});
+  ctx.fillRect(130, 50, 30, 30);
+
+  // Undefined and other inputs that throw exceptions are tested in:
+  // html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.html
+</script>
diff --git a/html/canvas/element/manual/filters/idl-conversions/canvas-filter-sequence-conversion.html b/html/canvas/element/manual/filters/idl-conversions/canvas-filter-sequence-conversion.html
new file mode 100644
index 0000000..7774f3a
--- /dev/null
+++ b/html/canvas/element/manual/filters/idl-conversions/canvas-filter-sequence-conversion.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>Canvas test: canvas-filter-sequence-conversion</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>canvas-filter-sequence-conversion</h1>
+<p class="desc">Test converting types into sequences</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 pixels on CanvasFilter() various inputs to tableValues (which is a sequence)");
+_addTest(function(canvas, ctx) {
+
+  // Inputs to parameters that are expecting sequence<long>. Results are either the value of the
+  // red pixel drawing using the resultant filter or that we expect this input to throw an error.
+  const testCases = [
+    {input: [], result: 0},
+    {input: [0.5], result: 127},
+    {input: ["0.5"], result: 127},
+    {input: 1, result: "throws"},
+    {input: {}, result: "throws"},
+    {input: false, result: "throws"},
+    {input: true, result: "throws"},
+    {input: NaN, result: "throws"},
+    {input: { valueOf() { return [1]; }}, result: "throws"},
+  ];
+
+  // A simple filter that just overrides the red channel if successful.
+  function makeFilter(value) {
+    return new CanvasFilter({
+      filter: "componentTransfer",
+      funcR: {type: "table", tableValues: value}
+    });
+  }
+
+  for (const tc of testCases) {
+    if (tc.result === "throws") {
+      assert_throws_js(TypeError, function(){ makeFilter(tc.input) });
+    } else {
+      ctx.reset();
+      ctx.filter = makeFilter(tc.input);
+      ctx.fillRect(0, 0, 100, 100);
+      _assertPixelApprox(canvas, 5, 5, tc.result,0,0,255, "5,5", `${tc.result},0,0,255`, 2);
+    }
+  }
+  t.done();
+});
+</script>
diff --git a/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.html b/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.html
index c047903..d3a03dc 100644
--- a/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.html
+++ b/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.html
@@ -21,8 +21,11 @@
 var ctx = offscreenCanvas.getContext('2d');
 
 assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur"}); });
-assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDevation: null}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: undefined}); });
 assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: "foo"}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: [1,2]}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: NaN}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: {}}); });
 t.done();
 
 });
diff --git a/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.worker.js b/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.worker.js
index 1f44c00..29f743d 100644
--- a/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.worker.js
+++ b/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.blur.exceptions.worker.js
@@ -17,8 +17,11 @@
 var ctx = offscreenCanvas.getContext('2d');
 
 assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur"}); });
-assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDevation: null}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: undefined}); });
 assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: "foo"}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: [1,2]}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: NaN}); });
+assert_throws_js(TypeError, function() { ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: {}}); });
 t.done();
 
 });
diff --git a/html/canvas/tools/yaml/element/filters.yaml b/html/canvas/tools/yaml/element/filters.yaml
index 420af37..57cbebc 100644
--- a/html/canvas/tools/yaml/element/filters.yaml
+++ b/html/canvas/tools/yaml/element/filters.yaml
@@ -61,8 +61,11 @@
   desc: Test exceptions on CanvasFilter() blur.object
   code: |
     @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur"});
-    @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDevation: null});
+    @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: undefined});
     @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: "foo"});
+    @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: [1,2]});
+    @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: NaN});
+    @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: {}});
 
 - name: 2d.filter.canvasFilterObject.colorMatrix
   desc: Test the functionality of ColorMatrix filters in CanvasFilter objects
diff --git a/html/canvas/tools/yaml/offscreen/filters.yaml b/html/canvas/tools/yaml/offscreen/filters.yaml
index e715c95..f9cf1cb 100644
--- a/html/canvas/tools/yaml/offscreen/filters.yaml
+++ b/html/canvas/tools/yaml/offscreen/filters.yaml
@@ -28,8 +28,11 @@
   desc: Test exceptions on CanvasFilter() blur.object
   code: |
     @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur"});
-    @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDevation: null});
+    @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: undefined});
     @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: "foo"});
+    @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: [1,2]});
+    @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: NaN});
+    @assert throws TypeError ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: {}});
     t.done();
 
 - name: 2d.filter.canvasFilterObject.colorMatrix