Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebIDL: Use Uint8ClampedArray instead of raw JSObject in bindings #31317

Conversation

Taym95
Copy link
Contributor

@Taym95 Taym95 commented Feb 11, 2024

Part #31064, we would like to remove the direct use of unsafe NonNull<JSObject>, and replace it with use of the appropriate safe wrapper found in typedarray.rs, in this PR we are replacing unsafe NonNull<JSObject> with Uint8ClampedArray , according to spec


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • These changes do not require tests because there is not behavior change

Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Copy link
Member

@gterzian gterzian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contrib again! Let's change the new_initialized method a bit.

@@ -31,6 +31,16 @@ where
T: TypedArrayElement + TypedArrayElementCreator,
T::Element: Clone + Copy,
{
pub fn new_initialized(js_object: Option<*mut JSObject>) -> HeapTypedArray<T> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So let's add an pub enum like so:

HeapTypedArrayInit {
    Object(*mut JSObject),
     Info {
         len: usize
     }
}

And let's make it the init argument to this method.

The Info variant should be creating the array using a rooted object and call create_typed_array_with_length(which should be private).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re the Object variant, I hope it can be typed later as a result of doing #31320

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much better, I updated the code, thanks

Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Copy link
Member

@gterzian gterzian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contrib! Couple of changes suggested...

fn Data(&self, _: JSContext) -> Uint8ClampedArray {
self.data
.get_internal()
.expect("Failed to get Data from ImageData.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's return JsError as we did in the other PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we do it for other changes we merged, we have lot of .get_internal().expect ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, but it depends on the spec. It would be good to do this in a separate PR so each cases can be investigated separately(it may require updating test expectations also).

Copy link
Contributor Author

@Taym95 Taym95 Feb 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we only return error when function returns Fallible but not in this case?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes! Although we can check the spec to see if the function should be fallible...

Copy link
Contributor Author

@Taym95 Taym95 Feb 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the spec, I Don't see Data fallible, what do you think?

Copy link
Member

@gterzian gterzian Feb 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec doesn't say it direclty, but wording like "initialize the data attribute of imageData to a new Uint8ClampedArray object" implies using the Web IDL and JS operations which are in fact fallible.

Let's return JsError, by adding the Throws attribute to

readonly attribute Uint8ClampedArray data;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

.expect("Creating TypedArray from length should never fail");
let heap_typed_array = HeapTypedArray::<T>::default();
heap_typed_array
.set_data(cx, unsafe { typed_array.as_slice() })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unsafe is unnecessary, because the entire module allows it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still get this operation is unsafe and requires an unsafe function or block when I remove it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it's better to keep unsafe here instead of using it in new_with_jsobject

Copy link
Member

@gterzian gterzian Feb 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yes sorry, you need unsafe blocks for unsafe calls(but there is no need to mark the method as allowing unsafe, which is what I had in mind somehow).

create_typed_array_with_length::<T>(cx, len as usize, array.handle_mut())
.expect("Creating TypedArray from length should never fail");
let heap_typed_array = HeapTypedArray::<T>::default();
heap_typed_array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can simply do heap_typed_array.internal.set(*typed_array)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes heap_typed_array.internal.set(*array) should be okey

let array = array_res.map_err(|_| {
let heap_typed_array =
new_initialized_heap_typed_array(HeapTypedArrayInit::Object(jsobject));
let array = heap_typed_array.acquire_data(cx).map_err(|_| {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

acquire_data detaches the buffer, so instead we want to use get_internal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed thanks, fixed

Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Copy link
Member

@gterzian gterzian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few last changes!

fn Data(&self, _: JSContext) -> Uint8ClampedArray {
self.data
.get_internal()
.expect("Failed to get Data from ImageData.")
Copy link
Member

@gterzian gterzian Feb 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec doesn't say it direclty, but wording like "initialize the data attribute of imageData to a new Uint8ClampedArray object" implies using the Web IDL and JS operations which are in fact fallible.

Let's return JsError, by adding the Throws attribute to

readonly attribute Uint8ClampedArray data;

@@ -31,6 +31,32 @@ unsafe impl<T> crate::dom::bindings::trace::JSTraceable for HeapTypedArray<T> {
}
}

pub fn new_initialized_heap_typed_array<T>(init: HeapTypedArrayInit) -> HeapTypedArray<T>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's return a result, and return the error from create_typed_array_with_length. (creating the buffer is falling, as we saw in the other PR).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

…array

Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Copy link
Member

@gterzian gterzian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! LGTM with just one nit...

components/script/dom/bindings/typedarrays.rs Outdated Show resolved Hide resolved
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Copy link
Member

@gterzian gterzian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, thanks!

@gterzian
Copy link
Member

I'll add it to the queue, although it may require a rebase.

@gterzian gterzian added this pull request to the merge queue Feb 16, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to a conflict with the base branch Feb 16, 2024
@mrobinson mrobinson added this pull request to the merge queue Feb 16, 2024
Merged via the queue into servo:main with commit 328c376 Feb 16, 2024
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants