0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2025-03-09 13:38:51 -04:00

Add ArrayBuffer::set_detach_key (#1127)

This method, introduced in V8 10.9, makes it so an `ArrayBuffer`
object is impossible to detach unless a specific detach key is passed
to the `detach` method. Such `ArrayBuffer`s still count as detachable
as per the `ArrayBuffer::is_detachable` method, but otherwise behave
much like WebAssembly memories.
This commit is contained in:
Andreu Botella 2022-11-21 12:46:57 +01:00 committed by GitHub
parent 601fed8d2a
commit acba887fa4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 1 deletions

View file

@ -41,6 +41,7 @@ extern "C" {
this: *const ArrayBuffer,
key: *const Value,
) -> MaybeBool;
fn v8__ArrayBuffer__SetDetachKey(this: *const ArrayBuffer, key: *const Value);
fn v8__ArrayBuffer__Data(this: *const ArrayBuffer) -> *mut c_void;
fn v8__ArrayBuffer__IsDetachable(this: *const ArrayBuffer) -> bool;
fn v8__ArrayBuffer__WasDetached(this: *const ArrayBuffer) -> bool;
@ -408,7 +409,7 @@ impl ArrayBuffer {
/// Detaching sets the byte length of the buffer and all typed arrays to zero,
/// preventing JavaScript from ever accessing underlying backing store.
/// ArrayBuffer should have been externalized and must be detachable. Returns
/// `None` if the key didn't pass the [[ArrayBufferDetachKey]] check,
/// `None` if the key didn't pass the `[[ArrayBufferDetachKey]]` check,
/// and `Some(true)` otherwise.
#[inline(always)]
pub fn detach(&self, key: Local<Value>) -> Option<bool> {
@ -421,6 +422,12 @@ impl ArrayBuffer {
}
}
/// Sets the `[[ArrayBufferDetachKey]]`.
#[inline(always)]
pub fn set_detach_key(&self, key: Local<Value>) {
unsafe { v8__ArrayBuffer__SetDetachKey(self, &*key) };
}
/// More efficient shortcut for GetBackingStore()->Data().
/// The returned pointer is valid as long as the ArrayBuffer is alive.
#[inline(always)]

View file

@ -835,6 +835,11 @@ bool v8__ArrayBuffer__WasDetached(const v8::ArrayBuffer& self) {
return v8::Utils::OpenHandle(&self)->was_detached();
}
void v8__ArrayBuffer__SetDetachKey(const v8::ArrayBuffer& self,
const v8::Value* key) {
return ptr_to_local(&self)->SetDetachKey(ptr_to_local(key));
}
void* v8__BackingStore__Data(const v8::BackingStore& self) {
return self.Data();
}

View file

@ -8524,3 +8524,50 @@ fn test_fast_calls_callback_options_data() {
eval(scope, source).unwrap();
assert!(unsafe { DATA });
}
#[test]
fn test_detach_key() {
let _setup_guard = setup();
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
// Object detach key
{
let detach_key = eval(scope, "({})").unwrap();
assert!(detach_key.is_object());
let buffer = v8::ArrayBuffer::new(scope, 1024);
buffer.set_detach_key(detach_key);
assert!(buffer.is_detachable());
assert_eq!(buffer.detach(v8::undefined(scope).into()), None);
assert!(!buffer.was_detached());
assert_eq!(buffer.detach(detach_key), Some(true));
assert!(buffer.was_detached());
}
// External detach key
{
let mut rust_detach_key = Box::new(42usize);
let v8_detach_key = v8::External::new(
scope,
&mut *rust_detach_key as *mut usize as *mut c_void,
);
let buffer = v8::ArrayBuffer::new(scope, 1024);
buffer.set_detach_key(v8_detach_key.into());
assert!(buffer.is_detachable());
assert_eq!(buffer.detach(v8::undefined(scope).into()), None);
assert!(!buffer.was_detached());
assert_eq!(buffer.detach(v8_detach_key.into()), Some(true));
assert!(buffer.was_detached());
}
// Undefined detach key
{
let buffer = v8::ArrayBuffer::new(scope, 1024);
buffer.set_detach_key(v8::undefined(scope).into());
assert!(buffer.is_detachable());
assert_eq!(buffer.detach(v8::undefined(scope).into()), Some(true));
assert!(buffer.was_detached());
}
}