diff --git a/components/script/dom/imagedata.rs b/components/script/dom/imagedata.rs index 33863cde2b6..d3adb0f3f76 100644 --- a/components/script/dom/imagedata.rs +++ b/components/script/dom/imagedata.rs @@ -5,6 +5,7 @@ use core::nonzero::NonZero; use dom::bindings::codegen::Bindings::ImageDataBinding; use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; +use dom::bindings::error::{Fallible, Error}; use dom::bindings::js::Root; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::globalscope::GlobalScope; @@ -28,14 +29,7 @@ pub struct ImageData { impl ImageData { #[allow(unsafe_code)] pub fn new(global: &GlobalScope, width: u32, height: u32, mut data: Option>) -> Root { - let imagedata = box ImageData { - reflector_: Reflector::new(), - width: width, - height: height, - data: Heap::default(), - }; let len = width * height * 4; - unsafe { let cx = global.get_cx(); rooted!(in (cx) let mut js_object = ptr::null_mut()); @@ -47,11 +41,88 @@ impl ImageData { None => CreateWith::Length(len), }; Uint8ClampedArray::create(cx, data, js_object.handle_mut()).unwrap(); - (*imagedata).data.set(js_object.get()); + Self::new_with_jsobject(global, width, Some(height), Some(js_object.get())).unwrap() + } + } + + #[allow(unsafe_code)] + unsafe fn new_with_jsobject(global: &GlobalScope, + width: u32, + mut opt_height: Option, + opt_jsobject: Option<*mut JSObject>) + -> Fallible> { + assert!(opt_jsobject.is_some() || opt_height.is_some()); + + if width == 0 { + return Err(Error::IndexSize); } - reflect_dom_object(imagedata, - global, ImageDataBinding::Wrap) + // checking jsobject type and verifying (height * width * 4 == jsobject.byte_len()) + if let Some(jsobject) = opt_jsobject { + let cx = global.get_cx(); + typedarray!(in(cx) let array_res: Uint8ClampedArray = jsobject); + let mut array = try!(array_res + .map_err(|_| Error::Type("Argument to Image data is not an Uint8ClampedArray".to_owned()))); + + let byte_len = array.as_slice().len() as u32; + if byte_len % 4 != 0 { + return Err(Error::InvalidState); + } + + let len = byte_len / 4; + if width == 0 || len % width != 0 { + return Err(Error::IndexSize); + } + + let height = len / width; + if opt_height.map_or(false, |x| height != x) { + return Err(Error::IndexSize); + } else { + opt_height = Some(height); + } + } + + let height = opt_height.unwrap(); + if height == 0 { + return Err(Error::IndexSize); + } + + let imagedata = box ImageData { + reflector_: Reflector::new(), + width: width, + height: height, + data: Heap::default(), + }; + + if let Some(jsobject) = opt_jsobject { + (*imagedata).data.set(jsobject); + } else { + let len = width * height * 4; + let cx = global.get_cx(); + rooted!(in (cx) let mut array = ptr::null_mut()); + Uint8ClampedArray::create(cx, CreateWith::Length(len), array.handle_mut()).unwrap(); + (*imagedata).data.set(array.get()); + } + + Ok(reflect_dom_object(imagedata, global, ImageDataBinding::Wrap)) + } + + // https://html.spec.whatwg.org/multipage/#pixel-manipulation:dom-imagedata-3 + #[allow(unsafe_code)] + pub fn Constructor(global: &GlobalScope, width: u32, height: u32) -> Fallible> { + unsafe { Self::new_with_jsobject(global, width, Some(height), None) } + } + + // https://html.spec.whatwg.org/multipage/#pixel-manipulation:dom-imagedata-4 + #[allow(unsafe_code)] + #[allow(unused_variables)] + pub unsafe fn Constructor_(cx: *mut JSContext, + global: &GlobalScope, + jsobject: *mut JSObject, + width: u32, + opt_height: Option) + -> Fallible> { + Self::new_with_jsobject(global, width, opt_height, Some(jsobject)) } #[allow(unsafe_code)] diff --git a/components/script/dom/webidls/ImageData.webidl b/components/script/dom/webidls/ImageData.webidl index 3461b5e387f..d327facd5c9 100644 --- a/components/script/dom/webidls/ImageData.webidl +++ b/components/script/dom/webidls/ImageData.webidl @@ -9,9 +9,9 @@ * You are granted a license to use, reproduce and create derivative works of this document. */ -//[Constructor(unsigned long sw, unsigned long sh), -//Constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh), -[Exposed=(Window,Worker)] +[Constructor(unsigned long sw, unsigned long sh), + Constructor(/* Uint8ClampedArray */ object data, unsigned long sw, optional unsigned long sh), + Exposed=(Window,Worker)] interface ImageData { //[Constant] readonly attribute unsigned long width; diff --git a/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.object.ctor.html.ini b/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.object.ctor.html.ini new file mode 100644 index 00000000000..2a649b8ab43 --- /dev/null +++ b/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.object.ctor.html.ini @@ -0,0 +1,4 @@ +[2d.imageData.object.ctor.html] + type: testharness + [ImageData does not have a usable constructor] + expected: FAIL diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 975eb852e8f..34ef6d7c8f5 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -92591,6 +92591,12 @@ {} ] ], + "html/semantics/embedded-content/the-canvas-element/imagedata.html": [ + [ + "/html/semantics/embedded-content/the-canvas-element/imagedata.html", + {} + ] + ], "html/semantics/embedded-content/the-canvas-element/initial.colour.html": [ [ "/html/semantics/embedded-content/the-canvas-element/initial.colour.html", @@ -175580,6 +175586,10 @@ "38b6f3c5707b360427854b82054d86f5364dc0b8", "testharness" ], + "html/semantics/embedded-content/the-canvas-element/imagedata.html": [ + "e685ab0d76bdd1b60a5d6f1e2126ea1a89db97d1", + "testharness" + ], "html/semantics/embedded-content/the-canvas-element/initial.colour.html": [ "22ddb77f5a18a19edc409d36532120f852bfbc57", "testharness" diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini index 9d198261b01..7db5fef3a93 100644 --- a/tests/wpt/metadata/html/dom/interfaces.html.ini +++ b/tests/wpt/metadata/html/dom/interfaces.html.ini @@ -4116,9 +4116,6 @@ [TextMetrics interface: attribute ideographicBaseline] expected: FAIL - [ImageData interface object length] - expected: FAIL - [DrawingStyle interface: existence and properties of interface object] expected: FAIL diff --git a/tests/wpt/metadata/html/dom/interfaces.worker.js.ini b/tests/wpt/metadata/html/dom/interfaces.worker.js.ini index a5836d9611c..14b7a2381d0 100644 --- a/tests/wpt/metadata/html/dom/interfaces.worker.js.ini +++ b/tests/wpt/metadata/html/dom/interfaces.worker.js.ini @@ -1,8 +1,5 @@ [interfaces.worker.html] type: testharness - [ImageData interface object length] - expected: FAIL - [Path2D interface: existence and properties of interface object] expected: FAIL diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/imagedata.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/imagedata.html new file mode 100644 index 00000000000..b5b4d0de275 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/imagedata.html @@ -0,0 +1,58 @@ + + +ImageData Tests + + +