Bug 630052, part c: Handle non-finite and negative arguments to createImageData and getImageData according to spec; r=bz
authorMs2ger <ms2ger@gmail.com>
Sat, 02 Apr 2011 14:19:03 -0400
changeset 64656 c51360e5cc597c94574275e7aedf12362bdabaf8
parent 64655 2676052e13a8236bff374b3c8d35e8c65b7b746f
child 64657 c88a58ccb0af893431816e55a1bb0b00012db197
push idunknown
push userunknown
push dateunknown
reviewersbz
bugs630052
milestone2.2a1pre
Bug 630052, part c: Handle non-finite and negative arguments to createImageData and getImageData according to spec; r=bz
content/canvas/src/CustomQS_Canvas2D.h
content/canvas/test/test_canvas.html
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -11,22 +11,23 @@
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
  * The Original Code is Gecko code.
  *
  * The Initial Developer of the Original Code is
- *   Mozilla Corporation
+ * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Vladimir Vukicevic <vladimir@pobox.com> (original author)
+ *   Ms2ger <ms2ger@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -35,16 +36,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsDOMError.h"
 #include "nsIDOMCanvasRenderingContext2D.h"
 #include "CheckedInt.h"
+#include "nsMathUtils.h"
 
 typedef nsresult (NS_STDCALL nsIDOMCanvasRenderingContext2D::*CanvasStyleSetterType)(const nsAString &, nsISupports *);
 typedef nsresult (NS_STDCALL nsIDOMCanvasRenderingContext2D::*CanvasStyleGetterType)(nsAString &, nsISupports **, PRInt32 *);
 
 static JSBool
 Canvas2D_SetStyleHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
                         CanvasStyleSetterType setfunc)
 {
@@ -218,27 +220,32 @@ nsIDOMCanvasRenderingContext2D_CreateIma
 
     /* Note: this doesn't need JS_THIS_OBJECT */
 
     if (argc < 2)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
-    int32 wi, hi;
-    if (!JS_ValueToECMAInt32(cx, argv[0], &wi) ||
-        !JS_ValueToECMAInt32(cx, argv[1], &hi))
-        return JS_FALSE;
+    jsdouble width, height;
+    if (!JS_ValueToNumber(cx, argv[0], &width) ||
+        !JS_ValueToNumber(cx, argv[1], &height))
+        return false;
 
-    if (wi <= 0 || hi <= 0)
+    if (!NS_finite(width) || !NS_finite(height))
+        return xpc_qsThrow(cx, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+
+    if (!width || !height)
         return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
 
-    uint32 w = (uint32) wi;
-    uint32 h = (uint32) hi;
+    int32 wi = JS_DoubleToInt32(width);
+    int32 hi = JS_DoubleToInt32(height);
 
+    uint32 w = PR_ABS(wi);
+    uint32 h = PR_ABS(hi);
     return CreateImageData(cx, w, h, NULL, 0, 0, vp);
 }
 
 static JSBool
 nsIDOMCanvasRenderingContext2D_GetImageData(JSContext *cx, uintN argc, jsval *vp)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
 
@@ -252,30 +259,50 @@ nsIDOMCanvasRenderingContext2D_GetImageD
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 4)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
-    int32 x, y;
-    int32 wi, hi;
-    if (!JS_ValueToECMAInt32(cx, argv[0], &x) ||
-        !JS_ValueToECMAInt32(cx, argv[1], &y) ||
-        !JS_ValueToECMAInt32(cx, argv[2], &wi) ||
-        !JS_ValueToECMAInt32(cx, argv[3], &hi))
-        return JS_FALSE;
+    jsdouble xd, yd, width, height;
+    if (!JS_ValueToNumber(cx, argv[0], &xd) ||
+        !JS_ValueToNumber(cx, argv[1], &yd) ||
+        !JS_ValueToNumber(cx, argv[2], &width) ||
+        !JS_ValueToNumber(cx, argv[3], &height))
+        return false;
 
-    if (wi <= 0 || hi <= 0)
+    if (!NS_finite(xd) || !NS_finite(yd) ||
+        !NS_finite(width) || !NS_finite(height))
+        return xpc_qsThrow(cx, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+
+    if (!width || !height)
         return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
 
-    uint32 w = (uint32) wi;
-    uint32 h = (uint32) hi;
+    int32 x = JS_DoubleToInt32(xd);
+    int32 y = JS_DoubleToInt32(yd);
+    int32 wi = JS_DoubleToInt32(width);
+    int32 hi = JS_DoubleToInt32(height);
 
+    // Handle negative width and height by flipping the rectangle over in the
+    // relevant direction.
+    uint32 w, h;
+    if (width < 0) {
+        w = -wi;
+        x -= w;
+    } else {
+        w = wi;
+    }
+    if (height < 0) {
+        h = -hi;
+        y -= h;
+    } else {
+        h = hi;
+    }
     return CreateImageData(cx, w, h, self, x, y, vp);
 }
 
 static JSBool
 nsIDOMCanvasRenderingContext2D_PutImageData(JSContext *cx, uintN argc, jsval *vp)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
 
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -7305,17 +7305,17 @@ var imgdata3 = ctx.createImageData(10, -
 var imgdata4 = ctx.createImageData(-10, -20);
 ok(imgdata1.data.length == imgdata2.data.length, "imgdata1.data.length == imgdata2.data.length");
 ok(imgdata2.data.length == imgdata3.data.length, "imgdata2.data.length == imgdata3.data.length");
 ok(imgdata3.data.length == imgdata4.data.length, "imgdata3.data.length == imgdata4.data.length");
 
 } catch (e) {
     _thrown_outer = true;
 }
-todo(!_thrown_outer, 'should not throw exception');
+ok(!_thrown_outer, 'should not throw exception');
 
 
 }
 </script>
 
 <!-- [[[ test_2d.imageData.create.nonfinite.html ]]] -->
 
 <p>Canvas test: 2d.imageData.create.nonfinite - bug 433004</p>
@@ -7325,35 +7325,56 @@ todo(!_thrown_outer, 'should not throw e
 
 function test_2d_imageData_create_nonfinite() {
 
 var canvas = document.getElementById('c258');
 var ctx = canvas.getContext('2d');
 
 var _thrown = undefined; try {
   ctx.createImageData(Infinity, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.createImageData(-Infinity, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.createImageData(NaN, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.createImageData(10, Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.createImageData(10, -Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.createImageData(10, NaN);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.createImageData(Infinity, Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.createImageData({valueOf:function() Infinity}, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.createImageData({valueOf:function() -Infinity}, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.createImageData({valueOf:function() NaN}, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.createImageData(10, {valueOf:function() Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.createImageData(10, {valueOf:function() -Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.createImageData(10, {valueOf:function() NaN});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.createImageData({valueOf:function() Infinity}, {valueOf:function() Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.imageData.create.round.html ]]] -->
 
 <p>Canvas test: 2d.imageData.create.round - bug 433004</p>
@@ -7389,28 +7410,28 @@ function test_2d_imageData_create_tiny()
 var canvas = document.getElementById('c260');
 var ctx = canvas.getContext('2d');
 
 var _thrown_outer = false;
 try {
 
 var imgdata = ctx.createImageData(0.0001, 0.0001);
 ok(imgdata.data.length == imgdata.width*imgdata.height*4, "imgdata.data.length == imgdata.width*imgdata.height*4");
-ok(imgdata.width == 1, "imgdata.width == 1");
-ok(imgdata.height == 1, "imgdata.height == 1");
+todo(imgdata.width == 1, "imgdata.width == 1");
+todo(imgdata.height == 1, "imgdata.height == 1");
 var isTransparentBlack = true;
 for (var i = 0; i < imgdata.data.length; ++i)
     if (imgdata.data[i] !== 0)
         isTransparentBlack = false;
 ok(isTransparentBlack, "isTransparentBlack");
 
 } catch (e) {
     _thrown_outer = true;
 }
-todo(!_thrown_outer, 'should not throw exception');
+ok(!_thrown_outer, 'should not throw exception');
 
 
 }
 </script>
 
 <!-- [[[ test_2d.imageData.create.type.html ]]] -->
 
 <p>Canvas test: 2d.imageData.create.type - bug 433004</p>
@@ -7525,83 +7546,152 @@ ok(imgdata2.data[2] === 255, "imgdata2.d
 
 function test_2d_imageData_get_nonfinite() {
 
 var canvas = document.getElementById('c265');
 var ctx = canvas.getContext('2d');
 
 var _thrown = undefined; try {
   ctx.getImageData(Infinity, 10, 10, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(-Infinity, 10, 10, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(NaN, 10, 10, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, Infinity, 10, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, -Infinity, 10, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, NaN, 10, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, 10, Infinity, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, 10, -Infinity, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, 10, NaN, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, 10, 10, Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, 10, 10, -Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, 10, 10, NaN);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(Infinity, Infinity, 10, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(Infinity, Infinity, Infinity, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(Infinity, Infinity, Infinity, Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(Infinity, Infinity, 10, Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(Infinity, 10, Infinity, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(Infinity, 10, Infinity, Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(Infinity, 10, 10, Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, Infinity, Infinity, 10);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, Infinity, Infinity, Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, Infinity, 10, Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 var _thrown = undefined; try {
   ctx.getImageData(10, 10, Infinity, Infinity);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData({valueOf:function() Infinity}, 10, 10, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData({valueOf:function() -Infinity}, 10, 10, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData({valueOf:function() NaN}, 10, 10, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, {valueOf:function() Infinity}, 10, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, {valueOf:function() -Infinity}, 10, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, {valueOf:function() NaN}, 10, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, 10, {valueOf:function() Infinity}, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, 10, {valueOf:function() -Infinity}, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, 10, {valueOf:function() NaN}, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, 10, 10, {valueOf:function() Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, 10, 10, {valueOf:function() -Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, 10, 10, {valueOf:function() NaN});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData({valueOf:function() Infinity}, {valueOf:function() Infinity}, 10, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData({valueOf:function() Infinity}, {valueOf:function() Infinity}, {valueOf:function() Infinity}, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData({valueOf:function() Infinity}, {valueOf:function() Infinity}, {valueOf:function() Infinity}, {valueOf:function() Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData({valueOf:function() Infinity}, {valueOf:function() Infinity}, 10, {valueOf:function() Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData({valueOf:function() Infinity}, 10, {valueOf:function() Infinity}, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData({valueOf:function() Infinity}, 10, {valueOf:function() Infinity}, {valueOf:function() Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData({valueOf:function() Infinity}, 10, 10, {valueOf:function() Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, {valueOf:function() Infinity}, {valueOf:function() Infinity}, 10);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, {valueOf:function() Infinity}, {valueOf:function() Infinity}, {valueOf:function() Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, {valueOf:function() Infinity}, 10, {valueOf:function() Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
+var _thrown = undefined; try {
+  ctx.getImageData(10, 10, {valueOf:function() Infinity}, {valueOf:function() Infinity});
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
 
 
 }
 </script>
 
 <!-- [[[ test_2d.imageData.get.nonpremul.html ]]] -->
 
 <p>Canvas test: 2d.imageData.get.nonpremul</p>
@@ -7763,25 +7853,29 @@ var ctx = canvas.getContext('2d');
 var _thrown_outer = false;
 try {
 
 ctx.fillStyle = '#000';
 ctx.fillRect(0, 0, 100, 50);
 ctx.fillStyle = '#fff';
 ctx.fillRect(20, 10, 60, 10);
 
-var imgdata1 = ctx.getImageData(85, 25, -10, -10);
-ok(imgdata1.data[0] === 255, "imgdata1.data[\""+(0)+"\"] === 255");
-ok(imgdata1.data[1] === 255, "imgdata1.data[\""+(1)+"\"] === 255");
-ok(imgdata1.data[2] === 255, "imgdata1.data[\""+(2)+"\"] === 255");
-ok(imgdata1.data[3] === 255, "imgdata1.data[\""+(3)+"\"] === 255");
-ok(imgdata1.data[imgdata1.data.length-4+0] === 0, "imgdata1.data[imgdata1.data.length-4+0] === 0");
-ok(imgdata1.data[imgdata1.data.length-4+1] === 0, "imgdata1.data[imgdata1.data.length-4+1] === 0");
-ok(imgdata1.data[imgdata1.data.length-4+2] === 0, "imgdata1.data[imgdata1.data.length-4+2] === 0");
-ok(imgdata1.data[imgdata1.data.length-4+3] === 255, "imgdata1.data[imgdata1.data.length-4+3] === 255");
+try {
+  var imgdata1 = ctx.getImageData(85, 25, -10, -10);
+  ok(imgdata1.data[0] === 255, "imgdata1.data[\""+(0)+"\"] === 255");
+  ok(imgdata1.data[1] === 255, "imgdata1.data[\""+(1)+"\"] === 255");
+  ok(imgdata1.data[2] === 255, "imgdata1.data[\""+(2)+"\"] === 255");
+  ok(imgdata1.data[3] === 255, "imgdata1.data[\""+(3)+"\"] === 255");
+  ok(imgdata1.data[imgdata1.data.length-4+0] === 0, "imgdata1.data[imgdata1.data.length-4+0] === 0");
+  ok(imgdata1.data[imgdata1.data.length-4+1] === 0, "imgdata1.data[imgdata1.data.length-4+1] === 0");
+  ok(imgdata1.data[imgdata1.data.length-4+2] === 0, "imgdata1.data[imgdata1.data.length-4+2] === 0");
+  ok(imgdata1.data[imgdata1.data.length-4+3] === 255, "imgdata1.data[imgdata1.data.length-4+3] === 255");
+} catch (e) {
+  ok(false, "Unexpected exception in first part of test_2d_imageData_get_source_negative()", e);
+}
 
 var imgdata2 = ctx.getImageData(0, 0, -1, -1);
 ok(imgdata2.data[0] === 0, "imgdata2.data[\""+(0)+"\"] === 0");
 ok(imgdata2.data[1] === 0, "imgdata2.data[\""+(1)+"\"] === 0");
 ok(imgdata2.data[2] === 0, "imgdata2.data[\""+(2)+"\"] === 0");
 ok(imgdata2.data[3] === 0, "imgdata2.data[\""+(3)+"\"] === 0");
 
 } catch (e) {