Bug 1303099. LenientFloat handling should not prevent all arguments being processed; instead it should just cause an early return right after argument processing. r=qdot
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 15 Sep 2016 17:10:59 -0400
changeset 355458 f60f494e7d57bad0cffcce5472aee6af789497b5
parent 355457 a4ef0b5b78cbbea3212cfcf0eae948b433e88a48
child 355459 f8f7ef1f3e2703b96e88671a36ce62105dd7337c
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs1303099
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1303099. LenientFloat handling should not prevent all arguments being processed; instead it should just cause an early return right after argument processing. r=qdot
dom/bindings/Codegen.py
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/2dcontext/path-objects/2d.path.lineTo.nonfinite.details.html
testing/web-platform/tests/2dcontext/tools/tests2d.yaml
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -7176,22 +7176,23 @@ class CGPerSignatureCall(CGThing):
                       (idlNode.isStatic() and descriptor.interface.getExtendedAttribute("Deprecated")))
         if deprecated:
             cgThings.append(CGGeneric(dedent(
                 """
                 DeprecationWarning(cx, obj, nsIDocument::e%s);
                 """ % deprecated[0])))
 
         lenientFloatCode = None
-        if idlNode.getExtendedAttribute('LenientFloat') is not None:
-            if setter:
-                lenientFloatCode = "return true;\n"
-            elif idlNode.isMethod():
-                lenientFloatCode = ("args.rval().setUndefined();\n"
-                                    "return true;\n")
+        if (idlNode.getExtendedAttribute('LenientFloat') is not None and
+            (setter or idlNode.isMethod())):
+            cgThings.append(CGGeneric(dedent(
+                """
+                bool foundNonFiniteFloat = false;
+                """)))
+            lenientFloatCode = "foundNonFiniteFloat = true;\n"
 
         argsPre = []
         if idlNode.isStatic():
             # If we're a constructor, "obj" may not be a function, so calling
             # XrayAwareCalleeGlobal() on it is not safe.  Of course in the
             # constructor case either "obj" is an Xray or we're already in the
             # content compartment, not the Xray compartment, so just
             # constructing the GlobalObject from "obj" is fine.
@@ -7325,16 +7326,35 @@ class CGPerSignatureCall(CGThing):
 
         for i in range(argConversionStartsAt, self.argCount):
             cgThings.append(
                 CGArgumentConverter(arguments[i], i, self.descriptor,
                                     argDescription % {"index": i + 1},
                                     idlNode, invalidEnumValueFatal=not setter,
                                     lenientFloatCode=lenientFloatCode))
 
+        # Now that argument processing is done, enforce the LenientFloat stuff
+        if lenientFloatCode:
+            if setter:
+                foundNonFiniteFloatBehavior = "return true;\n"
+            else:
+                assert idlNode.isMethod()
+                foundNonFiniteFloatBehavior = dedent(
+                    """
+                    args.rval().setUndefined();
+                    return true;
+                    """)
+            cgThings.append(CGGeneric(fill(
+                """
+                if (foundNonFiniteFloat) {
+                  $*{returnSteps}
+                }
+                """,
+                returnSteps=foundNonFiniteFloatBehavior)))
+
         if needsUnwrap:
             # Something depends on having the unwrapped object, so unwrap it now.
             xraySteps = []
             # XXXkhuey we should be able to MOZ_ASSERT that ${obj} is
             # not null.
             xraySteps.append(
                 CGGeneric(fill(
                     """
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -37362,16 +37362,22 @@
                 "=="
               ]
             ],
             "url": "/svg/linking/reftests/href-use-element.html"
           }
         ]
       },
       "testharness": {
+        "2dcontext/path-objects/2d.path.lineTo.nonfinite.details.html": [
+          {
+            "path": "2dcontext/path-objects/2d.path.lineTo.nonfinite.details.html",
+            "url": "/2dcontext/path-objects/2d.path.lineTo.nonfinite.details.html"
+          }
+        ],
         "IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm": [
           {
             "path": "IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm",
             "timeout": "long",
             "url": "/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm"
           }
         ],
         "editing/other/restoration.html": [
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/2dcontext/path-objects/2d.path.lineTo.nonfinite.details.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.lineTo.nonfinite.details</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.lineTo.nonfinite.details</h1>
+<p class="desc">lineTo() with Infinity/NaN for first arg still converts the second arg</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("lineTo() with Infinity/NaN for first arg still converts the second arg");
+_addTest(function(canvas, ctx) {
+
+for (var arg1 of [Infinity, -Infinity, NaN]) {
+  var converted = false;
+  ctx.lineTo(arg1, { valueOf: function() { converted = true; return 0; } });
+  _assert(converted, "converted");
+}
+
+
+});
+</script>
+
--- a/testing/web-platform/tests/2dcontext/tools/tests2d.yaml
+++ b/testing/web-platform/tests/2dcontext/tools/tests2d.yaml
@@ -6192,16 +6192,28 @@
     ctx.lineTo(100, 50);
     ctx.lineTo(0, 50);
     ctx.fillStyle = '#0f0';
     ctx.fill();
     @assert pixel 50,25 == 0,255,0,255;
     @assert pixel 90,45 == 0,255,0,255;
   expected: green
 
+- name: 2d.path.lineTo.nonfinite.details
+  desc: lineTo() with Infinity/NaN for first arg still converts the second arg
+  testing:
+    - 2d.nonfinite
+  code: |
+    for (var arg1 of [Infinity, -Infinity, NaN]) {
+      var converted = false;
+      ctx.lineTo(arg1, { valueOf: function() { converted = true; return 0; } });
+      @assert converted;
+    }
+  expected: clear
+
 - name: 2d.path.quadraticCurveTo.ensuresubpath.1
   desc: If there is no subpath, the first control point is added (and nothing is drawn up to it)
   testing:
     - 2d.path.quadratic.empty
     - 2d.path.ensure
   code: |
     ctx.fillStyle = '#0f0';
     ctx.fillRect(0, 0, 100, 50);