0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-25 15:29:43 -05:00

Allow ValueSerializerImpl and ValueDeserializerImpl impls to be re-entrant (#1591)

Currently, if you were to call (for instance) write_value as part of a custom write_host_object implementation, you would be forced to create aliased exclusive references to the serializer (which is instant UB).

The underlying v8 de/serializers are re-entrant, so for the most part we simply need to pass around shared references instead of exclusive references.

Also adds some bindings to some missing functions, and makes ValueSerializer (and deserializer) garbage collectable.
This commit is contained in:
Nathan Whitaker 2024-08-28 12:44:40 -07:00 committed by GitHub
parent 6a6064d9ff
commit 5989346753
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 360 additions and 269 deletions

View file

@ -3539,6 +3539,11 @@ void v8__ValueSerializer__Release(v8::ValueSerializer* self, uint8_t** ptr,
*size = result.second; *size = result.second;
} }
void v8__ValueSerializer__SetTreatArrayBufferViewsAsHostObjects(
v8::ValueSerializer* self, bool mode) {
self->SetTreatArrayBufferViewsAsHostObjects(mode);
}
void v8__ValueSerializer__WriteHeader(v8::ValueSerializer* self) { void v8__ValueSerializer__WriteHeader(v8::ValueSerializer* self) {
self->WriteHeader(); self->WriteHeader();
} }
@ -3678,6 +3683,11 @@ bool v8__ValueDeserializer__ReadRawBytes(v8::ValueDeserializer* self,
size_t length, const void** data) { size_t length, const void** data) {
return self->ReadRawBytes(length, data); return self->ReadRawBytes(length, data);
} }
uint32_t v8__ValueDeserializer__GetWireFormatVersion(
v8::ValueDeserializer* self) {
return self->GetWireFormatVersion();
}
} // extern "C" } // extern "C"
// v8::CompiledWasmModule // v8::CompiledWasmModule

View file

@ -1,6 +1,9 @@
use crate::ArrayBuffer; use crate::ArrayBuffer;
use crate::CallbackScope;
use crate::Context; use crate::Context;
use crate::ContextScope;
use crate::Exception; use crate::Exception;
use crate::Global;
use crate::HandleScope; use crate::HandleScope;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
@ -27,36 +30,37 @@ pub struct CxxValueDeserializerDelegate {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueDeserializer__Delegate__ReadHostObject( unsafe extern "C" fn v8__ValueDeserializer__Delegate__ReadHostObject(
this: &mut CxxValueDeserializerDelegate, this: &CxxValueDeserializerDelegate,
_isolate: *mut Isolate, isolate: *mut Isolate,
) -> *const Object { ) -> *const Object {
let value_deserializer_heap = ValueDeserializerHeap::dispatch_mut(this); let value_deserializer_heap = ValueDeserializerHeap::dispatch(this);
let scope = let scope = &mut CallbackScope::new(isolate.as_mut().unwrap());
&mut crate::scope::CallbackScope::new(value_deserializer_heap.context); let context = Local::new(scope, &value_deserializer_heap.context);
let value_deserializer_impl = let scope = &mut ContextScope::new(scope, context);
value_deserializer_heap.value_deserializer_impl.as_mut();
match value_deserializer_impl.read_host_object( match value_deserializer_heap
scope, .value_deserializer_impl
&mut value_deserializer_heap.cxx_value_deserializer, .read_host_object(scope, &value_deserializer_heap.cxx_value_deserializer)
) { {
None => std::ptr::null(), None => std::ptr::null(),
Some(x) => x.as_non_null().as_ptr(), Some(x) => x.as_non_null().as_ptr(),
} }
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueDeserializer__Delegate__GetSharedArrayBufferFromId( unsafe extern "C" fn v8__ValueDeserializer__Delegate__GetSharedArrayBufferFromId(
this: &mut CxxValueDeserializerDelegate, this: &CxxValueDeserializerDelegate,
_isolate: *mut Isolate, isolate: *mut Isolate,
transfer_id: u32, transfer_id: u32,
) -> *const SharedArrayBuffer { ) -> *const SharedArrayBuffer {
let value_deserializer_heap = ValueDeserializerHeap::dispatch_mut(this); let value_deserializer_heap = ValueDeserializerHeap::dispatch(this);
let scope = let scope = &mut CallbackScope::new(isolate.as_mut().unwrap());
&mut crate::scope::CallbackScope::new(value_deserializer_heap.context); let context = Local::new(scope, &value_deserializer_heap.context);
let value_deserializer_impl = let scope = &mut ContextScope::new(scope, context);
value_deserializer_heap.value_deserializer_impl.as_mut();
match value_deserializer_impl match value_deserializer_heap
.value_deserializer_impl
.get_shared_array_buffer_from_id(scope, transfer_id) .get_shared_array_buffer_from_id(scope, transfer_id)
{ {
None => std::ptr::null(), None => std::ptr::null(),
@ -65,17 +69,20 @@ pub unsafe extern "C" fn v8__ValueDeserializer__Delegate__GetSharedArrayBufferFr
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueDeserializer__Delegate__GetWasmModuleFromId( unsafe extern "C" fn v8__ValueDeserializer__Delegate__GetWasmModuleFromId(
this: &mut CxxValueDeserializerDelegate, this: &mut CxxValueDeserializerDelegate,
_isolate: *mut Isolate, isolate: *mut Isolate,
clone_id: u32, clone_id: u32,
) -> *const WasmModuleObject { ) -> *const WasmModuleObject {
let value_deserializer_heap = ValueDeserializerHeap::dispatch_mut(this); let value_deserializer_heap = ValueDeserializerHeap::dispatch(this);
let scope = let scope = &mut CallbackScope::new(isolate.as_mut().unwrap());
&mut crate::scope::CallbackScope::new(value_deserializer_heap.context); let context = Local::new(scope, &value_deserializer_heap.context);
let value_deserializer_impl = let scope = &mut ContextScope::new(scope, context);
value_deserializer_heap.value_deserializer_impl.as_mut();
match value_deserializer_impl.get_wasm_module_from_id(scope, clone_id) { match value_deserializer_heap
.value_deserializer_impl
.get_wasm_module_from_id(scope, clone_id)
{
None => std::ptr::null(), None => std::ptr::null(),
Some(x) => x.as_non_null().as_ptr(), Some(x) => x.as_non_null().as_ptr(),
} }
@ -146,15 +153,19 @@ extern "C" {
length: usize, length: usize,
data: *mut *const c_void, data: *mut *const c_void,
) -> bool; ) -> bool;
fn v8__ValueDeserializer__GetWireFormatVersion(
this: *mut CxxValueDeserializer,
) -> u32;
} }
/// The ValueDeserializerImpl trait allows for /// The ValueDeserializerImpl trait allows for
/// custom callback functions used by v8. /// custom callback functions used by v8.
pub trait ValueDeserializerImpl { pub trait ValueDeserializerImpl {
fn read_host_object<'s>( fn read_host_object<'s>(
&mut self, &self,
scope: &mut HandleScope<'s>, scope: &mut HandleScope<'s>,
_value_deserializer: &mut dyn ValueDeserializerHelper, _value_deserializer: &dyn ValueDeserializerHelper,
) -> Option<Local<'s, Object>> { ) -> Option<Local<'s, Object>> {
let msg = let msg =
String::new(scope, "Deno deserializer: read_host_object not implemented") String::new(scope, "Deno deserializer: read_host_object not implemented")
@ -165,7 +176,7 @@ pub trait ValueDeserializerImpl {
} }
fn get_shared_array_buffer_from_id<'s>( fn get_shared_array_buffer_from_id<'s>(
&mut self, &self,
scope: &mut HandleScope<'s>, scope: &mut HandleScope<'s>,
_transfer_id: u32, _transfer_id: u32,
) -> Option<Local<'s, SharedArrayBuffer>> { ) -> Option<Local<'s, SharedArrayBuffer>> {
@ -180,7 +191,7 @@ pub trait ValueDeserializerImpl {
} }
fn get_wasm_module_from_id<'s>( fn get_wasm_module_from_id<'s>(
&mut self, &self,
scope: &mut HandleScope<'s>, scope: &mut HandleScope<'s>,
_clone_id: u32, _clone_id: u32,
) -> Option<Local<'s, WasmModuleObject>> { ) -> Option<Local<'s, WasmModuleObject>> {
@ -195,6 +206,10 @@ pub trait ValueDeserializerImpl {
} }
} }
fn cast_to_ptr<T>(t: &T) -> *mut T {
t as *const _ as *mut _
}
/// The ValueDeserializerHeap object contains all objects related to a /// The ValueDeserializerHeap object contains all objects related to a
/// deserializer. This object has to be pinned to the heap because of the Cpp /// deserializer. This object has to be pinned to the heap because of the Cpp
/// pointers that have to remain valid. Moving this object would result in the /// pointers that have to remain valid. Moving this object would result in the
@ -202,14 +217,14 @@ pub trait ValueDeserializerImpl {
/// callback to fail. Additionally the deserializer and implementation are also /// callback to fail. Additionally the deserializer and implementation are also
/// pinned in memory because these have to be accessable from within the /// pinned in memory because these have to be accessable from within the
/// delegate callback methods. /// delegate callback methods.
pub struct ValueDeserializerHeap<'a, 's> { pub struct ValueDeserializerHeap<'a> {
value_deserializer_impl: Box<dyn ValueDeserializerImpl + 'a>, value_deserializer_impl: Box<dyn ValueDeserializerImpl + 'a>,
cxx_value_deserializer: CxxValueDeserializer, cxx_value_deserializer: CxxValueDeserializer,
cxx_value_deserializer_delegate: CxxValueDeserializerDelegate, cxx_value_deserializer_delegate: CxxValueDeserializerDelegate,
context: Local<'s, Context>, context: Global<Context>,
} }
impl<'a, 's> ValueDeserializerHeap<'a, 's> { impl<'a> ValueDeserializerHeap<'a> {
fn get_cxx_value_deserializer_delegate_offset( fn get_cxx_value_deserializer_delegate_offset(
) -> FieldOffset<CxxValueDeserializerDelegate> { ) -> FieldOffset<CxxValueDeserializerDelegate> {
let buf = std::mem::MaybeUninit::<Self>::uninit(); let buf = std::mem::MaybeUninit::<Self>::uninit();
@ -219,25 +234,15 @@ impl<'a, 's> ValueDeserializerHeap<'a, 's> {
} }
/// Starting from 'this' pointer a ValueDeserializerHeap ref can be created /// Starting from 'this' pointer a ValueDeserializerHeap ref can be created
#[allow(dead_code)]
pub unsafe fn dispatch( pub unsafe fn dispatch(
value_serializer_delegate: &'s CxxValueDeserializerDelegate, value_serializer_delegate: &CxxValueDeserializerDelegate,
) -> &Self { ) -> &Self {
Self::get_cxx_value_deserializer_delegate_offset() Self::get_cxx_value_deserializer_delegate_offset()
.to_embedder::<Self>(value_serializer_delegate) .to_embedder::<Self>(value_serializer_delegate)
} }
/// Starting from 'this' pointer the ValueDeserializerHeap mut ref can be
/// created
pub unsafe fn dispatch_mut(
value_serializer_delegate: &'s mut CxxValueDeserializerDelegate,
) -> &mut Self {
Self::get_cxx_value_deserializer_delegate_offset()
.to_embedder_mut::<Self>(value_serializer_delegate)
}
} }
impl<'a, 's> Drop for ValueDeserializerHeap<'a, 's> { impl<'a> Drop for ValueDeserializerHeap<'a> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
v8__ValueDeserializer__DESTRUCT(&mut self.cxx_value_deserializer) v8__ValueDeserializer__DESTRUCT(&mut self.cxx_value_deserializer)
@ -249,12 +254,12 @@ impl<'a, 's> Drop for ValueDeserializerHeap<'a, 's> {
/// Mostly used by the read_host_object callback function in the /// Mostly used by the read_host_object callback function in the
/// ValueDeserializerImpl trait to create custom deserialization logic. /// ValueDeserializerImpl trait to create custom deserialization logic.
pub trait ValueDeserializerHelper { pub trait ValueDeserializerHelper {
fn get_cxx_value_deserializer(&mut self) -> &mut CxxValueDeserializer; fn get_cxx_value_deserializer(&self) -> &CxxValueDeserializer;
fn read_header(&mut self, context: Local<Context>) -> Option<bool> { fn read_header(&self, context: Local<Context>) -> Option<bool> {
unsafe { unsafe {
v8__ValueDeserializer__ReadHeader( v8__ValueDeserializer__ReadHeader(
self.get_cxx_value_deserializer(), cast_to_ptr(self.get_cxx_value_deserializer()),
context, context,
) )
} }
@ -262,49 +267,49 @@ pub trait ValueDeserializerHelper {
} }
fn read_value<'s>( fn read_value<'s>(
&mut self, &self,
context: Local<'s, Context>, context: Local<'s, Context>,
) -> Option<Local<'s, Value>> { ) -> Option<Local<'s, Value>> {
unsafe { unsafe {
Local::from_raw(v8__ValueDeserializer__ReadValue( Local::from_raw(v8__ValueDeserializer__ReadValue(
self.get_cxx_value_deserializer(), cast_to_ptr(self.get_cxx_value_deserializer()),
context, context,
)) ))
} }
} }
fn read_uint32(&mut self, value: &mut u32) -> bool { fn read_uint32(&self, value: &mut u32) -> bool {
unsafe { unsafe {
v8__ValueDeserializer__ReadUint32( v8__ValueDeserializer__ReadUint32(
self.get_cxx_value_deserializer(), cast_to_ptr(self.get_cxx_value_deserializer()),
value, value,
) )
} }
} }
fn read_uint64(&mut self, value: &mut u64) -> bool { fn read_uint64(&self, value: &mut u64) -> bool {
unsafe { unsafe {
v8__ValueDeserializer__ReadUint64( v8__ValueDeserializer__ReadUint64(
self.get_cxx_value_deserializer(), cast_to_ptr(self.get_cxx_value_deserializer()),
value, value,
) )
} }
} }
fn read_double(&mut self, value: &mut f64) -> bool { fn read_double(&self, value: &mut f64) -> bool {
unsafe { unsafe {
v8__ValueDeserializer__ReadDouble( v8__ValueDeserializer__ReadDouble(
self.get_cxx_value_deserializer(), cast_to_ptr(self.get_cxx_value_deserializer()),
value, value,
) )
} }
} }
fn read_raw_bytes(&mut self, length: usize) -> Option<&[u8]> { fn read_raw_bytes(&self, length: usize) -> Option<&[u8]> {
let mut data: *const c_void = std::ptr::null_mut(); let mut data: *const c_void = std::ptr::null_mut();
let ok = unsafe { let ok = unsafe {
v8__ValueDeserializer__ReadRawBytes( v8__ValueDeserializer__ReadRawBytes(
self.get_cxx_value_deserializer(), cast_to_ptr(self.get_cxx_value_deserializer()),
length, length,
&mut data, &mut data,
) )
@ -318,35 +323,43 @@ pub trait ValueDeserializerHelper {
} }
fn transfer_array_buffer( fn transfer_array_buffer(
&mut self, &self,
transfer_id: u32, transfer_id: u32,
array_buffer: Local<ArrayBuffer>, array_buffer: Local<ArrayBuffer>,
) { ) {
unsafe { unsafe {
v8__ValueDeserializer__TransferArrayBuffer( v8__ValueDeserializer__TransferArrayBuffer(
self.get_cxx_value_deserializer(), cast_to_ptr(self.get_cxx_value_deserializer()),
transfer_id, transfer_id,
array_buffer, array_buffer,
) )
}; };
} }
fn get_wire_format_version(&self) -> u32 {
unsafe {
v8__ValueDeserializer__GetWireFormatVersion(cast_to_ptr(
self.get_cxx_value_deserializer(),
))
}
}
} }
impl ValueDeserializerHelper for CxxValueDeserializer { impl ValueDeserializerHelper for CxxValueDeserializer {
fn get_cxx_value_deserializer(&mut self) -> &mut CxxValueDeserializer { fn get_cxx_value_deserializer(&self) -> &CxxValueDeserializer {
self self
} }
} }
impl<'a, 's> ValueDeserializerHelper for ValueDeserializerHeap<'a, 's> { impl<'a> ValueDeserializerHelper for ValueDeserializerHeap<'a> {
fn get_cxx_value_deserializer(&mut self) -> &mut CxxValueDeserializer { fn get_cxx_value_deserializer(&self) -> &CxxValueDeserializer {
&mut self.cxx_value_deserializer &self.cxx_value_deserializer
} }
} }
impl<'a, 's> ValueDeserializerHelper for ValueDeserializer<'a, 's> { impl<'a> ValueDeserializerHelper for ValueDeserializer<'a> {
fn get_cxx_value_deserializer(&mut self) -> &mut CxxValueDeserializer { fn get_cxx_value_deserializer(&self) -> &CxxValueDeserializer {
&mut self.value_deserializer_heap.cxx_value_deserializer &self.value_deserializer_heap.cxx_value_deserializer
} }
} }
@ -355,18 +368,23 @@ impl<'a, 's> ValueDeserializerHelper for ValueDeserializer<'a, 's> {
/// The 'a lifetime is the lifetime of the ValueDeserializerImpl implementation. /// The 'a lifetime is the lifetime of the ValueDeserializerImpl implementation.
/// The 's lifetime is the lifetime of the HandleScope which is used to retrieve /// The 's lifetime is the lifetime of the HandleScope which is used to retrieve
/// a Local<'s, Context> for the CallbackScopes /// a Local<'s, Context> for the CallbackScopes
pub struct ValueDeserializer<'a, 's> { pub struct ValueDeserializer<'a> {
value_deserializer_heap: Pin<Box<ValueDeserializerHeap<'a, 's>>>, value_deserializer_heap: Pin<Box<ValueDeserializerHeap<'a>>>,
// ValueDeserializerHeap is already !Send and !Sync
// but this is just making it explicit
_phantom: std::marker::PhantomData<*mut ()>,
} }
impl<'a, 's> ValueDeserializer<'a, 's> { impl<'a> ValueDeserializer<'a> {
pub fn new<D: ValueDeserializerImpl + 'a>( pub fn new<D: ValueDeserializerImpl + 'a>(
scope: &mut HandleScope<'s>, scope: &mut HandleScope,
value_deserializer_impl: Box<D>, value_deserializer_impl: Box<D>,
data: &[u8], data: &[u8],
) -> Self { ) -> Self {
let context = scope.get_current_context();
// create dummy ValueDeserializerHeap and move to heap + pin to address // create dummy ValueDeserializerHeap and move to heap + pin to address
let mut value_deserializer_heap = Box::pin(ValueDeserializerHeap { let value_deserializer_heap_ptr =
Box::into_raw(Box::new(ValueDeserializerHeap {
value_deserializer_impl, value_deserializer_impl,
cxx_value_deserializer: CxxValueDeserializer { cxx_value_deserializer: CxxValueDeserializer {
_cxx_vtable: CxxVTable(std::ptr::null()), _cxx_vtable: CxxVTable(std::ptr::null()),
@ -374,48 +392,56 @@ impl<'a, 's> ValueDeserializer<'a, 's> {
cxx_value_deserializer_delegate: CxxValueDeserializerDelegate { cxx_value_deserializer_delegate: CxxValueDeserializerDelegate {
_cxx_vtable: CxxVTable(std::ptr::null()), _cxx_vtable: CxxVTable(std::ptr::null()),
}, },
context: scope.get_current_context(), context: Global::new(scope, context),
}); }));
unsafe { unsafe {
let delegate_ptr = std::ptr::addr_of_mut!(
(*value_deserializer_heap_ptr).cxx_value_deserializer_delegate
);
let deserializer_ptr = std::ptr::addr_of_mut!(
(*value_deserializer_heap_ptr).cxx_value_deserializer
);
v8__ValueDeserializer__Delegate__CONSTRUCT( v8__ValueDeserializer__Delegate__CONSTRUCT(
&mut value_deserializer_heap.cxx_value_deserializer_delegate delegate_ptr
as *mut CxxValueDeserializerDelegate .cast::<std::mem::MaybeUninit<CxxValueDeserializerDelegate>>(),
as *mut std::mem::MaybeUninit<CxxValueDeserializerDelegate>,
); );
v8__ValueDeserializer__CONSTRUCT( v8__ValueDeserializer__CONSTRUCT(
&mut value_deserializer_heap.cxx_value_deserializer deserializer_ptr.cast::<std::mem::MaybeUninit<CxxValueDeserializer>>(),
as *mut CxxValueDeserializer
as *mut std::mem::MaybeUninit<CxxValueDeserializer>,
scope.get_isolate_ptr(), scope.get_isolate_ptr(),
data.as_ptr(), data.as_ptr(),
data.len(), data.len(),
&mut value_deserializer_heap.cxx_value_deserializer_delegate, delegate_ptr,
); );
}; };
// SAFETY: pointer from Box::into_raw is valid
let value_deserializer_heap =
Pin::new(unsafe { Box::from_raw(value_deserializer_heap_ptr) });
ValueDeserializer { ValueDeserializer {
value_deserializer_heap, value_deserializer_heap,
_phantom: std::marker::PhantomData,
} }
} }
} }
impl<'a, 's> ValueDeserializer<'a, 's> { impl<'a> ValueDeserializer<'a> {
pub fn set_supports_legacy_wire_format( pub fn set_supports_legacy_wire_format(
&mut self, &self,
supports_legacy_wire_format: bool, supports_legacy_wire_format: bool,
) { ) {
unsafe { unsafe {
v8__ValueDeserializer__SetSupportsLegacyWireFormat( v8__ValueDeserializer__SetSupportsLegacyWireFormat(
&mut self.value_deserializer_heap.cxx_value_deserializer, cast_to_ptr(&self.value_deserializer_heap.cxx_value_deserializer),
supports_legacy_wire_format, supports_legacy_wire_format,
); );
} }
} }
pub fn read_value<'t>( pub fn read_value<'t>(
&mut self, &self,
context: Local<'t, Context>, context: Local<'t, Context>,
) -> Option<Local<'t, Value>> { ) -> Option<Local<'t, Value>> {
self.value_deserializer_heap.read_value(context) self.value_deserializer_heap.read_value(context)

View file

@ -1,6 +1,9 @@
use crate::ArrayBuffer; use crate::ArrayBuffer;
use crate::CallbackScope;
use crate::Context; use crate::Context;
use crate::ContextScope;
use crate::Exception; use crate::Exception;
use crate::Global;
use crate::HandleScope; use crate::HandleScope;
use crate::Isolate; use crate::Isolate;
use crate::Local; use crate::Local;
@ -16,6 +19,7 @@ use std::alloc::realloc;
use std::alloc::Layout; use std::alloc::Layout;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::ptr::addr_of; use std::ptr::addr_of;
use std::sync::atomic::AtomicUsize;
use crate::support::CxxVTable; use crate::support::CxxVTable;
use crate::support::FieldOffset; use crate::support::FieldOffset;
@ -32,76 +36,82 @@ pub struct CxxValueSerializerDelegate {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueSerializer__Delegate__ThrowDataCloneError( unsafe extern "C" fn v8__ValueSerializer__Delegate__ThrowDataCloneError(
this: &mut CxxValueSerializerDelegate, this: &CxxValueSerializerDelegate,
message: Local<String>, message: Local<String>,
) { ) {
let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); let value_serializer_heap = ValueSerializerHeap::dispatch(this);
let scope = let scope = &mut CallbackScope::new(
&mut crate::scope::CallbackScope::new(value_serializer_heap.context); value_serializer_heap.isolate_ptr.as_mut().unwrap(),
);
let context = Local::new(scope, &value_serializer_heap.context);
let scope = &mut ContextScope::new(scope, context);
value_serializer_heap value_serializer_heap
.value_serializer_impl .value_serializer_impl
.as_mut()
.throw_data_clone_error(scope, message) .throw_data_clone_error(scope, message)
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueSerializer__Delegate__HasCustomHostObject( unsafe extern "C" fn v8__ValueSerializer__Delegate__HasCustomHostObject(
this: &mut CxxValueSerializerDelegate, this: &CxxValueSerializerDelegate,
isolate: *mut Isolate, isolate: *mut Isolate,
) -> bool { ) -> bool {
let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); let value_serializer_heap = ValueSerializerHeap::dispatch(this);
value_serializer_heap value_serializer_heap
.value_serializer_impl .value_serializer_impl
.as_mut()
.has_custom_host_object(&mut *isolate) .has_custom_host_object(&mut *isolate)
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueSerializer__Delegate__IsHostObject( unsafe extern "C" fn v8__ValueSerializer__Delegate__IsHostObject(
this: &mut CxxValueSerializerDelegate, this: &CxxValueSerializerDelegate,
_isolate: *mut Isolate, isolate: *mut Isolate,
object: Local<Object>, object: Local<Object>,
) -> MaybeBool { ) -> MaybeBool {
let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); let value_serializer_heap = ValueSerializerHeap::dispatch(this);
let scope = let scope = &mut CallbackScope::new(isolate.as_mut().unwrap());
&mut crate::scope::CallbackScope::new(value_serializer_heap.context); let context = Local::new(scope, &value_serializer_heap.context);
let value_serializer_impl = let scope = &mut ContextScope::new(scope, context);
value_serializer_heap.value_serializer_impl.as_mut();
MaybeBool::from(value_serializer_impl.is_host_object(scope, object)) MaybeBool::from(
value_serializer_heap
.value_serializer_impl
.is_host_object(scope, object),
)
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueSerializer__Delegate__WriteHostObject( unsafe extern "C" fn v8__ValueSerializer__Delegate__WriteHostObject(
this: &mut CxxValueSerializerDelegate, this: &CxxValueSerializerDelegate,
_isolate: *mut Isolate, isolate: *mut Isolate,
object: Local<Object>, object: Local<Object>,
) -> MaybeBool { ) -> MaybeBool {
let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); let value_serializer_heap = ValueSerializerHeap::dispatch(this);
let scope = let scope = &mut CallbackScope::new(isolate.as_mut().unwrap());
&mut crate::scope::CallbackScope::new(value_serializer_heap.context); let context = Local::new(scope, &value_serializer_heap.context);
let scope = &mut ContextScope::new(scope, context);
let value_serializer_impl = let value_serializer_impl =
value_serializer_heap.value_serializer_impl.as_mut(); value_serializer_heap.value_serializer_impl.as_ref();
MaybeBool::from(value_serializer_impl.write_host_object( MaybeBool::from(value_serializer_impl.write_host_object(
scope, scope,
object, object,
&mut value_serializer_heap.cxx_value_serializer, &value_serializer_heap.cxx_value_serializer,
)) ))
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueSerializer__Delegate__GetSharedArrayBufferId( unsafe extern "C" fn v8__ValueSerializer__Delegate__GetSharedArrayBufferId(
this: &mut CxxValueSerializerDelegate, this: &CxxValueSerializerDelegate,
_isolate: *mut Isolate, isolate: *mut Isolate,
shared_array_buffer: Local<SharedArrayBuffer>, shared_array_buffer: Local<SharedArrayBuffer>,
clone_id: *mut u32, clone_id: *mut u32,
) -> bool { ) -> bool {
let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); let value_serializer_heap = ValueSerializerHeap::dispatch(this);
let scope = let scope = &mut CallbackScope::new(isolate.as_mut().unwrap());
&mut crate::scope::CallbackScope::new(value_serializer_heap.context); let context = Local::new(scope, &value_serializer_heap.context);
let scope = &mut ContextScope::new(scope, context);
match value_serializer_heap match value_serializer_heap
.value_serializer_impl .value_serializer_impl
.as_mut()
.get_shared_array_buffer_id(scope, shared_array_buffer) .get_shared_array_buffer_id(scope, shared_array_buffer)
{ {
Some(x) => { Some(x) => {
@ -113,18 +123,18 @@ pub unsafe extern "C" fn v8__ValueSerializer__Delegate__GetSharedArrayBufferId(
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueSerializer__Delegate__GetWasmModuleTransferId( unsafe extern "C" fn v8__ValueSerializer__Delegate__GetWasmModuleTransferId(
this: &mut CxxValueSerializerDelegate, this: &CxxValueSerializerDelegate,
_isolate: *mut Isolate, isolate: *mut Isolate,
module: Local<WasmModuleObject>, module: Local<WasmModuleObject>,
transfer_id: *mut u32, transfer_id: *mut u32,
) -> bool { ) -> bool {
let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); let value_serializer_heap = ValueSerializerHeap::dispatch(this);
let scope = let scope = &mut CallbackScope::new(isolate.as_mut().unwrap());
&mut crate::scope::CallbackScope::new(value_serializer_heap.context); let context = Local::new(scope, value_serializer_heap.context.clone());
let scope = &mut ContextScope::new(scope, context);
match value_serializer_heap match value_serializer_heap
.value_serializer_impl .value_serializer_impl
.as_mut()
.get_wasm_module_transfer_id(scope, module) .get_wasm_module_transfer_id(scope, module)
{ {
Some(x) => { Some(x) => {
@ -136,36 +146,41 @@ pub unsafe extern "C" fn v8__ValueSerializer__Delegate__GetWasmModuleTransferId(
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueSerializer__Delegate__ReallocateBufferMemory( unsafe extern "C" fn v8__ValueSerializer__Delegate__ReallocateBufferMemory(
this: &mut CxxValueSerializerDelegate, this: &CxxValueSerializerDelegate,
old_buffer: *mut c_void, old_buffer: *mut c_void,
size: usize, size: usize,
actual_size: *mut usize, actual_size: *mut usize,
) -> *mut c_void { ) -> *mut c_void {
let base = ValueSerializerHeap::dispatch_mut(this); let base = ValueSerializerHeap::dispatch(this);
let buffer_size = base
.buffer_size
.swap(size, std::sync::atomic::Ordering::Release);
let new_buffer = if old_buffer.is_null() { let new_buffer = if old_buffer.is_null() {
let layout = Layout::from_size_align(size, 1).unwrap(); let layout = Layout::from_size_align(size, 1).unwrap();
alloc(layout) alloc(layout)
} else { } else {
let old_layout = Layout::from_size_align(base.buffer_size, 1).unwrap(); let old_layout = Layout::from_size_align(buffer_size, 1).unwrap();
realloc(old_buffer as *mut _, old_layout, size) realloc(old_buffer as *mut _, old_layout, size)
}; };
base.buffer_size = size;
*actual_size = size; *actual_size = size;
new_buffer as *mut c_void new_buffer as *mut c_void
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn v8__ValueSerializer__Delegate__FreeBufferMemory( unsafe extern "C" fn v8__ValueSerializer__Delegate__FreeBufferMemory(
this: &mut CxxValueSerializerDelegate, this: &mut CxxValueSerializerDelegate,
buffer: *mut c_void, buffer: *mut c_void,
) { ) {
let base = ValueSerializerHeap::dispatch_mut(this); let base = ValueSerializerHeap::dispatch(this);
if !buffer.is_null() { if !buffer.is_null() {
let layout = Layout::from_size_align(base.buffer_size, 1).unwrap(); let layout = Layout::from_size_align(
base.buffer_size.load(std::sync::atomic::Ordering::Relaxed),
1,
)
.unwrap();
dealloc(buffer as *mut _, layout) dealloc(buffer as *mut _, layout)
}; };
} }
@ -226,23 +241,27 @@ extern "C" {
source: *const c_void, source: *const c_void,
length: usize, length: usize,
); );
fn v8__ValueSerializer__SetTreatArrayBufferViewsAsHostObjects(
this: *mut CxxValueSerializer,
mode: bool,
);
} }
/// The ValueSerializerImpl trait allows for /// The ValueSerializerImpl trait allows for
/// custom callback functions used by v8. /// custom callback functions used by v8.
pub trait ValueSerializerImpl { pub trait ValueSerializerImpl {
fn throw_data_clone_error<'s>( fn throw_data_clone_error<'s>(
&mut self, &self,
scope: &mut HandleScope<'s>, scope: &mut HandleScope<'s>,
message: Local<'s, String>, message: Local<'s, String>,
); );
fn has_custom_host_object(&mut self, _isolate: &mut Isolate) -> bool { fn has_custom_host_object(&self, _isolate: &mut Isolate) -> bool {
false false
} }
fn is_host_object<'s>( fn is_host_object<'s>(
&mut self, &self,
scope: &mut HandleScope<'s>, scope: &mut HandleScope<'s>,
_object: Local<'s, Object>, _object: Local<'s, Object>,
) -> Option<bool> { ) -> Option<bool> {
@ -255,10 +274,10 @@ pub trait ValueSerializerImpl {
} }
fn write_host_object<'s>( fn write_host_object<'s>(
&mut self, &self,
scope: &mut HandleScope<'s>, scope: &mut HandleScope<'s>,
_object: Local<'s, Object>, _object: Local<'s, Object>,
_value_serializer: &mut dyn ValueSerializerHelper, _value_serializer: &dyn ValueSerializerHelper,
) -> Option<bool> { ) -> Option<bool> {
let msg = let msg =
String::new(scope, "Deno serializer: write_host_object not implemented") String::new(scope, "Deno serializer: write_host_object not implemented")
@ -269,7 +288,7 @@ pub trait ValueSerializerImpl {
} }
fn get_shared_array_buffer_id<'s>( fn get_shared_array_buffer_id<'s>(
&mut self, &self,
_scope: &mut HandleScope<'s>, _scope: &mut HandleScope<'s>,
_shared_array_buffer: Local<'s, SharedArrayBuffer>, _shared_array_buffer: Local<'s, SharedArrayBuffer>,
) -> Option<u32> { ) -> Option<u32> {
@ -277,7 +296,7 @@ pub trait ValueSerializerImpl {
} }
fn get_wasm_module_transfer_id( fn get_wasm_module_transfer_id(
&mut self, &self,
scope: &mut HandleScope<'_>, scope: &mut HandleScope<'_>,
_module: Local<WasmModuleObject>, _module: Local<WasmModuleObject>,
) -> Option<u32> { ) -> Option<u32> {
@ -299,15 +318,16 @@ pub trait ValueSerializerImpl {
/// to fail. Additionally the serializer and implementation are also pinned /// to fail. Additionally the serializer and implementation are also pinned
/// in memory because these have to be accessable from within the delegate /// in memory because these have to be accessable from within the delegate
/// callback methods. /// callback methods.
pub struct ValueSerializerHeap<'a, 's> { pub struct ValueSerializerHeap<'a> {
value_serializer_impl: Box<dyn ValueSerializerImpl + 'a>, value_serializer_impl: Box<dyn ValueSerializerImpl + 'a>,
cxx_value_serializer_delegate: CxxValueSerializerDelegate, cxx_value_serializer_delegate: CxxValueSerializerDelegate,
cxx_value_serializer: CxxValueSerializer, cxx_value_serializer: CxxValueSerializer,
buffer_size: usize, buffer_size: AtomicUsize,
context: Local<'s, Context>, context: Global<Context>,
isolate_ptr: *mut Isolate,
} }
impl<'a, 's> ValueSerializerHeap<'a, 's> { impl<'a> ValueSerializerHeap<'a> {
fn get_cxx_value_serializer_delegate_offset( fn get_cxx_value_serializer_delegate_offset(
) -> FieldOffset<CxxValueSerializerDelegate> { ) -> FieldOffset<CxxValueSerializerDelegate> {
let buf = std::mem::MaybeUninit::<Self>::uninit(); let buf = std::mem::MaybeUninit::<Self>::uninit();
@ -317,50 +337,46 @@ impl<'a, 's> ValueSerializerHeap<'a, 's> {
} }
/// Starting from 'this' pointer a ValueSerializerHeap ref can be created /// Starting from 'this' pointer a ValueSerializerHeap ref can be created
#[allow(dead_code)]
pub unsafe fn dispatch( pub unsafe fn dispatch(
value_serializer_delegate: &'s CxxValueSerializerDelegate, value_serializer_delegate: &CxxValueSerializerDelegate,
) -> &Self { ) -> &Self {
Self::get_cxx_value_serializer_delegate_offset() Self::get_cxx_value_serializer_delegate_offset()
.to_embedder::<Self>(value_serializer_delegate) .to_embedder::<Self>(value_serializer_delegate)
} }
/// Starting from 'this' pointer the ValueSerializerHeap mut ref can be
/// created
pub unsafe fn dispatch_mut(
value_serializer_delegate: &'s mut CxxValueSerializerDelegate,
) -> &mut Self {
Self::get_cxx_value_serializer_delegate_offset()
.to_embedder_mut::<Self>(value_serializer_delegate)
}
} }
impl<'a, 's> Drop for ValueSerializerHeap<'a, 's> { impl<'a> Drop for ValueSerializerHeap<'a> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { v8__ValueSerializer__DESTRUCT(&mut self.cxx_value_serializer) }; unsafe { v8__ValueSerializer__DESTRUCT(&mut self.cxx_value_serializer) };
} }
} }
fn cast_to_ptr<T>(x: &T) -> *mut T {
x as *const T as *mut T
}
/// Trait used for direct write to the serialization buffer. /// Trait used for direct write to the serialization buffer.
/// Mostly used by the write_host_object callback function in the /// Mostly used by the write_host_object callback function in the
/// ValueSerializerImpl trait to create custom serialization logic. /// ValueSerializerImpl trait to create custom serialization logic.
pub trait ValueSerializerHelper { pub trait ValueSerializerHelper {
fn get_cxx_value_serializer(&mut self) -> &mut CxxValueSerializer; fn get_cxx_value_serializer(&self) -> &CxxValueSerializer;
fn write_header(&mut self) { fn write_header(&self) {
unsafe { unsafe {
v8__ValueSerializer__WriteHeader(self.get_cxx_value_serializer()) v8__ValueSerializer__WriteHeader(cast_to_ptr(
self.get_cxx_value_serializer(),
))
}; };
} }
fn write_value( fn write_value(
&mut self, &self,
context: Local<Context>, context: Local<Context>,
value: Local<Value>, value: Local<Value>,
) -> Option<bool> { ) -> Option<bool> {
unsafe { unsafe {
v8__ValueSerializer__WriteValue( v8__ValueSerializer__WriteValue(
self.get_cxx_value_serializer(), cast_to_ptr(self.get_cxx_value_serializer()),
context, context,
value, value,
) )
@ -368,28 +384,37 @@ pub trait ValueSerializerHelper {
.into() .into()
} }
fn write_uint32(&mut self, value: u32) { fn write_uint32(&self, value: u32) {
unsafe { unsafe {
v8__ValueSerializer__WriteUint32(self.get_cxx_value_serializer(), value) v8__ValueSerializer__WriteUint32(
cast_to_ptr(self.get_cxx_value_serializer()),
value,
)
}; };
} }
fn write_uint64(&mut self, value: u64) { fn write_uint64(&self, value: u64) {
unsafe { unsafe {
v8__ValueSerializer__WriteUint64(self.get_cxx_value_serializer(), value) v8__ValueSerializer__WriteUint64(
cast_to_ptr(self.get_cxx_value_serializer()),
value,
)
}; };
} }
fn write_double(&mut self, value: f64) { fn write_double(&self, value: f64) {
unsafe { unsafe {
v8__ValueSerializer__WriteDouble(self.get_cxx_value_serializer(), value) v8__ValueSerializer__WriteDouble(
cast_to_ptr(self.get_cxx_value_serializer()),
value,
)
}; };
} }
fn write_raw_bytes(&mut self, source: &[u8]) { fn write_raw_bytes(&self, source: &[u8]) {
unsafe { unsafe {
v8__ValueSerializer__WriteRawBytes( v8__ValueSerializer__WriteRawBytes(
self.get_cxx_value_serializer(), cast_to_ptr(self.get_cxx_value_serializer()),
source.as_ptr() as *const _, source.as_ptr() as *const _,
source.len(), source.len(),
) )
@ -397,40 +422,52 @@ pub trait ValueSerializerHelper {
} }
fn transfer_array_buffer( fn transfer_array_buffer(
&mut self, &self,
transfer_id: u32, transfer_id: u32,
array_buffer: Local<ArrayBuffer>, array_buffer: Local<ArrayBuffer>,
) { ) {
unsafe { unsafe {
v8__ValueSerializer__TransferArrayBuffer( v8__ValueSerializer__TransferArrayBuffer(
self.get_cxx_value_serializer(), cast_to_ptr(self.get_cxx_value_serializer()),
transfer_id, transfer_id,
array_buffer, array_buffer,
) )
}; };
} }
fn set_treat_array_buffer_views_as_host_objects(&self, mode: bool) {
unsafe {
v8__ValueSerializer__SetTreatArrayBufferViewsAsHostObjects(
cast_to_ptr(self.get_cxx_value_serializer()),
mode,
)
};
}
} }
impl ValueSerializerHelper for CxxValueSerializer { impl ValueSerializerHelper for CxxValueSerializer {
fn get_cxx_value_serializer(&mut self) -> &mut CxxValueSerializer { fn get_cxx_value_serializer(&self) -> &CxxValueSerializer {
self self
} }
} }
impl<'a, 's> ValueSerializerHelper for ValueSerializerHeap<'a, 's> { impl<'a> ValueSerializerHelper for ValueSerializerHeap<'a> {
fn get_cxx_value_serializer(&mut self) -> &mut CxxValueSerializer { fn get_cxx_value_serializer(&self) -> &CxxValueSerializer {
&mut self.cxx_value_serializer &self.cxx_value_serializer
} }
} }
impl<'a, 's> ValueSerializerHelper for ValueSerializer<'a, 's> { impl<'a> ValueSerializerHelper for ValueSerializer<'a> {
fn get_cxx_value_serializer(&mut self) -> &mut CxxValueSerializer { fn get_cxx_value_serializer(&self) -> &CxxValueSerializer {
&mut self.value_serializer_heap.cxx_value_serializer &self.value_serializer_heap.cxx_value_serializer
} }
} }
pub struct ValueSerializer<'a, 's> { pub struct ValueSerializer<'a> {
value_serializer_heap: Pin<Box<ValueSerializerHeap<'a, 's>>>, value_serializer_heap: Pin<Box<ValueSerializerHeap<'a>>>,
// ValueSerializerHeap is already !Send and !Sync
// but this is just making it explicit
_phantom: std::marker::PhantomData<*mut ()>,
} }
/// ValueSerializer is a stack object used as entry-point for an owned and /// ValueSerializer is a stack object used as entry-point for an owned and
@ -438,13 +475,15 @@ pub struct ValueSerializer<'a, 's> {
/// The 'a lifetime is the lifetime of the ValueSerializerImpl implementation. /// The 'a lifetime is the lifetime of the ValueSerializerImpl implementation.
/// The 's lifetime is the lifetime of the HandleScope which is used to retrieve /// The 's lifetime is the lifetime of the HandleScope which is used to retrieve
/// a Local<'s, Context> for the CallbackScopes /// a Local<'s, Context> for the CallbackScopes
impl<'a, 's> ValueSerializer<'a, 's> { impl<'a> ValueSerializer<'a> {
pub fn new<D: ValueSerializerImpl + 'a>( pub fn new<D: ValueSerializerImpl + 'a>(
scope: &mut HandleScope<'s>, scope: &mut HandleScope,
value_serializer_impl: Box<D>, value_serializer_impl: Box<D>,
) -> Self { ) -> Self {
let context = scope.get_current_context();
// create dummy ValueSerializerHeap 'a, and move to heap + pin to address // create dummy ValueSerializerHeap 'a, and move to heap + pin to address
let mut value_serializer_heap = Box::pin(ValueSerializerHeap { let value_serializer_heap_ptr =
Box::into_raw(Box::new(ValueSerializerHeap {
value_serializer_impl, value_serializer_impl,
cxx_value_serializer: CxxValueSerializer { cxx_value_serializer: CxxValueSerializer {
_cxx_vtable: CxxVTable(std::ptr::null()), _cxx_vtable: CxxVTable(std::ptr::null()),
@ -452,48 +491,64 @@ impl<'a, 's> ValueSerializer<'a, 's> {
cxx_value_serializer_delegate: CxxValueSerializerDelegate { cxx_value_serializer_delegate: CxxValueSerializerDelegate {
_cxx_vtable: CxxVTable(std::ptr::null()), _cxx_vtable: CxxVTable(std::ptr::null()),
}, },
buffer_size: 0, buffer_size: AtomicUsize::new(0),
context: scope.get_current_context(), context: Global::new(scope, context),
}); isolate_ptr: scope.get_isolate_ptr(),
}));
unsafe { unsafe {
let delegate_ptr = std::ptr::addr_of_mut!(
(*value_serializer_heap_ptr).cxx_value_serializer_delegate
);
let serializer_ptr = std::ptr::addr_of_mut!(
(*value_serializer_heap_ptr).cxx_value_serializer
);
v8__ValueSerializer__Delegate__CONSTRUCT( v8__ValueSerializer__Delegate__CONSTRUCT(
&mut value_serializer_heap.cxx_value_serializer_delegate delegate_ptr
as *mut CxxValueSerializerDelegate .cast::<std::mem::MaybeUninit<CxxValueSerializerDelegate>>(),
as *mut std::mem::MaybeUninit<CxxValueSerializerDelegate>,
); );
v8__ValueSerializer__CONSTRUCT( v8__ValueSerializer__CONSTRUCT(
&mut value_serializer_heap.cxx_value_serializer serializer_ptr.cast::<std::mem::MaybeUninit<CxxValueSerializer>>(),
as *mut CxxValueSerializer
as *mut std::mem::MaybeUninit<CxxValueSerializer>,
scope.get_isolate_ptr(), scope.get_isolate_ptr(),
&mut value_serializer_heap.cxx_value_serializer_delegate, delegate_ptr,
); );
}; };
// SAFETY: pointer from `Box::into_raw` is valid
let value_serializer_heap =
Pin::new(unsafe { Box::from_raw(value_serializer_heap_ptr) });
Self { Self {
value_serializer_heap, value_serializer_heap,
_phantom: std::marker::PhantomData,
} }
} }
} }
impl<'a, 's> ValueSerializer<'a, 's> { impl<'a> ValueSerializer<'a> {
pub fn release(mut self) -> Vec<u8> { pub fn release(&self) -> Vec<u8> {
unsafe { unsafe {
let mut size: usize = 0; let mut size: usize = 0;
let mut ptr: *mut u8 = &mut 0; let mut ptr: *mut u8 = &mut 0;
v8__ValueSerializer__Release( v8__ValueSerializer__Release(
&mut self.value_serializer_heap.cxx_value_serializer, cast_to_ptr(self.get_cxx_value_serializer()),
&mut ptr, &mut ptr,
&mut size, &mut size,
); );
Vec::from_raw_parts(ptr, size, self.value_serializer_heap.buffer_size) Vec::from_raw_parts(
ptr,
size,
self
.value_serializer_heap
.buffer_size
.swap(0, std::sync::atomic::Ordering::Relaxed),
)
} }
} }
pub fn write_value( pub fn write_value(
&mut self, &self,
context: Local<Context>, context: Local<Context>,
value: Local<Value>, value: Local<Value>,
) -> Option<bool> { ) -> Option<bool> {

View file

@ -7952,14 +7952,15 @@ fn bigint() {
type ArrayBuffers = Vec<v8::SharedRef<v8::BackingStore>>; type ArrayBuffers = Vec<v8::SharedRef<v8::BackingStore>>;
struct Custom1Value<'a> { struct Custom1Value<'a> {
array_buffers: &'a mut ArrayBuffers, array_buffers: RefCell<&'a mut ArrayBuffers>,
} }
impl<'a> Custom1Value<'a> { impl<'a> Custom1Value<'a> {
fn serializer<'s>( fn serializer<'s>(
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
array_buffers: &'a mut ArrayBuffers, array_buffers: &'a mut ArrayBuffers,
) -> v8::ValueSerializer<'a, 's> { ) -> v8::ValueSerializer<'a> {
let array_buffers = RefCell::new(array_buffers);
v8::ValueSerializer::new(scope, Box::new(Self { array_buffers })) v8::ValueSerializer::new(scope, Box::new(Self { array_buffers }))
} }
@ -7967,7 +7968,8 @@ impl<'a> Custom1Value<'a> {
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
data: &[u8], data: &[u8],
array_buffers: &'a mut ArrayBuffers, array_buffers: &'a mut ArrayBuffers,
) -> v8::ValueDeserializer<'a, 's> { ) -> v8::ValueDeserializer<'a> {
let array_buffers = RefCell::new(array_buffers);
v8::ValueDeserializer::new(scope, Box::new(Self { array_buffers }), data) v8::ValueDeserializer::new(scope, Box::new(Self { array_buffers }), data)
} }
} }
@ -7975,7 +7977,7 @@ impl<'a> Custom1Value<'a> {
impl<'a> v8::ValueSerializerImpl for Custom1Value<'a> { impl<'a> v8::ValueSerializerImpl for Custom1Value<'a> {
#[allow(unused_variables)] #[allow(unused_variables)]
fn throw_data_clone_error<'s>( fn throw_data_clone_error<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
message: v8::Local<'s, v8::String>, message: v8::Local<'s, v8::String>,
) { ) {
@ -7985,23 +7987,21 @@ impl<'a> v8::ValueSerializerImpl for Custom1Value<'a> {
#[allow(unused_variables)] #[allow(unused_variables)]
fn get_shared_array_buffer_id<'s>( fn get_shared_array_buffer_id<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
shared_array_buffer: v8::Local<'s, v8::SharedArrayBuffer>, shared_array_buffer: v8::Local<'s, v8::SharedArrayBuffer>,
) -> Option<u32> { ) -> Option<u32> {
self self.array_buffers.borrow_mut().push(
.array_buffers v8::SharedArrayBuffer::get_backing_store(&shared_array_buffer),
.push(v8::SharedArrayBuffer::get_backing_store( );
&shared_array_buffer, Some((self.array_buffers.borrow().len() as u32) - 1)
));
Some((self.array_buffers.len() as u32) - 1)
} }
fn write_host_object<'s>( fn write_host_object<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
object: v8::Local<'s, v8::Object>, object: v8::Local<'s, v8::Object>,
value_serializer: &mut dyn v8::ValueSerializerHelper, value_serializer: &dyn v8::ValueSerializerHelper,
) -> Option<bool> { ) -> Option<bool> {
let key = v8::String::new(scope, "hostObject").unwrap(); let key = v8::String::new(scope, "hostObject").unwrap();
let value = object let value = object
@ -8017,21 +8017,26 @@ impl<'a> v8::ValueSerializerImpl for Custom1Value<'a> {
impl<'a> v8::ValueDeserializerImpl for Custom1Value<'a> { impl<'a> v8::ValueDeserializerImpl for Custom1Value<'a> {
#[allow(unused_variables)] #[allow(unused_variables)]
fn get_shared_array_buffer_from_id<'s>( fn get_shared_array_buffer_from_id<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
transfer_id: u32, transfer_id: u32,
) -> Option<v8::Local<'s, v8::SharedArrayBuffer>> { ) -> Option<v8::Local<'s, v8::SharedArrayBuffer>> {
let backing_store = self.array_buffers.get(transfer_id as usize).unwrap(); let backing_store = self
.array_buffers
.borrow()
.get(transfer_id as usize)
.unwrap()
.clone();
Some(v8::SharedArrayBuffer::with_backing_store( Some(v8::SharedArrayBuffer::with_backing_store(
scope, scope,
backing_store, &backing_store,
)) ))
} }
fn read_host_object<'s>( fn read_host_object<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
value_deserializer: &mut dyn v8::ValueDeserializerHelper, value_deserializer: &dyn v8::ValueDeserializerHelper,
) -> Option<v8::Local<'s, v8::Object>> { ) -> Option<v8::Local<'s, v8::Object>> {
let mut value = 0; let mut value = 0;
value_deserializer.read_uint32(&mut value); value_deserializer.read_uint32(&mut value);
@ -8060,8 +8065,7 @@ fn value_serializer_and_deserializer() {
let scope = &mut v8::ContextScope::new(scope, context); let scope = &mut v8::ContextScope::new(scope, context);
let buffer; let buffer;
{ {
let mut value_serializer = let value_serializer = Custom1Value::serializer(scope, &mut array_buffers);
Custom1Value::serializer(scope, &mut array_buffers);
value_serializer.write_header(); value_serializer.write_header();
value_serializer.write_double(55.44); value_serializer.write_double(55.44);
value_serializer.write_uint32(22); value_serializer.write_uint32(22);
@ -8071,7 +8075,7 @@ fn value_serializer_and_deserializer() {
let mut double: f64 = 0.0; let mut double: f64 = 0.0;
let mut int32: u32 = 0; let mut int32: u32 = 0;
{ {
let mut value_deserializer = let value_deserializer =
Custom1Value::deserializer(scope, &buffer, &mut array_buffers); Custom1Value::deserializer(scope, &buffer, &mut array_buffers);
assert_eq!(value_deserializer.read_header(context), Some(true)); assert_eq!(value_deserializer.read_header(context), Some(true));
assert!(value_deserializer.read_double(&mut double)); assert!(value_deserializer.read_double(&mut double));
@ -8117,8 +8121,7 @@ fn value_serializer_and_deserializer_js_objects() {
]"#, ]"#,
) )
.unwrap(); .unwrap();
let mut value_serializer = let value_serializer = Custom1Value::serializer(scope, &mut array_buffers);
Custom1Value::serializer(scope, &mut array_buffers);
value_serializer.write_header(); value_serializer.write_header();
assert_eq!(value_serializer.write_value(context, objects), Some(true)); assert_eq!(value_serializer.write_value(context, objects), Some(true));
@ -8134,7 +8137,7 @@ fn value_serializer_and_deserializer_js_objects() {
let context = v8::Context::new(scope, Default::default()); let context = v8::Context::new(scope, Default::default());
let scope = &mut v8::ContextScope::new(scope, context); let scope = &mut v8::ContextScope::new(scope, context);
let mut value_deserializer = let value_deserializer =
Custom1Value::deserializer(scope, &buffer, &mut array_buffers); Custom1Value::deserializer(scope, &buffer, &mut array_buffers);
assert_eq!(value_deserializer.read_header(context), Some(true)); assert_eq!(value_deserializer.read_header(context), Some(true));
let name = v8::String::new(scope, "objects").unwrap(); let name = v8::String::new(scope, "objects").unwrap();
@ -8224,8 +8227,7 @@ fn value_serializer_and_deserializer_array_buffers() {
}"#, }"#,
) )
.unwrap(); .unwrap();
let mut value_serializer = let value_serializer = Custom1Value::serializer(scope, &mut array_buffers);
Custom1Value::serializer(scope, &mut array_buffers);
assert_eq!(value_serializer.write_value(context, objects), Some(true)); assert_eq!(value_serializer.write_value(context, objects), Some(true));
buffer = value_serializer.release(); buffer = value_serializer.release();
@ -8240,7 +8242,7 @@ fn value_serializer_and_deserializer_array_buffers() {
let context = v8::Context::new(scope, Default::default()); let context = v8::Context::new(scope, Default::default());
let scope = &mut v8::ContextScope::new(scope, context); let scope = &mut v8::ContextScope::new(scope, context);
let mut value_deserializer = let value_deserializer =
Custom1Value::deserializer(scope, &buffer, &mut array_buffers); Custom1Value::deserializer(scope, &buffer, &mut array_buffers);
let name = v8::String::new(scope, "objects").unwrap(); let name = v8::String::new(scope, "objects").unwrap();
let objects: v8::Local<v8::Value> = let objects: v8::Local<v8::Value> =
@ -8286,8 +8288,7 @@ fn value_serializer_and_deserializer_embedder_host_object() {
let value = v8::Integer::new_from_unsigned(scope, expected); let value = v8::Integer::new_from_unsigned(scope, expected);
host_object.set(scope, key.into(), value.into()); host_object.set(scope, key.into(), value.into());
let mut value_serializer = let value_serializer = Custom1Value::serializer(scope, &mut array_buffers);
Custom1Value::serializer(scope, &mut array_buffers);
assert_eq!( assert_eq!(
value_serializer.write_value(context, host_object.into()), value_serializer.write_value(context, host_object.into()),
Some(true) Some(true)
@ -8305,7 +8306,7 @@ fn value_serializer_and_deserializer_embedder_host_object() {
let context = v8::Context::new(scope, Default::default()); let context = v8::Context::new(scope, Default::default());
let scope = &mut v8::ContextScope::new(scope, context); let scope = &mut v8::ContextScope::new(scope, context);
let mut value_deserializer = let value_deserializer =
Custom1Value::deserializer(scope, &buffer, &mut array_buffers); Custom1Value::deserializer(scope, &buffer, &mut array_buffers);
let host_object_out = value_deserializer let host_object_out = value_deserializer
.read_value(context) .read_value(context)
@ -8328,7 +8329,7 @@ struct Custom2Value {}
impl<'a> Custom2Value { impl<'a> Custom2Value {
fn serializer<'s>( fn serializer<'s>(
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
) -> v8::ValueSerializer<'a, 's> { ) -> v8::ValueSerializer<'a> {
v8::ValueSerializer::new(scope, Box::new(Self {})) v8::ValueSerializer::new(scope, Box::new(Self {}))
} }
} }
@ -8336,7 +8337,7 @@ impl<'a> Custom2Value {
impl v8::ValueSerializerImpl for Custom2Value { impl v8::ValueSerializerImpl for Custom2Value {
#[allow(unused_variables)] #[allow(unused_variables)]
fn throw_data_clone_error<'s>( fn throw_data_clone_error<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
message: v8::Local<'s, v8::String>, message: v8::Local<'s, v8::String>,
) { ) {
@ -8367,7 +8368,7 @@ fn value_serializer_not_implemented() {
}"#, }"#,
) )
.unwrap(); .unwrap();
let mut value_serializer = Custom2Value::serializer(scope); let value_serializer = Custom2Value::serializer(scope);
assert_eq!(value_serializer.write_value(context, objects), None); assert_eq!(value_serializer.write_value(context, objects), None);
assert!(scope.exception().is_some()); assert!(scope.exception().is_some());
@ -8388,14 +8389,14 @@ struct Custom3Value {}
impl<'a> Custom3Value { impl<'a> Custom3Value {
fn serializer<'s>( fn serializer<'s>(
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
) -> v8::ValueSerializer<'a, 's> { ) -> v8::ValueSerializer<'a> {
v8::ValueSerializer::new(scope, Box::new(Self {})) v8::ValueSerializer::new(scope, Box::new(Self {}))
} }
fn deserializer<'s>( fn deserializer<'s>(
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
data: &[u8], data: &[u8],
) -> v8::ValueDeserializer<'a, 's> { ) -> v8::ValueDeserializer<'a> {
v8::ValueDeserializer::new(scope, Box::new(Self {}), data) v8::ValueDeserializer::new(scope, Box::new(Self {}), data)
} }
} }
@ -8403,7 +8404,7 @@ impl<'a> Custom3Value {
impl v8::ValueSerializerImpl for Custom3Value { impl v8::ValueSerializerImpl for Custom3Value {
#[allow(unused_variables)] #[allow(unused_variables)]
fn throw_data_clone_error<'s>( fn throw_data_clone_error<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
message: v8::Local<'s, v8::String>, message: v8::Local<'s, v8::String>,
) { ) {
@ -8411,12 +8412,12 @@ impl v8::ValueSerializerImpl for Custom3Value {
scope.throw_exception(error); scope.throw_exception(error);
} }
fn has_custom_host_object(&mut self, _isolate: &mut v8::Isolate) -> bool { fn has_custom_host_object(&self, _isolate: &mut v8::Isolate) -> bool {
true true
} }
fn is_host_object<'s>( fn is_host_object<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
object: v8::Local<'s, v8::Object>, object: v8::Local<'s, v8::Object>,
) -> Option<bool> { ) -> Option<bool> {
@ -8425,10 +8426,10 @@ impl v8::ValueSerializerImpl for Custom3Value {
} }
fn write_host_object<'s>( fn write_host_object<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
object: v8::Local<'s, v8::Object>, object: v8::Local<'s, v8::Object>,
value_serializer: &mut dyn v8::ValueSerializerHelper, value_serializer: &dyn v8::ValueSerializerHelper,
) -> Option<bool> { ) -> Option<bool> {
let key = v8::String::new(scope, "hostObject").unwrap(); let key = v8::String::new(scope, "hostObject").unwrap();
let value = object let value = object
@ -8443,9 +8444,9 @@ impl v8::ValueSerializerImpl for Custom3Value {
impl v8::ValueDeserializerImpl for Custom3Value { impl v8::ValueDeserializerImpl for Custom3Value {
fn read_host_object<'s>( fn read_host_object<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
value_deserializer: &mut dyn v8::ValueDeserializerHelper, value_deserializer: &dyn v8::ValueDeserializerHelper,
) -> Option<v8::Local<'s, v8::Object>> { ) -> Option<v8::Local<'s, v8::Object>> {
let mut value = 0; let mut value = 0;
value_deserializer.read_uint32(&mut value); value_deserializer.read_uint32(&mut value);
@ -8475,7 +8476,7 @@ fn value_serializer_and_deserializer_custom_host_object() {
let value = v8::Integer::new_from_unsigned(scope, expected); let value = v8::Integer::new_from_unsigned(scope, expected);
host_object.set(scope, key.into(), value.into()); host_object.set(scope, key.into(), value.into());
let mut value_serializer = Custom3Value::serializer(scope); let value_serializer = Custom3Value::serializer(scope);
assert_eq!( assert_eq!(
value_serializer.write_value(context, host_object.into()), value_serializer.write_value(context, host_object.into()),
Some(true) Some(true)
@ -8493,7 +8494,7 @@ fn value_serializer_and_deserializer_custom_host_object() {
let context = v8::Context::new(scope, Default::default()); let context = v8::Context::new(scope, Default::default());
let scope = &mut v8::ContextScope::new(scope, context); let scope = &mut v8::ContextScope::new(scope, context);
let mut value_deserializer = Custom3Value::deserializer(scope, &buffer); let value_deserializer = Custom3Value::deserializer(scope, &buffer);
let host_object_out = value_deserializer let host_object_out = value_deserializer
.read_value(context) .read_value(context)
.unwrap() .unwrap()
@ -11743,17 +11744,17 @@ fn allow_scope_in_read_host_object() {
struct Serializer; struct Serializer;
impl v8::ValueSerializerImpl for Serializer { impl v8::ValueSerializerImpl for Serializer {
fn write_host_object<'s>( fn write_host_object<'s>(
&mut self, &self,
_scope: &mut v8::HandleScope<'s>, _scope: &mut v8::HandleScope<'s>,
_object: v8::Local<'s, v8::Object>, _object: v8::Local<'s, v8::Object>,
_value_serializer: &mut dyn v8::ValueSerializerHelper, _value_serializer: &dyn v8::ValueSerializerHelper,
) -> Option<bool> { ) -> Option<bool> {
// Doesn't look at the object or writes anything. // Doesn't look at the object or writes anything.
Some(true) Some(true)
} }
fn throw_data_clone_error<'s>( fn throw_data_clone_error<'s>(
&mut self, &self,
_scope: &mut v8::HandleScope<'s>, _scope: &mut v8::HandleScope<'s>,
_message: v8::Local<'s, v8::String>, _message: v8::Local<'s, v8::String>,
) { ) {
@ -11764,9 +11765,9 @@ fn allow_scope_in_read_host_object() {
struct Deserializer; struct Deserializer;
impl v8::ValueDeserializerImpl for Deserializer { impl v8::ValueDeserializerImpl for Deserializer {
fn read_host_object<'s>( fn read_host_object<'s>(
&mut self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
_value_deserializer: &mut dyn v8::ValueDeserializerHelper, _value_deserializer: &dyn v8::ValueDeserializerHelper,
) -> Option<v8::Local<'s, v8::Object>> { ) -> Option<v8::Local<'s, v8::Object>> {
let scope2 = &mut v8::AllowJavascriptExecutionScope::new(scope); let scope2 = &mut v8::AllowJavascriptExecutionScope::new(scope);
let value = eval(scope2, "{}").unwrap(); let value = eval(scope2, "{}").unwrap();
@ -11783,15 +11784,14 @@ fn allow_scope_in_read_host_object() {
let mut scope = v8::ContextScope::new(&mut scope, context); let mut scope = v8::ContextScope::new(&mut scope, context);
let serialized = { let serialized = {
let mut serializer = let serializer = v8::ValueSerializer::new(&mut scope, Box::new(Serializer));
v8::ValueSerializer::new(&mut scope, Box::new(Serializer));
serializer serializer
.write_value(context, v8::Object::new(&mut scope).into()) .write_value(context, v8::Object::new(&mut scope).into())
.unwrap(); .unwrap();
serializer.release() serializer.release()
}; };
let mut deserializer = let deserializer =
v8::ValueDeserializer::new(&mut scope, Box::new(Deserializer), &serialized); v8::ValueDeserializer::new(&mut scope, Box::new(Deserializer), &serialized);
let value = deserializer.read_value(context).unwrap(); let value = deserializer.read_value(context).unwrap();
assert!(value.is_object()); assert!(value.is_object());