From 34fb380ed38ff324202b7779ae850edab133e577 Mon Sep 17 00:00:00 2001 From: Marcos Casagrande Date: Tue, 25 Oct 2022 14:22:37 +0200 Subject: feat(ext/web): use ArrayBuffer.was_detached() (#16307) This PR adds a way to reliably check if an ArrayBuffer was detached --- core/ops_builtin_v8.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'core/ops_builtin_v8.rs') diff --git a/core/ops_builtin_v8.rs b/core/ops_builtin_v8.rs index c04fe3400..818ba03ee 100644 --- a/core/ops_builtin_v8.rs +++ b/core/ops_builtin_v8.rs @@ -1,5 +1,6 @@ // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. use crate::bindings::script_origin; +use crate::error::custom_error; use crate::error::is_instance_of_error; use crate::error::range_error; use crate::error::type_error; @@ -51,6 +52,7 @@ pub(crate) fn init_builtins_v8() -> Vec { op_store_pending_promise_exception::decl(), op_remove_pending_promise_exception::decl(), op_has_pending_promise_exception::decl(), + op_arraybuffer_was_detached::decl(), ] } @@ -448,22 +450,27 @@ fn op_serialize( if let Some(transferred_array_buffers) = transferred_array_buffers { let state_rc = JsRuntime::state(scope); let state = state_rc.borrow_mut(); - for i in 0..transferred_array_buffers.length() { - let i = v8::Number::new(scope, i as f64).into(); + for index in 0..transferred_array_buffers.length() { + let i = v8::Number::new(scope, index as f64).into(); let buf = transferred_array_buffers.get(scope, i).unwrap(); let buf = v8::Local::::try_from(buf).map_err(|_| { type_error("item in transferredArrayBuffers not an ArrayBuffer") })?; if let Some(shared_array_buffer_store) = &state.shared_array_buffer_store { - // TODO(lucacasonato): we need to check here that the buffer is not - // already detached. We can not do that because V8 does not provide - // a way to check if a buffer is already detached. if !buf.is_detachable() { return Err(type_error( "item in transferredArrayBuffers is not transferable", )); } + + if buf.was_detached() { + return Err(custom_error( + "DOMExceptionOperationError", + format!("ArrayBuffer at index {} is already detached", index), + )); + } + let backing_store = buf.get_backing_store(); buf.detach(); let id = shared_array_buffer_store.insert(backing_store); @@ -877,3 +884,12 @@ fn op_has_pending_promise_exception<'a>( .pending_promise_exceptions .contains_key(&promise_global) } + +#[op(v8)] +fn op_arraybuffer_was_detached<'a>( + _scope: &mut v8::HandleScope<'a>, + input: serde_v8::Value<'a>, +) -> Result { + let ab = v8::Local::::try_from(input.v8_value)?; + Ok(ab.was_detached()) +} -- cgit v1.2.3