0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2025-02-02 04:37:35 -05:00

add v8::SharedArrayBuffer (#134)

This commit is contained in:
Andy Finch 2019-12-28 16:29:42 -05:00 committed by Ry Dahl
parent 5284abdab0
commit 00d592cd4d
5 changed files with 142 additions and 2 deletions

View file

@ -28,6 +28,7 @@ extern "C" {
isolate: *mut Isolate,
byte_length: usize,
) -> *mut BackingStore;
fn v8__BackingStore__Data(self_: &mut BackingStore) -> *mut std::ffi::c_void;
fn v8__BackingStore__ByteLength(self_: &BackingStore) -> usize;
fn v8__BackingStore__IsShared(self_: &BackingStore) -> bool;
fn v8__BackingStore__DELETE(self_: &mut BackingStore);
@ -98,11 +99,21 @@ impl Delete for Allocator {
pub struct BackingStore([usize; 6]);
impl BackingStore {
/// Returns a rust u8 slice with a lifetime equal to the lifetime of the BackingStore.
pub fn data_bytes<'a>(&'a mut self) -> &'a mut [u8] {
unsafe {
std::slice::from_raw_parts_mut::<'a, u8>(
v8__BackingStore__Data(self) as *mut u8,
self.byte_length(),
)
}
}
/// Return a pointer to the beginning of the memory block for this backing
/// store. The pointer is only valid as long as this backing store object
/// lives.
pub fn data(&self) -> std::ffi::c_void {
unimplemented!()
pub fn data(&mut self) -> &mut std::ffi::c_void {
unsafe { &mut *v8__BackingStore__Data(self) }
}
/// The length (in bytes) of this backing store.

View file

@ -335,6 +335,10 @@ two_pointers_t v8__ArrayBuffer__GetBackingStore(v8::ArrayBuffer& self) {
return make_pod<two_pointers_t>(self.GetBackingStore());
}
void* v8__BackingStore__Data(v8::BackingStore& self) {
return self.Data();
}
size_t v8__BackingStore__ByteLength(v8::BackingStore& self) {
return self.ByteLength();
}
@ -682,6 +686,18 @@ v8::PrimitiveArray* v8__ScriptOrModule__GetHostDefinedOptions(
return local_to_ptr(self.GetHostDefinedOptions());
}
v8::SharedArrayBuffer* v8__SharedArrayBuffer__New(v8::Isolate* isolate, size_t byte_length) {
return local_to_ptr(v8::SharedArrayBuffer::New(isolate, byte_length));
}
size_t v8__SharedArrayBuffer__ByteLength(v8::SharedArrayBuffer& self) {
return self.ByteLength();
}
two_pointers_t v8__SharedArrayBuffer__GetBackingStore(v8::SharedArrayBuffer& self) {
return make_pod<two_pointers_t>(self.GetBackingStore());
}
v8::Value* v8__JSON__Parse(v8::Local<v8::Context> context,
v8::Local<v8::String> json_string) {
return maybe_local_to_ptr(v8::JSON::Parse(context, json_string));

View file

@ -61,6 +61,7 @@ mod promise;
mod property;
mod script;
mod script_or_module;
mod shared_array_buffer;
mod snapshot;
mod string;
mod support;
@ -104,6 +105,7 @@ pub use promise::{
pub use property::PropertyCallbackInfo;
pub use script::{Script, ScriptOrigin};
pub use script_or_module::ScriptOrModule;
pub use shared_array_buffer::SharedArrayBuffer;
pub use snapshot::{FunctionCodeHandling, SnapshotCreator, StartupData};
pub use string::NewStringType;
pub use string::String;

View file

@ -0,0 +1,62 @@
use std::ops::Deref;
use crate::support::Opaque;
use crate::support::SharedRef;
use crate::BackingStore;
use crate::Isolate;
use crate::Local;
use crate::ToLocal;
use crate::Value;
extern "C" {
fn v8__SharedArrayBuffer__New(
isolate: *mut Isolate,
byte_length: usize,
) -> *mut SharedArrayBuffer;
fn v8__SharedArrayBuffer__ByteLength(
self_: *const SharedArrayBuffer,
) -> usize;
fn v8__SharedArrayBuffer__GetBackingStore(
self_: *const SharedArrayBuffer,
) -> SharedRef<BackingStore>;
}
/// An instance of the built-in SharedArrayBuffer constructor.
/// This API is experimental and may change significantly.
#[repr(C)]
pub struct SharedArrayBuffer(Opaque);
impl SharedArrayBuffer {
/// Create a new SharedArrayBuffer. Allocate |byte_length| bytes.
/// Allocated memory will be owned by a created SharedArrayBuffer and
/// will be deallocated when it is garbage-collected,
/// unless the object is externalized.
pub fn new<'sc>(
scope: &mut impl ToLocal<'sc>,
byte_length: usize,
) -> Option<Local<'sc, SharedArrayBuffer>> {
unsafe {
Local::from_raw(v8__SharedArrayBuffer__New(scope.isolate(), byte_length))
}
}
/// Data length in bytes.
pub fn byte_length(&self) -> usize {
unsafe { v8__SharedArrayBuffer__ByteLength(self) }
}
/// Get a shared pointer to the backing store of this array buffer. This
/// pointer coordinates the lifetime management of the internal storage
/// with any live ArrayBuffers on the heap, even across isolates. The embedder
/// should not attempt to manage lifetime of the storage through other means.
pub fn get_backing_store(&self) -> SharedRef<BackingStore> {
unsafe { v8__SharedArrayBuffer__GetBackingStore(self) }
}
}
impl Deref for SharedArrayBuffer {
type Target = Value;
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const _ as *const Value) }
}
}

View file

@ -1491,3 +1491,52 @@ fn dynamic_import() {
isolate.exit();
drop(g);
}
#[test]
fn shared_array_buffer() {
let g = setup();
let mut params = v8::Isolate::create_params();
params.set_array_buffer_allocator(v8::new_default_allocator());
let mut isolate = v8::Isolate::new(params);
isolate.enter();
let mut locker = v8::Locker::new(&isolate);
{
let mut hs = v8::HandleScope::new(&mut locker);
let s = hs.enter();
let mut context = v8::Context::new(s);
context.enter();
let maybe_sab = v8::SharedArrayBuffer::new(s, 16);
assert!(maybe_sab.is_some());
let sab = maybe_sab.unwrap();
let mut backing_store = sab.get_backing_store();
let shared_buf = backing_store.data_bytes();
shared_buf[5] = 12;
shared_buf[12] = 52;
let global = context.global(s);
assert_eq!(
global.create_data_property(
context,
cast(v8_str(s, "shared")),
cast(sab)
),
v8::MaybeBool::JustTrue
);
let source = v8::String::new(
s,
"sharedBytes = new Uint8Array(shared); sharedBytes[2] = 16; sharedBytes[14] = 62; sharedBytes[5] + sharedBytes[12]",
)
.unwrap();
let mut script = v8::Script::compile(s, context, source, None).unwrap();
source.to_rust_string_lossy(s);
let result = script.run(s, context).unwrap();
// TODO: safer casts.
let result: v8::Local<v8::Integer> = cast(result);
assert_eq!(result.value(), 64);
assert_eq!(shared_buf[2], 16);
assert_eq!(shared_buf[14], 62);
context.exit();
}
drop(locker);
isolate.exit();
drop(g);
}