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:
parent
601fed8d2a
commit
acba887fa4
3 changed files with 60 additions and 1 deletions
|
@ -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)]
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue