mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
WebIDL Fix ImageData constructor to take a Uint8ClampedArray instead of js_object (#31398)
<!-- Please describe your changes on the following line: --> Fix ImageData constructor to take a Uint8ClampedArray instead of js_object --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #31320 <!-- Either: --> - [x] These changes do not require tests because there is not behavior change. <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> --------- Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
This commit is contained in:
parent
53be79a5b5
commit
e5347eceac
4 changed files with 42 additions and 61 deletions
|
@ -37,7 +37,7 @@ use js::rust::{
|
||||||
#[cfg(feature = "webgpu")]
|
#[cfg(feature = "webgpu")]
|
||||||
use js::typedarray::{ArrayBuffer, HeapArrayBuffer};
|
use js::typedarray::{ArrayBuffer, HeapArrayBuffer};
|
||||||
use js::typedarray::{
|
use js::typedarray::{
|
||||||
ArrayBufferU8, ArrayBufferView, ArrayBufferViewU8, CreateWith, TypedArray, TypedArrayElement,
|
ArrayBufferU8, ArrayBufferViewU8, CreateWith, TypedArray, TypedArrayElement,
|
||||||
TypedArrayElementCreator,
|
TypedArrayElementCreator,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,36 +63,25 @@ pub(crate) enum BufferSource {
|
||||||
ArrayBuffer(Box<Heap<*mut JSObject>>),
|
ArrayBuffer(Box<Heap<*mut JSObject>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_initialized_heap_buffer_source<T>(
|
pub(crate) fn create_heap_buffer_source_with_length<T>(
|
||||||
init: HeapTypedArrayInit,
|
cx: JSContext,
|
||||||
|
len: u32,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Result<HeapBufferSource<T>, ()>
|
) -> Fallible<HeapBufferSource<T>>
|
||||||
where
|
where
|
||||||
T: TypedArrayElement + TypedArrayElementCreator,
|
T: TypedArrayElement + TypedArrayElementCreator,
|
||||||
T::Element: Clone + Copy,
|
T::Element: Clone + Copy,
|
||||||
{
|
{
|
||||||
let heap_buffer_source = match init {
|
rooted!(in (*cx) let mut array = ptr::null_mut::<JSObject>());
|
||||||
HeapTypedArrayInit::Buffer(buffer_source) => HeapBufferSource {
|
let typed_array_result =
|
||||||
buffer_source,
|
create_buffer_source_with_length::<T>(cx, len as usize, array.handle_mut(), can_gc);
|
||||||
phantom: PhantomData,
|
if typed_array_result.is_err() {
|
||||||
},
|
return Err(Error::JSFailed);
|
||||||
HeapTypedArrayInit::Info { len, cx } => {
|
}
|
||||||
rooted!(in (*cx) let mut array = ptr::null_mut::<JSObject>());
|
|
||||||
let typed_array_result =
|
|
||||||
create_buffer_source_with_length::<T>(cx, len as usize, array.handle_mut(), can_gc);
|
|
||||||
if typed_array_result.is_err() {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapBufferSource::<T>::new(BufferSource::ArrayBufferView(Heap::boxed(*array.handle())))
|
Ok(HeapBufferSource::<T>::new(BufferSource::ArrayBufferView(
|
||||||
},
|
Heap::boxed(*array.handle()),
|
||||||
};
|
)))
|
||||||
Ok(heap_buffer_source)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) enum HeapTypedArrayInit {
|
|
||||||
Buffer(BufferSource),
|
|
||||||
Info { len: u32, cx: JSContext },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct HeapBufferSource<T> {
|
pub(crate) struct HeapBufferSource<T> {
|
||||||
|
@ -131,11 +120,11 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_view(
|
pub(crate) fn from_view(
|
||||||
chunk: CustomAutoRooterGuard<ArrayBufferView>,
|
chunk: CustomAutoRooterGuard<TypedArray<T, *mut JSObject>>,
|
||||||
) -> HeapBufferSource<ArrayBufferViewU8> {
|
) -> HeapBufferSource<T> {
|
||||||
HeapBufferSource::<ArrayBufferViewU8>::new(BufferSource::ArrayBufferView(Heap::boxed(
|
HeapBufferSource::<T>::new(BufferSource::ArrayBufferView(Heap::boxed(unsafe {
|
||||||
unsafe { *chunk.underlying_object() },
|
*chunk.underlying_object()
|
||||||
)))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn default() -> Self {
|
pub(crate) fn default() -> Self {
|
||||||
|
|
|
@ -9,13 +9,13 @@ use std::vec::Vec;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::default::{Rect, Size2D};
|
use euclid::default::{Rect, Size2D};
|
||||||
use ipc_channel::ipc::IpcSharedMemory;
|
use ipc_channel::ipc::IpcSharedMemory;
|
||||||
use js::jsapi::{Heap, JSObject};
|
use js::gc::CustomAutoRooterGuard;
|
||||||
|
use js::jsapi::JSObject;
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
use js::typedarray::{ClampedU8, CreateWith, Uint8ClampedArray};
|
use js::typedarray::{ClampedU8, CreateWith, Uint8ClampedArray};
|
||||||
|
|
||||||
use super::bindings::buffer_source::{
|
use super::bindings::buffer_source::{HeapBufferSource, create_heap_buffer_source_with_length};
|
||||||
BufferSource, HeapBufferSource, HeapTypedArrayInit, new_initialized_heap_buffer_source,
|
use crate::dom::bindings::buffer_source::create_buffer_source;
|
||||||
};
|
|
||||||
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::ImageDataMethods;
|
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::ImageDataMethods;
|
||||||
use crate::dom::bindings::error::{Error, Fallible};
|
use crate::dom::bindings::error::{Error, Fallible};
|
||||||
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object_with_proto};
|
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::<JSObject>());
|
rooted!(in (*cx) let mut js_object = ptr::null_mut::<JSObject>());
|
||||||
if let Some(ref mut d) = data {
|
if let Some(ref mut d) = data {
|
||||||
d.resize(len as usize, 0);
|
d.resize(len as usize, 0);
|
||||||
|
|
||||||
|
let typed_array =
|
||||||
|
create_buffer_source::<ClampedU8>(cx, &d[..], js_object.handle_mut(), can_gc)
|
||||||
|
.map_err(|_| Error::JSFailed)?;
|
||||||
|
|
||||||
let data = CreateWith::Slice(&d[..]);
|
let data = CreateWith::Slice(&d[..]);
|
||||||
Uint8ClampedArray::create(*cx, data, js_object.handle_mut()).unwrap();
|
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 {
|
} else {
|
||||||
Self::new_without_jsobject(global, None, width, height, can_gc)
|
Self::new_without_data(global, None, width, height, can_gc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn new_with_jsobject(
|
fn new_with_data(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
proto: Option<HandleObject>,
|
proto: Option<HandleObject>,
|
||||||
width: u32,
|
width: u32,
|
||||||
opt_height: Option<u32>,
|
opt_height: Option<u32>,
|
||||||
jsobject: *mut JSObject,
|
data: CustomAutoRooterGuard<Uint8ClampedArray>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Fallible<DomRoot<ImageData>> {
|
) -> Fallible<DomRoot<ImageData>> {
|
||||||
let heap_typed_array = match new_initialized_heap_buffer_source::<ClampedU8>(
|
let heap_typed_array = HeapBufferSource::<ClampedU8>::from_view(data);
|
||||||
HeapTypedArrayInit::Buffer(BufferSource::ArrayBufferView(Heap::boxed(jsobject))),
|
|
||||||
can_gc,
|
|
||||||
) {
|
|
||||||
Ok(heap_typed_array) => heap_typed_array,
|
|
||||||
Err(_) => return Err(Error::JSFailed),
|
|
||||||
};
|
|
||||||
|
|
||||||
let typed_array = match heap_typed_array.get_typed_array() {
|
let typed_array = match heap_typed_array.get_typed_array() {
|
||||||
Ok(array) => array,
|
Ok(array) => array,
|
||||||
|
@ -117,13 +117,14 @@ impl ImageData {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_without_jsobject(
|
fn new_without_data(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
proto: Option<HandleObject>,
|
proto: Option<HandleObject>,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Fallible<DomRoot<ImageData>> {
|
) -> Fallible<DomRoot<ImageData>> {
|
||||||
|
// If one or both of sw and sh are zero, then throw an "IndexSizeError" DOMException.
|
||||||
if width == 0 || height == 0 {
|
if width == 0 || height == 0 {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
|
@ -139,13 +140,8 @@ impl ImageData {
|
||||||
|
|
||||||
let cx = GlobalScope::get_cx();
|
let cx = GlobalScope::get_cx();
|
||||||
|
|
||||||
let heap_typed_array = match new_initialized_heap_buffer_source::<ClampedU8>(
|
let heap_typed_array = create_heap_buffer_source_with_length::<ClampedU8>(cx, len, can_gc)?;
|
||||||
HeapTypedArrayInit::Info { len, cx },
|
|
||||||
can_gc,
|
|
||||||
) {
|
|
||||||
Ok(heap_typed_array) => heap_typed_array,
|
|
||||||
Err(_) => return Err(Error::JSFailed),
|
|
||||||
};
|
|
||||||
let imagedata = Box::new(ImageData {
|
let imagedata = Box::new(ImageData {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
width,
|
width,
|
||||||
|
@ -198,20 +194,19 @@ impl ImageDataMethods<crate::DomTypeHolder> for ImageData {
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Fallible<DomRoot<Self>> {
|
) -> Fallible<DomRoot<Self>> {
|
||||||
Self::new_without_jsobject(global, proto, width, height, can_gc)
|
Self::new_without_data(global, proto, width, height, can_gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#dom-imagedata-with-data>
|
/// <https://html.spec.whatwg.org/multipage/#dom-imagedata-with-data>
|
||||||
fn Constructor_(
|
fn Constructor_(
|
||||||
_cx: JSContext,
|
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
proto: Option<HandleObject>,
|
proto: Option<HandleObject>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
jsobject: *mut JSObject,
|
data: CustomAutoRooterGuard<Uint8ClampedArray>,
|
||||||
width: u32,
|
width: u32,
|
||||||
opt_height: Option<u32>,
|
opt_height: Option<u32>,
|
||||||
) -> Fallible<DomRoot<Self>> {
|
) -> Fallible<DomRoot<Self>> {
|
||||||
Self::new_with_jsobject(global, proto, width, opt_height, jsobject, can_gc)
|
Self::new_with_data(global, proto, width, opt_height, data, can_gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#dom-imagedata-width>
|
/// <https://html.spec.whatwg.org/multipage/#dom-imagedata-width>
|
||||||
|
|
|
@ -254,7 +254,7 @@ interface CanvasPattern {
|
||||||
Serializable]
|
Serializable]
|
||||||
interface ImageData {
|
interface ImageData {
|
||||||
[Throws] constructor(unsigned long sw, unsigned long sh/*, optional ImageDataSettings settings = {}*/);
|
[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 = {}*/);
|
/*, optional ImageDataSettings settings = {}*/);
|
||||||
|
|
||||||
readonly attribute unsigned long width;
|
readonly attribute unsigned long width;
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[2d.imageData.object.ctor.basics.html]
|
|
||||||
[Testing different type of ImageData constructor]
|
|
||||||
expected: FAIL
|
|
Loading…
Add table
Add a link
Reference in a new issue