mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-03-09 21:47:00 -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:
parent
601fed8d2a
commit
acba887fa4
3 changed files with 60 additions and 1 deletions
|
@ -41,6 +41,7 @@ extern "C" {
|
||||||
this: *const ArrayBuffer,
|
this: *const ArrayBuffer,
|
||||||
key: *const Value,
|
key: *const Value,
|
||||||
) -> MaybeBool;
|
) -> MaybeBool;
|
||||||
|
fn v8__ArrayBuffer__SetDetachKey(this: *const ArrayBuffer, key: *const Value);
|
||||||
fn v8__ArrayBuffer__Data(this: *const ArrayBuffer) -> *mut c_void;
|
fn v8__ArrayBuffer__Data(this: *const ArrayBuffer) -> *mut c_void;
|
||||||
fn v8__ArrayBuffer__IsDetachable(this: *const ArrayBuffer) -> bool;
|
fn v8__ArrayBuffer__IsDetachable(this: *const ArrayBuffer) -> bool;
|
||||||
fn v8__ArrayBuffer__WasDetached(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,
|
/// Detaching sets the byte length of the buffer and all typed arrays to zero,
|
||||||
/// preventing JavaScript from ever accessing underlying backing store.
|
/// preventing JavaScript from ever accessing underlying backing store.
|
||||||
/// ArrayBuffer should have been externalized and must be detachable. Returns
|
/// 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.
|
/// and `Some(true)` otherwise.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn detach(&self, key: Local<Value>) -> Option<bool> {
|
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().
|
/// More efficient shortcut for GetBackingStore()->Data().
|
||||||
/// The returned pointer is valid as long as the ArrayBuffer is alive.
|
/// The returned pointer is valid as long as the ArrayBuffer is alive.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -835,6 +835,11 @@ bool v8__ArrayBuffer__WasDetached(const v8::ArrayBuffer& self) {
|
||||||
return v8::Utils::OpenHandle(&self)->was_detached();
|
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) {
|
void* v8__BackingStore__Data(const v8::BackingStore& self) {
|
||||||
return self.Data();
|
return self.Data();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8524,3 +8524,50 @@ fn test_fast_calls_callback_options_data() {
|
||||||
eval(scope, source).unwrap();
|
eval(scope, source).unwrap();
|
||||||
assert!(unsafe { DATA });
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue