Bug 550309 - Part a: Tighten up support for fake ImageData objects; r=bz

This commit is contained in:
Ms2ger 2012-03-16 10:41:53 +01:00
parent a3590a2571
commit eaded82b0f
5 changed files with 76 additions and 83 deletions

View File

@ -0,0 +1,52 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef CustomQS_Canvas_h
#define CustomQS_Canvas_h
#include "jsapi.h"
static bool
GetPositiveInt(JSContext* cx, JSObject& obj, const char* name, uint32_t* out)
{
JS::Value temp;
int32_t signedInt;
if (!JS_GetProperty(cx, &obj, name, &temp) ||
!JS_ValueToECMAInt32(cx, temp, &signedInt)) {
return false;
}
if (signedInt <= 0) {
return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
}
*out = uint32_t(signedInt);
return true;
}
static bool
GetImageData(JSContext* cx, const JS::Value& imageData,
uint32_t* width, uint32_t* height, JS::Anchor<JSObject*>* array)
{
if (!imageData.isObject()) {
return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
}
JSObject& dataObject = imageData.toObject();
if (!GetPositiveInt(cx, dataObject, "width", width) ||
!GetPositiveInt(cx, dataObject, "height", height)) {
return false;
}
JS::Value temp;
if (!JS_GetProperty(cx, &dataObject, "data", &temp)) {
return false;
}
if (!temp.isObject()) {
return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
}
array->set(&temp.toObject());
return true;
}
#endif // CustomQS_Canvas_h

View File

@ -42,6 +42,7 @@
#include "nsIDOMCanvasRenderingContext2D.h"
#include "CheckedInt.h"
#include "nsMathUtils.h"
#include "CustomQS_Canvas.h"
#include "jsapi.h"
@ -219,32 +220,6 @@ CreateImageData(JSContext* cx,
return true;
}
static bool
GetImageDataDimensions(JSContext *cx, JSObject *dataObject, uint32_t *width, uint32_t *height)
{
jsval temp;
int32_t wi, hi;
// Need to check that dataObject is ImageData object. That's hard for the moment
// because they're just vanilla objects in our implementation.
// Let's guess, if the object has valid width and height then it's suitable
// for this operation.
if (!JS_GetProperty(cx, dataObject, "width", &temp) ||
!JS_ValueToECMAInt32(cx, temp, &wi))
return false;
if (!JS_GetProperty(cx, dataObject, "height", &temp) ||
!JS_ValueToECMAInt32(cx, temp, &hi))
return false;
if (wi <= 0 || hi <= 0)
return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
*width = uint32_t(wi);
*height = uint32_t(hi);
return true;
}
static JSBool
nsIDOMCanvasRenderingContext2D_CreateImageData(JSContext *cx, unsigned argc, jsval *vp)
{
@ -258,16 +233,11 @@ nsIDOMCanvasRenderingContext2D_CreateImageData(JSContext *cx, unsigned argc, jsv
jsval *argv = JS_ARGV(cx, vp);
if (argc == 1) {
// The specification asks to throw NOT_SUPPORTED if first argument is NULL,
// An object is expected, so throw an exception for all primitives.
if (JSVAL_IS_PRIMITIVE(argv[0]))
return xpc_qsThrow(cx, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
JSObject *dataObject = JSVAL_TO_OBJECT(argv[0]);
uint32_t data_width, data_height;
if (!GetImageDataDimensions(cx, dataObject, &data_width, &data_height))
JS::Anchor<JSObject*> darray;
if (!GetImageData(cx, argv[0], &data_width, &data_height, &darray)) {
return false;
}
return CreateImageData(cx, data_width, data_height, NULL, 0, 0, vp);
}
@ -370,10 +340,11 @@ nsIDOMCanvasRenderingContext2D_PutImageData(JSContext *cx, unsigned argc, jsval
jsval *argv = JS_ARGV(cx, vp);
if (JSVAL_IS_PRIMITIVE(argv[0]))
return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
JSObject *dataObject = JSVAL_TO_OBJECT(argv[0]);
uint32_t w, h;
JS::Anchor<JSObject*> darray;
if (!GetImageData(cx, argv[0], &w, &h, &darray)) {
return false;
}
double xd, yd;
if (!JS_ValueToNumber(cx, argv[1], &xd) ||
@ -388,13 +359,6 @@ nsIDOMCanvasRenderingContext2D_PutImageData(JSContext *cx, unsigned argc, jsval
int32_t x = JS_DoubleToInt32(xd);
int32_t y = JS_DoubleToInt32(yd);
// Grab width, height, and the dense array from the dataObject.
JS::AutoValueRooter tv(cx);
uint32_t w, h;
if (!GetImageDataDimensions(cx, dataObject, &w, &h))
return JS_FALSE;
// the optional dirty rect
bool hasDirtyRect = false;
int32_t dirtyX = 0,
@ -424,24 +388,16 @@ nsIDOMCanvasRenderingContext2D_PutImageData(JSContext *cx, unsigned argc, jsval
hasDirtyRect = true;
}
if (!JS_GetProperty(cx, dataObject, "data", tv.jsval_addr()))
return JS_FALSE;
if (JSVAL_IS_PRIMITIVE(tv.jsval_value()))
return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
JSObject *darray = JSVAL_TO_OBJECT(tv.jsval_value());
JS::AutoValueRooter tsrc_tvr(cx);
JSObject *tsrc = NULL;
if (js::GetObjectClass(darray) == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8] ||
js::GetObjectClass(darray) == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8_CLAMPED])
if (js::GetObjectClass(darray.get()) == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8] ||
js::GetObjectClass(darray.get()) == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8_CLAMPED])
{
tsrc = js::TypedArray::getTypedArray(darray);
} else if (JS_IsArrayObject(cx, darray) || js_IsTypedArray(darray)) {
tsrc = darray.get();
} else if (JS_IsArrayObject(cx, darray.get()) || js_IsTypedArray(darray.get())) {
// ugh, this isn't a uint8 typed array, someone made their own object; convert it to a typed array
JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_UINT8, darray);
JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_UINT8, darray.get());
if (!nobj)
return JS_FALSE;

View File

@ -42,6 +42,7 @@
#include "jsapi.h"
#include "jstypedarray.h"
#include "CustomQS_Canvas.h"
#define GET_INT32_ARG(var, index) \
int32_t var; \
@ -479,33 +480,16 @@ TexImage2DImageDataOrElement(JSContext* cx, T& self, JS::Value* object)
// Failed to interpret object as an Element, now try to interpret it as
// ImageData.
JSObject* imageData = &object->toObject();
jsval js_width, js_height, js_data;
if (!JS_GetProperty(cx, imageData, "width", &js_width) ||
!JS_GetProperty(cx, imageData, "height", &js_height) ||
!JS_GetProperty(cx, imageData, "data", &js_data)) {
uint32_t int_width, int_height;
JS::Anchor<JSObject*> obj_data;
if (!GetImageData(cx, *object, &int_width, &int_height, &obj_data)) {
return false;
}
if (js_width == JSVAL_VOID ||
js_height == JSVAL_VOID ||
!js_data.isObject())
{
return xpc_qsThrow(cx, NS_ERROR_FAILURE);
}
int32_t int_width, int_height;
JSObject *obj_data = JSVAL_TO_OBJECT(js_data);
if (!JS_ValueToECMAInt32(cx, js_width, &int_width) ||
!JS_ValueToECMAInt32(cx, js_height, &int_height))
{
return false;
}
if (!js_IsTypedArray(obj_data))
{
if (!js_IsTypedArray(obj_data.get())) {
return xpc_qsThrow(cx, NS_ERROR_FAILURE);
}
nsresult rv = self.DoCallForImageData(int_width, int_height, obj_data);
nsresult rv = self.DoCallForImageData(int_width, int_height, obj_data.get());
return NS_SUCCEEDED(rv) || xpc_qsThrow(cx, rv);
}

View File

@ -49,6 +49,7 @@ LIBRARY_NAME = gkconcvs_s
LIBXUL_LIBRARY = 1
EXPORTS = \
CustomQS_Canvas.h \
CustomQS_Canvas2D.h \
CustomQS_WebGL.h \
$(NULL)

View File

@ -7681,7 +7681,7 @@ var _thrown = undefined; try {
<!-- [[[ test_2d.imageData.create1.zero.html ]]] -->
<p>Canvas test: 2d.imageData.create1.zero - bug 630040</p>
<!-- Testing: createImageData(null) throws NOT_SUPPORTED_ERR -->
<!-- Testing: createImageData(null) throws TypeError -->
<canvas id="c262a" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
<script>
@ -7692,7 +7692,7 @@ var ctx = canvas.getContext('2d');
var _thrown = undefined; try {
ctx.createImageData(null);
} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
} catch (e) { _thrown = e }; todo(_thrown && _thrown instanceof TypeError, "should throw TypeError");
}
@ -10790,7 +10790,7 @@ if (ctx.createImageData) {
} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
var _thrown = undefined; try {
ctx.createImageData(1);
} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.NOT_SUPPORTED_ERR, "should throw NOT_SUPPORTED_ERR");
}
if (ctx.getImageData) {
var _thrown = undefined; try {