From e5347eceacd7354c8f48bddbf2d9cee6b8f8cfc3 Mon Sep 17 00:00:00 2001 From: Taym Haddadi Date: Fri, 9 May 2025 13:05:56 +0200 Subject: [PATCH] WebIDL Fix ImageData constructor to take a Uint8ClampedArray instead of js_object (#31398) Fix ImageData constructor to take a Uint8ClampedArray instead of js_object --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #31320 - [x] These changes do not require tests because there is not behavior change. --------- Signed-off-by: Taym Haddadi --- .../script/dom/bindings/buffer_source.rs | 49 +++++++------------ components/script/dom/imagedata.rs | 49 +++++++++---------- .../webidls/CanvasRenderingContext2D.webidl | 2 +- .../2d.imageData.object.ctor.basics.html.ini | 3 -- 4 files changed, 42 insertions(+), 61 deletions(-) delete mode 100644 tests/wpt/meta/html/canvas/element/pixel-manipulation/2d.imageData.object.ctor.basics.html.ini diff --git a/components/script/dom/bindings/buffer_source.rs b/components/script/dom/bindings/buffer_source.rs index dd6984e1eab..14a71532e9d 100644 --- a/components/script/dom/bindings/buffer_source.rs +++ b/components/script/dom/bindings/buffer_source.rs @@ -37,7 +37,7 @@ use js::rust::{ #[cfg(feature = "webgpu")] use js::typedarray::{ArrayBuffer, HeapArrayBuffer}; use js::typedarray::{ - ArrayBufferU8, ArrayBufferView, ArrayBufferViewU8, CreateWith, TypedArray, TypedArrayElement, + ArrayBufferU8, ArrayBufferViewU8, CreateWith, TypedArray, TypedArrayElement, TypedArrayElementCreator, }; @@ -63,36 +63,25 @@ pub(crate) enum BufferSource { ArrayBuffer(Box>), } -pub(crate) fn new_initialized_heap_buffer_source( - init: HeapTypedArrayInit, +pub(crate) fn create_heap_buffer_source_with_length( + cx: JSContext, + len: u32, can_gc: CanGc, -) -> Result, ()> +) -> Fallible> where T: TypedArrayElement + TypedArrayElementCreator, T::Element: Clone + Copy, { - let heap_buffer_source = match init { - HeapTypedArrayInit::Buffer(buffer_source) => HeapBufferSource { - buffer_source, - phantom: PhantomData, - }, - HeapTypedArrayInit::Info { len, cx } => { - rooted!(in (*cx) let mut array = ptr::null_mut::()); - let typed_array_result = - create_buffer_source_with_length::(cx, len as usize, array.handle_mut(), can_gc); - if typed_array_result.is_err() { - return Err(()); - } + rooted!(in (*cx) let mut array = ptr::null_mut::()); + let typed_array_result = + create_buffer_source_with_length::(cx, len as usize, array.handle_mut(), can_gc); + if typed_array_result.is_err() { + return Err(Error::JSFailed); + } - HeapBufferSource::::new(BufferSource::ArrayBufferView(Heap::boxed(*array.handle()))) - }, - }; - Ok(heap_buffer_source) -} - -pub(crate) enum HeapTypedArrayInit { - Buffer(BufferSource), - Info { len: u32, cx: JSContext }, + Ok(HeapBufferSource::::new(BufferSource::ArrayBufferView( + Heap::boxed(*array.handle()), + ))) } pub(crate) struct HeapBufferSource { @@ -131,11 +120,11 @@ where } pub(crate) fn from_view( - chunk: CustomAutoRooterGuard, - ) -> HeapBufferSource { - HeapBufferSource::::new(BufferSource::ArrayBufferView(Heap::boxed( - unsafe { *chunk.underlying_object() }, - ))) + chunk: CustomAutoRooterGuard>, + ) -> HeapBufferSource { + HeapBufferSource::::new(BufferSource::ArrayBufferView(Heap::boxed(unsafe { + *chunk.underlying_object() + }))) } pub(crate) fn default() -> Self { diff --git a/components/script/dom/imagedata.rs b/components/script/dom/imagedata.rs index bd45a80fce2..a891064952a 100644 --- a/components/script/dom/imagedata.rs +++ b/components/script/dom/imagedata.rs @@ -9,13 +9,13 @@ use std::vec::Vec; use dom_struct::dom_struct; use euclid::default::{Rect, Size2D}; use ipc_channel::ipc::IpcSharedMemory; -use js::jsapi::{Heap, JSObject}; +use js::gc::CustomAutoRooterGuard; +use js::jsapi::JSObject; use js::rust::HandleObject; use js::typedarray::{ClampedU8, CreateWith, Uint8ClampedArray}; -use super::bindings::buffer_source::{ - BufferSource, HeapBufferSource, HeapTypedArrayInit, new_initialized_heap_buffer_source, -}; +use super::bindings::buffer_source::{HeapBufferSource, create_heap_buffer_source_with_length}; +use crate::dom::bindings::buffer_source::create_buffer_source; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::ImageDataMethods; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::reflector::{Reflector, reflect_dom_object_with_proto}; @@ -55,31 +55,31 @@ impl ImageData { rooted!(in (*cx) let mut js_object = ptr::null_mut::()); if let Some(ref mut d) = data { d.resize(len as usize, 0); + + let typed_array = + create_buffer_source::(cx, &d[..], js_object.handle_mut(), can_gc) + .map_err(|_| Error::JSFailed)?; + let data = CreateWith::Slice(&d[..]); Uint8ClampedArray::create(*cx, data, js_object.handle_mut()).unwrap(); - Self::new_with_jsobject(global, None, width, Some(height), js_object.get(), can_gc) + auto_root!(in(*cx) let data = typed_array); + Self::new_with_data(global, None, width, Some(height), data, can_gc) } else { - Self::new_without_jsobject(global, None, width, height, can_gc) + Self::new_without_data(global, None, width, height, can_gc) } } } #[allow(unsafe_code)] - fn new_with_jsobject( + fn new_with_data( global: &GlobalScope, proto: Option, width: u32, opt_height: Option, - jsobject: *mut JSObject, + data: CustomAutoRooterGuard, can_gc: CanGc, ) -> Fallible> { - let heap_typed_array = match new_initialized_heap_buffer_source::( - HeapTypedArrayInit::Buffer(BufferSource::ArrayBufferView(Heap::boxed(jsobject))), - can_gc, - ) { - Ok(heap_typed_array) => heap_typed_array, - Err(_) => return Err(Error::JSFailed), - }; + let heap_typed_array = HeapBufferSource::::from_view(data); let typed_array = match heap_typed_array.get_typed_array() { Ok(array) => array, @@ -117,13 +117,14 @@ impl ImageData { )) } - fn new_without_jsobject( + fn new_without_data( global: &GlobalScope, proto: Option, width: u32, height: u32, can_gc: CanGc, ) -> Fallible> { + // If one or both of sw and sh are zero, then throw an "IndexSizeError" DOMException. if width == 0 || height == 0 { return Err(Error::IndexSize); } @@ -139,13 +140,8 @@ impl ImageData { let cx = GlobalScope::get_cx(); - let heap_typed_array = match new_initialized_heap_buffer_source::( - HeapTypedArrayInit::Info { len, cx }, - can_gc, - ) { - Ok(heap_typed_array) => heap_typed_array, - Err(_) => return Err(Error::JSFailed), - }; + let heap_typed_array = create_heap_buffer_source_with_length::(cx, len, can_gc)?; + let imagedata = Box::new(ImageData { reflector_: Reflector::new(), width, @@ -198,20 +194,19 @@ impl ImageDataMethods for ImageData { width: u32, height: u32, ) -> Fallible> { - Self::new_without_jsobject(global, proto, width, height, can_gc) + Self::new_without_data(global, proto, width, height, can_gc) } /// fn Constructor_( - _cx: JSContext, global: &GlobalScope, proto: Option, can_gc: CanGc, - jsobject: *mut JSObject, + data: CustomAutoRooterGuard, width: u32, opt_height: Option, ) -> Fallible> { - Self::new_with_jsobject(global, proto, width, opt_height, jsobject, can_gc) + Self::new_with_data(global, proto, width, opt_height, data, can_gc) } /// diff --git a/components/script_bindings/webidls/CanvasRenderingContext2D.webidl b/components/script_bindings/webidls/CanvasRenderingContext2D.webidl index 0c4960fe6ad..46d91683577 100644 --- a/components/script_bindings/webidls/CanvasRenderingContext2D.webidl +++ b/components/script_bindings/webidls/CanvasRenderingContext2D.webidl @@ -254,7 +254,7 @@ interface CanvasPattern { Serializable] interface ImageData { [Throws] constructor(unsigned long sw, unsigned long sh/*, optional ImageDataSettings settings = {}*/); - [Throws] constructor(/* Uint8ClampedArray */ object data, unsigned long sw, optional unsigned long sh + [Throws] constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh /*, optional ImageDataSettings settings = {}*/); readonly attribute unsigned long width; diff --git a/tests/wpt/meta/html/canvas/element/pixel-manipulation/2d.imageData.object.ctor.basics.html.ini b/tests/wpt/meta/html/canvas/element/pixel-manipulation/2d.imageData.object.ctor.basics.html.ini deleted file mode 100644 index 1a3c292f9f2..00000000000 --- a/tests/wpt/meta/html/canvas/element/pixel-manipulation/2d.imageData.object.ctor.basics.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[2d.imageData.object.ctor.basics.html] - [Testing different type of ImageData constructor] - expected: FAIL