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

feat(ext/web): use ArrayBuffer.was_detached() #16307

Merged
merged 6 commits into from
Oct 25, 2022

Conversation

marcosc90
Copy link
Contributor

This PR adds a way to reliably check if an ArrayBuffer was detached

Blocked by: denoland/rusty_v8#1103

ext/web/lib.rs Outdated
Comment on lines 341 to 349
#[op(v8)]
fn op_arraybuffer_was_detached<'a>(
_scope: &mut v8::HandleScope<'a>,
input: serde_v8::Value<'a>,
) -> Result<bool, AnyError> {
let ab = v8::Local::<v8::ArrayBuffer>::try_from(input.v8_value)?;
Ok(ab.was_detached())
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Why not make this a function in Deno.core, like Deno.core.isProxy?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Like this?

isProxy: (value) => ops.op_is_proxy(value),

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah. The op would have to be moved to core/ops_builtin_v8.rs.

@bartlomieju
Copy link
Member

@marcosc90 you should be now unblocked on this PR after rebasing against main

@marcosc90 marcosc90 marked this pull request as ready for review October 20, 2022 19:04
@bartlomieju bartlomieju self-requested a review October 20, 2022 19:06
// TODO(marcosc90) remove isFakeDetached once transferArrayBuffer
// actually detaches the buffer
return ReflectHas(O, isFakeDetached) ||
core.ops.op_arraybuffer_was_detached(O);
Copy link
Contributor Author

@marcosc90 marcosc90 Oct 20, 2022

Choose a reason for hiding this comment

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

This can be changed after is merged #16294 to:

return core.ops.op_arraybuffer_was_detached(O);

core/01_core.js Outdated
@@ -364,6 +364,7 @@
eventLoopHasMoreWork: () => ops.op_event_loop_has_more_work(),
setPromiseRejectCallback: (fn) => ops.op_set_promise_reject_callback(fn),
byteLength: (str) => ops.op_str_byte_length(str),
arrayBufferWasDetached: (ab) => ops.op_arraybuffer_was_detached(ab),
Copy link
Member

Choose a reason for hiding this comment

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

This is not needed, since you're calling it like core.ops.op_arraybuffer_was_detached in code. Feel free to 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.

Done! I added it because it was proposed by Andreu #16307 (comment)

To be honest, I'm not sure what's the reason for exposing some methods to Deno.core if almost all of them are available in Deno.core.ops, couldn't find any info about the reasoning, AFAIK those APIs are not documented, although they're publicly exposed.

Copy link
Member

Choose a reason for hiding this comment

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

It's legacy stuff, that was left to not break deno_std. We should really fix this...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good to know, thanks!

@bartlomieju bartlomieju added this to the 1.27 milestone Oct 22, 2022
Comment on lines +246 to +256
for (let i = 0, j = 0; i < transferables.length; i++) {
const ab = transferables[i];
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, ab)) {
if (ab.byteLength === 0 && core.ops.op_arraybuffer_was_detached(ab)) {
throw new DOMException(
`ArrayBuffer at index ${j} is already detached`,
"DataCloneError",
);
}
j++;
transferredArrayBuffers.push(ab);
Copy link
Member

@lucacasonato lucacasonato Oct 24, 2022

Choose a reason for hiding this comment

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

Suggested change
for (let i = 0, j = 0; i < transferables.length; i++) {
const ab = transferables[i];
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, ab)) {
if (ab.byteLength === 0 && core.ops.op_arraybuffer_was_detached(ab)) {
throw new DOMException(
`ArrayBuffer at index ${j} is already detached`,
"DataCloneError",
);
}
j++;
transferredArrayBuffers.push(ab);
for (let i = 0; i < transferables.length; i++) {
const ab = transferables[i];
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, ab)) {
if (ab.byteLength === 0 && core.ops.op_arraybuffer_was_detached(ab)) {
throw new DOMException(
`ArrayBuffer at index ${i} is already detached`,
"DataCloneError",
);
}
transferredArrayBuffers.push(ab);

The user doesn't care about the index of the AB, they care about the index in the transferables 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.

@lucacasonato Wanted to mimic Chrome error message.

const buf = new Uint8Array(5);
structuredClone(buf, { transfer: [buf.buffer] });
structuredClone([buf.buffer], { transfer: [new ReadableStream(), buf.buffer] });
// Uncaught DOMException: ... ArrayBuffer at index 0 is already detached

Also did it that way to make JS error be the same as Rust's where we're looping through AB list, not transferables

format!("ArrayBuffer at index {} is already detached", index),

Since we're not passing the transferables array to Rust, should I just remove the index hint, and leave the old message: Can not transfer detached ArrayBuffer?

Copy link
Member

Choose a reason for hiding this comment

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

Okay, I think mimicing Chrome is fine here.

Copy link
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

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

LGTM, thanks @marcosc90!

@bartlomieju bartlomieju merged commit 34fb380 into denoland:main Oct 25, 2022
@marcosc90 marcosc90 deleted the arraybuffer_was_detached branch October 25, 2022 16:39
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

4 participants