diff --git a/src/binding.cc b/src/binding.cc index 1d5a157d..4f198984 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -3539,6 +3539,11 @@ void v8__ValueSerializer__Release(v8::ValueSerializer* self, uint8_t** ptr, *size = result.second; } +void v8__ValueSerializer__SetTreatArrayBufferViewsAsHostObjects( + v8::ValueSerializer* self, bool mode) { + self->SetTreatArrayBufferViewsAsHostObjects(mode); +} + void v8__ValueSerializer__WriteHeader(v8::ValueSerializer* self) { self->WriteHeader(); } @@ -3678,6 +3683,11 @@ bool v8__ValueDeserializer__ReadRawBytes(v8::ValueDeserializer* self, size_t length, const void** data) { return self->ReadRawBytes(length, data); } + +uint32_t v8__ValueDeserializer__GetWireFormatVersion( + v8::ValueDeserializer* self) { + return self->GetWireFormatVersion(); +} } // extern "C" // v8::CompiledWasmModule diff --git a/src/value_deserializer.rs b/src/value_deserializer.rs index 00f3a9ad..91af64cc 100644 --- a/src/value_deserializer.rs +++ b/src/value_deserializer.rs @@ -1,6 +1,9 @@ use crate::ArrayBuffer; +use crate::CallbackScope; use crate::Context; +use crate::ContextScope; use crate::Exception; +use crate::Global; use crate::HandleScope; use crate::Isolate; use crate::Local; @@ -27,36 +30,37 @@ pub struct CxxValueDeserializerDelegate { } #[no_mangle] -pub unsafe extern "C" fn v8__ValueDeserializer__Delegate__ReadHostObject( - this: &mut CxxValueDeserializerDelegate, - _isolate: *mut Isolate, +unsafe extern "C" fn v8__ValueDeserializer__Delegate__ReadHostObject( + this: &CxxValueDeserializerDelegate, + isolate: *mut Isolate, ) -> *const Object { - let value_deserializer_heap = ValueDeserializerHeap::dispatch_mut(this); - let scope = - &mut crate::scope::CallbackScope::new(value_deserializer_heap.context); - let value_deserializer_impl = - value_deserializer_heap.value_deserializer_impl.as_mut(); - match value_deserializer_impl.read_host_object( - scope, - &mut value_deserializer_heap.cxx_value_deserializer, - ) { + let value_deserializer_heap = ValueDeserializerHeap::dispatch(this); + let scope = &mut CallbackScope::new(isolate.as_mut().unwrap()); + let context = Local::new(scope, &value_deserializer_heap.context); + let scope = &mut ContextScope::new(scope, context); + + match value_deserializer_heap + .value_deserializer_impl + .read_host_object(scope, &value_deserializer_heap.cxx_value_deserializer) + { None => std::ptr::null(), Some(x) => x.as_non_null().as_ptr(), } } #[no_mangle] -pub unsafe extern "C" fn v8__ValueDeserializer__Delegate__GetSharedArrayBufferFromId( - this: &mut CxxValueDeserializerDelegate, - _isolate: *mut Isolate, +unsafe extern "C" fn v8__ValueDeserializer__Delegate__GetSharedArrayBufferFromId( + this: &CxxValueDeserializerDelegate, + isolate: *mut Isolate, transfer_id: u32, ) -> *const SharedArrayBuffer { - let value_deserializer_heap = ValueDeserializerHeap::dispatch_mut(this); - let scope = - &mut crate::scope::CallbackScope::new(value_deserializer_heap.context); - let value_deserializer_impl = - value_deserializer_heap.value_deserializer_impl.as_mut(); - match value_deserializer_impl + let value_deserializer_heap = ValueDeserializerHeap::dispatch(this); + let scope = &mut CallbackScope::new(isolate.as_mut().unwrap()); + let context = Local::new(scope, &value_deserializer_heap.context); + let scope = &mut ContextScope::new(scope, context); + + match value_deserializer_heap + .value_deserializer_impl .get_shared_array_buffer_from_id(scope, transfer_id) { None => std::ptr::null(), @@ -65,17 +69,20 @@ pub unsafe extern "C" fn v8__ValueDeserializer__Delegate__GetSharedArrayBufferFr } #[no_mangle] -pub unsafe extern "C" fn v8__ValueDeserializer__Delegate__GetWasmModuleFromId( +unsafe extern "C" fn v8__ValueDeserializer__Delegate__GetWasmModuleFromId( this: &mut CxxValueDeserializerDelegate, - _isolate: *mut Isolate, + isolate: *mut Isolate, clone_id: u32, ) -> *const WasmModuleObject { - let value_deserializer_heap = ValueDeserializerHeap::dispatch_mut(this); - let scope = - &mut crate::scope::CallbackScope::new(value_deserializer_heap.context); - let value_deserializer_impl = - value_deserializer_heap.value_deserializer_impl.as_mut(); - match value_deserializer_impl.get_wasm_module_from_id(scope, clone_id) { + let value_deserializer_heap = ValueDeserializerHeap::dispatch(this); + let scope = &mut CallbackScope::new(isolate.as_mut().unwrap()); + let context = Local::new(scope, &value_deserializer_heap.context); + let scope = &mut ContextScope::new(scope, context); + + match value_deserializer_heap + .value_deserializer_impl + .get_wasm_module_from_id(scope, clone_id) + { None => std::ptr::null(), Some(x) => x.as_non_null().as_ptr(), } @@ -146,15 +153,19 @@ extern "C" { length: usize, data: *mut *const c_void, ) -> bool; + + fn v8__ValueDeserializer__GetWireFormatVersion( + this: *mut CxxValueDeserializer, + ) -> u32; } /// The ValueDeserializerImpl trait allows for /// custom callback functions used by v8. pub trait ValueDeserializerImpl { fn read_host_object<'s>( - &mut self, + &self, scope: &mut HandleScope<'s>, - _value_deserializer: &mut dyn ValueDeserializerHelper, + _value_deserializer: &dyn ValueDeserializerHelper, ) -> Option> { let msg = 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>( - &mut self, + &self, scope: &mut HandleScope<'s>, _transfer_id: u32, ) -> Option> { @@ -180,7 +191,7 @@ pub trait ValueDeserializerImpl { } fn get_wasm_module_from_id<'s>( - &mut self, + &self, scope: &mut HandleScope<'s>, _clone_id: u32, ) -> Option> { @@ -195,6 +206,10 @@ pub trait ValueDeserializerImpl { } } +fn cast_to_ptr(t: &T) -> *mut T { + t as *const _ as *mut _ +} + /// The ValueDeserializerHeap object contains all objects related to a /// 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 @@ -202,14 +217,14 @@ pub trait ValueDeserializerImpl { /// callback to fail. Additionally the deserializer and implementation are also /// pinned in memory because these have to be accessable from within the /// delegate callback methods. -pub struct ValueDeserializerHeap<'a, 's> { +pub struct ValueDeserializerHeap<'a> { value_deserializer_impl: Box, cxx_value_deserializer: CxxValueDeserializer, cxx_value_deserializer_delegate: CxxValueDeserializerDelegate, - context: Local<'s, Context>, + context: Global, } -impl<'a, 's> ValueDeserializerHeap<'a, 's> { +impl<'a> ValueDeserializerHeap<'a> { fn get_cxx_value_deserializer_delegate_offset( ) -> FieldOffset { let buf = std::mem::MaybeUninit::::uninit(); @@ -219,25 +234,15 @@ impl<'a, 's> ValueDeserializerHeap<'a, 's> { } /// Starting from 'this' pointer a ValueDeserializerHeap ref can be created - #[allow(dead_code)] pub unsafe fn dispatch( - value_serializer_delegate: &'s CxxValueDeserializerDelegate, + value_serializer_delegate: &CxxValueDeserializerDelegate, ) -> &Self { Self::get_cxx_value_deserializer_delegate_offset() .to_embedder::(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::(value_serializer_delegate) - } } -impl<'a, 's> Drop for ValueDeserializerHeap<'a, 's> { +impl<'a> Drop for ValueDeserializerHeap<'a> { fn drop(&mut self) { unsafe { 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 /// ValueDeserializerImpl trait to create custom deserialization logic. 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) -> Option { + fn read_header(&self, context: Local) -> Option { unsafe { v8__ValueDeserializer__ReadHeader( - self.get_cxx_value_deserializer(), + cast_to_ptr(self.get_cxx_value_deserializer()), context, ) } @@ -262,49 +267,49 @@ pub trait ValueDeserializerHelper { } fn read_value<'s>( - &mut self, + &self, context: Local<'s, Context>, ) -> Option> { unsafe { Local::from_raw(v8__ValueDeserializer__ReadValue( - self.get_cxx_value_deserializer(), + cast_to_ptr(self.get_cxx_value_deserializer()), context, )) } } - fn read_uint32(&mut self, value: &mut u32) -> bool { + fn read_uint32(&self, value: &mut u32) -> bool { unsafe { v8__ValueDeserializer__ReadUint32( - self.get_cxx_value_deserializer(), + cast_to_ptr(self.get_cxx_value_deserializer()), value, ) } } - fn read_uint64(&mut self, value: &mut u64) -> bool { + fn read_uint64(&self, value: &mut u64) -> bool { unsafe { v8__ValueDeserializer__ReadUint64( - self.get_cxx_value_deserializer(), + cast_to_ptr(self.get_cxx_value_deserializer()), value, ) } } - fn read_double(&mut self, value: &mut f64) -> bool { + fn read_double(&self, value: &mut f64) -> bool { unsafe { v8__ValueDeserializer__ReadDouble( - self.get_cxx_value_deserializer(), + cast_to_ptr(self.get_cxx_value_deserializer()), 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 ok = unsafe { v8__ValueDeserializer__ReadRawBytes( - self.get_cxx_value_deserializer(), + cast_to_ptr(self.get_cxx_value_deserializer()), length, &mut data, ) @@ -318,35 +323,43 @@ pub trait ValueDeserializerHelper { } fn transfer_array_buffer( - &mut self, + &self, transfer_id: u32, array_buffer: Local, ) { unsafe { v8__ValueDeserializer__TransferArrayBuffer( - self.get_cxx_value_deserializer(), + cast_to_ptr(self.get_cxx_value_deserializer()), transfer_id, 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 { - fn get_cxx_value_deserializer(&mut self) -> &mut CxxValueDeserializer { + fn get_cxx_value_deserializer(&self) -> &CxxValueDeserializer { self } } -impl<'a, 's> ValueDeserializerHelper for ValueDeserializerHeap<'a, 's> { - fn get_cxx_value_deserializer(&mut self) -> &mut CxxValueDeserializer { - &mut self.cxx_value_deserializer +impl<'a> ValueDeserializerHelper for ValueDeserializerHeap<'a> { + fn get_cxx_value_deserializer(&self) -> &CxxValueDeserializer { + &self.cxx_value_deserializer } } -impl<'a, 's> ValueDeserializerHelper for ValueDeserializer<'a, 's> { - fn get_cxx_value_deserializer(&mut self) -> &mut CxxValueDeserializer { - &mut self.value_deserializer_heap.cxx_value_deserializer +impl<'a> ValueDeserializerHelper for ValueDeserializer<'a> { + fn get_cxx_value_deserializer(&self) -> &CxxValueDeserializer { + &self.value_deserializer_heap.cxx_value_deserializer } } @@ -355,67 +368,80 @@ impl<'a, 's> ValueDeserializerHelper for ValueDeserializer<'a, 's> { /// The 'a lifetime is the lifetime of the ValueDeserializerImpl implementation. /// The 's lifetime is the lifetime of the HandleScope which is used to retrieve /// a Local<'s, Context> for the CallbackScopes -pub struct ValueDeserializer<'a, 's> { - value_deserializer_heap: Pin>>, +pub struct ValueDeserializer<'a> { + value_deserializer_heap: Pin>>, + // 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( - scope: &mut HandleScope<'s>, + scope: &mut HandleScope, value_deserializer_impl: Box, data: &[u8], ) -> Self { + let context = scope.get_current_context(); // create dummy ValueDeserializerHeap and move to heap + pin to address - let mut value_deserializer_heap = Box::pin(ValueDeserializerHeap { - value_deserializer_impl, - cxx_value_deserializer: CxxValueDeserializer { - _cxx_vtable: CxxVTable(std::ptr::null()), - }, - cxx_value_deserializer_delegate: CxxValueDeserializerDelegate { - _cxx_vtable: CxxVTable(std::ptr::null()), - }, - context: scope.get_current_context(), - }); + let value_deserializer_heap_ptr = + Box::into_raw(Box::new(ValueDeserializerHeap { + value_deserializer_impl, + cxx_value_deserializer: CxxValueDeserializer { + _cxx_vtable: CxxVTable(std::ptr::null()), + }, + cxx_value_deserializer_delegate: CxxValueDeserializerDelegate { + _cxx_vtable: CxxVTable(std::ptr::null()), + }, + context: Global::new(scope, context), + })); 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( - &mut value_deserializer_heap.cxx_value_deserializer_delegate - as *mut CxxValueDeserializerDelegate - as *mut std::mem::MaybeUninit, + delegate_ptr + .cast::>(), ); v8__ValueDeserializer__CONSTRUCT( - &mut value_deserializer_heap.cxx_value_deserializer - as *mut CxxValueDeserializer - as *mut std::mem::MaybeUninit, + deserializer_ptr.cast::>(), scope.get_isolate_ptr(), data.as_ptr(), 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 { value_deserializer_heap, + _phantom: std::marker::PhantomData, } } } -impl<'a, 's> ValueDeserializer<'a, 's> { +impl<'a> ValueDeserializer<'a> { pub fn set_supports_legacy_wire_format( - &mut self, + &self, supports_legacy_wire_format: bool, ) { unsafe { 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, ); } } pub fn read_value<'t>( - &mut self, + &self, context: Local<'t, Context>, ) -> Option> { self.value_deserializer_heap.read_value(context) diff --git a/src/value_serializer.rs b/src/value_serializer.rs index ca724fe0..20cddfa2 100644 --- a/src/value_serializer.rs +++ b/src/value_serializer.rs @@ -1,6 +1,9 @@ use crate::ArrayBuffer; +use crate::CallbackScope; use crate::Context; +use crate::ContextScope; use crate::Exception; +use crate::Global; use crate::HandleScope; use crate::Isolate; use crate::Local; @@ -16,6 +19,7 @@ use std::alloc::realloc; use std::alloc::Layout; use std::mem::MaybeUninit; use std::ptr::addr_of; +use std::sync::atomic::AtomicUsize; use crate::support::CxxVTable; use crate::support::FieldOffset; @@ -32,76 +36,82 @@ pub struct CxxValueSerializerDelegate { } #[no_mangle] -pub unsafe extern "C" fn v8__ValueSerializer__Delegate__ThrowDataCloneError( - this: &mut CxxValueSerializerDelegate, +unsafe extern "C" fn v8__ValueSerializer__Delegate__ThrowDataCloneError( + this: &CxxValueSerializerDelegate, message: Local, ) { - let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); - let scope = - &mut crate::scope::CallbackScope::new(value_serializer_heap.context); + let value_serializer_heap = ValueSerializerHeap::dispatch(this); + let scope = &mut CallbackScope::new( + 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_impl - .as_mut() .throw_data_clone_error(scope, message) } #[no_mangle] -pub unsafe extern "C" fn v8__ValueSerializer__Delegate__HasCustomHostObject( - this: &mut CxxValueSerializerDelegate, +unsafe extern "C" fn v8__ValueSerializer__Delegate__HasCustomHostObject( + this: &CxxValueSerializerDelegate, isolate: *mut Isolate, ) -> bool { - let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); + let value_serializer_heap = ValueSerializerHeap::dispatch(this); value_serializer_heap .value_serializer_impl - .as_mut() .has_custom_host_object(&mut *isolate) } #[no_mangle] -pub unsafe extern "C" fn v8__ValueSerializer__Delegate__IsHostObject( - this: &mut CxxValueSerializerDelegate, - _isolate: *mut Isolate, +unsafe extern "C" fn v8__ValueSerializer__Delegate__IsHostObject( + this: &CxxValueSerializerDelegate, + isolate: *mut Isolate, object: Local, ) -> MaybeBool { - let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); - let scope = - &mut crate::scope::CallbackScope::new(value_serializer_heap.context); - let value_serializer_impl = - value_serializer_heap.value_serializer_impl.as_mut(); - MaybeBool::from(value_serializer_impl.is_host_object(scope, object)) + let value_serializer_heap = ValueSerializerHeap::dispatch(this); + let scope = &mut CallbackScope::new(isolate.as_mut().unwrap()); + let context = Local::new(scope, &value_serializer_heap.context); + let scope = &mut ContextScope::new(scope, context); + + MaybeBool::from( + value_serializer_heap + .value_serializer_impl + .is_host_object(scope, object), + ) } #[no_mangle] -pub unsafe extern "C" fn v8__ValueSerializer__Delegate__WriteHostObject( - this: &mut CxxValueSerializerDelegate, - _isolate: *mut Isolate, +unsafe extern "C" fn v8__ValueSerializer__Delegate__WriteHostObject( + this: &CxxValueSerializerDelegate, + isolate: *mut Isolate, object: Local, ) -> MaybeBool { - let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); - let scope = - &mut crate::scope::CallbackScope::new(value_serializer_heap.context); + let value_serializer_heap = ValueSerializerHeap::dispatch(this); + let scope = &mut CallbackScope::new(isolate.as_mut().unwrap()); + let context = Local::new(scope, &value_serializer_heap.context); + let scope = &mut ContextScope::new(scope, context); 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( scope, object, - &mut value_serializer_heap.cxx_value_serializer, + &value_serializer_heap.cxx_value_serializer, )) } #[no_mangle] -pub unsafe extern "C" fn v8__ValueSerializer__Delegate__GetSharedArrayBufferId( - this: &mut CxxValueSerializerDelegate, - _isolate: *mut Isolate, +unsafe extern "C" fn v8__ValueSerializer__Delegate__GetSharedArrayBufferId( + this: &CxxValueSerializerDelegate, + isolate: *mut Isolate, shared_array_buffer: Local, clone_id: *mut u32, ) -> bool { - let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); - let scope = - &mut crate::scope::CallbackScope::new(value_serializer_heap.context); + let value_serializer_heap = ValueSerializerHeap::dispatch(this); + let scope = &mut CallbackScope::new(isolate.as_mut().unwrap()); + let context = Local::new(scope, &value_serializer_heap.context); + let scope = &mut ContextScope::new(scope, context); match value_serializer_heap .value_serializer_impl - .as_mut() .get_shared_array_buffer_id(scope, shared_array_buffer) { Some(x) => { @@ -113,18 +123,18 @@ pub unsafe extern "C" fn v8__ValueSerializer__Delegate__GetSharedArrayBufferId( } #[no_mangle] -pub unsafe extern "C" fn v8__ValueSerializer__Delegate__GetWasmModuleTransferId( - this: &mut CxxValueSerializerDelegate, - _isolate: *mut Isolate, +unsafe extern "C" fn v8__ValueSerializer__Delegate__GetWasmModuleTransferId( + this: &CxxValueSerializerDelegate, + isolate: *mut Isolate, module: Local, transfer_id: *mut u32, ) -> bool { - let value_serializer_heap = ValueSerializerHeap::dispatch_mut(this); - let scope = - &mut crate::scope::CallbackScope::new(value_serializer_heap.context); + let value_serializer_heap = ValueSerializerHeap::dispatch(this); + let scope = &mut CallbackScope::new(isolate.as_mut().unwrap()); + let context = Local::new(scope, value_serializer_heap.context.clone()); + let scope = &mut ContextScope::new(scope, context); match value_serializer_heap .value_serializer_impl - .as_mut() .get_wasm_module_transfer_id(scope, module) { Some(x) => { @@ -136,36 +146,41 @@ pub unsafe extern "C" fn v8__ValueSerializer__Delegate__GetWasmModuleTransferId( } #[no_mangle] -pub unsafe extern "C" fn v8__ValueSerializer__Delegate__ReallocateBufferMemory( - this: &mut CxxValueSerializerDelegate, +unsafe extern "C" fn v8__ValueSerializer__Delegate__ReallocateBufferMemory( + this: &CxxValueSerializerDelegate, old_buffer: *mut c_void, size: usize, actual_size: *mut usize, ) -> *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 layout = Layout::from_size_align(size, 1).unwrap(); alloc(layout) } 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) }; - base.buffer_size = size; - *actual_size = size; new_buffer as *mut c_void } #[no_mangle] -pub unsafe extern "C" fn v8__ValueSerializer__Delegate__FreeBufferMemory( +unsafe extern "C" fn v8__ValueSerializer__Delegate__FreeBufferMemory( this: &mut CxxValueSerializerDelegate, buffer: *mut c_void, ) { - let base = ValueSerializerHeap::dispatch_mut(this); + let base = ValueSerializerHeap::dispatch(this); 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) }; } @@ -226,23 +241,27 @@ extern "C" { source: *const c_void, length: usize, ); + fn v8__ValueSerializer__SetTreatArrayBufferViewsAsHostObjects( + this: *mut CxxValueSerializer, + mode: bool, + ); } /// The ValueSerializerImpl trait allows for /// custom callback functions used by v8. pub trait ValueSerializerImpl { fn throw_data_clone_error<'s>( - &mut self, + &self, scope: &mut HandleScope<'s>, 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 } fn is_host_object<'s>( - &mut self, + &self, scope: &mut HandleScope<'s>, _object: Local<'s, Object>, ) -> Option { @@ -255,10 +274,10 @@ pub trait ValueSerializerImpl { } fn write_host_object<'s>( - &mut self, + &self, scope: &mut HandleScope<'s>, _object: Local<'s, Object>, - _value_serializer: &mut dyn ValueSerializerHelper, + _value_serializer: &dyn ValueSerializerHelper, ) -> Option { let msg = String::new(scope, "Deno serializer: write_host_object not implemented") @@ -269,7 +288,7 @@ pub trait ValueSerializerImpl { } fn get_shared_array_buffer_id<'s>( - &mut self, + &self, _scope: &mut HandleScope<'s>, _shared_array_buffer: Local<'s, SharedArrayBuffer>, ) -> Option { @@ -277,7 +296,7 @@ pub trait ValueSerializerImpl { } fn get_wasm_module_transfer_id( - &mut self, + &self, scope: &mut HandleScope<'_>, _module: Local, ) -> Option { @@ -299,15 +318,16 @@ pub trait ValueSerializerImpl { /// to fail. Additionally the serializer and implementation are also pinned /// in memory because these have to be accessable from within the delegate /// callback methods. -pub struct ValueSerializerHeap<'a, 's> { +pub struct ValueSerializerHeap<'a> { value_serializer_impl: Box, cxx_value_serializer_delegate: CxxValueSerializerDelegate, cxx_value_serializer: CxxValueSerializer, - buffer_size: usize, - context: Local<'s, Context>, + buffer_size: AtomicUsize, + context: Global, + isolate_ptr: *mut Isolate, } -impl<'a, 's> ValueSerializerHeap<'a, 's> { +impl<'a> ValueSerializerHeap<'a> { fn get_cxx_value_serializer_delegate_offset( ) -> FieldOffset { let buf = std::mem::MaybeUninit::::uninit(); @@ -317,50 +337,46 @@ impl<'a, 's> ValueSerializerHeap<'a, 's> { } /// Starting from 'this' pointer a ValueSerializerHeap ref can be created - #[allow(dead_code)] pub unsafe fn dispatch( - value_serializer_delegate: &'s CxxValueSerializerDelegate, + value_serializer_delegate: &CxxValueSerializerDelegate, ) -> &Self { Self::get_cxx_value_serializer_delegate_offset() .to_embedder::(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::(value_serializer_delegate) - } } -impl<'a, 's> Drop for ValueSerializerHeap<'a, 's> { +impl<'a> Drop for ValueSerializerHeap<'a> { fn drop(&mut self) { unsafe { v8__ValueSerializer__DESTRUCT(&mut self.cxx_value_serializer) }; } } +fn cast_to_ptr(x: &T) -> *mut T { + x as *const T as *mut T +} + /// Trait used for direct write to the serialization buffer. /// Mostly used by the write_host_object callback function in the /// ValueSerializerImpl trait to create custom serialization logic. 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 { - v8__ValueSerializer__WriteHeader(self.get_cxx_value_serializer()) + v8__ValueSerializer__WriteHeader(cast_to_ptr( + self.get_cxx_value_serializer(), + )) }; } fn write_value( - &mut self, + &self, context: Local, value: Local, ) -> Option { unsafe { v8__ValueSerializer__WriteValue( - self.get_cxx_value_serializer(), + cast_to_ptr(self.get_cxx_value_serializer()), context, value, ) @@ -368,28 +384,37 @@ pub trait ValueSerializerHelper { .into() } - fn write_uint32(&mut self, value: u32) { + fn write_uint32(&self, value: u32) { 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 { - 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 { - 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 { v8__ValueSerializer__WriteRawBytes( - self.get_cxx_value_serializer(), + cast_to_ptr(self.get_cxx_value_serializer()), source.as_ptr() as *const _, source.len(), ) @@ -397,40 +422,52 @@ pub trait ValueSerializerHelper { } fn transfer_array_buffer( - &mut self, + &self, transfer_id: u32, array_buffer: Local, ) { unsafe { v8__ValueSerializer__TransferArrayBuffer( - self.get_cxx_value_serializer(), + cast_to_ptr(self.get_cxx_value_serializer()), transfer_id, 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 { - fn get_cxx_value_serializer(&mut self) -> &mut CxxValueSerializer { + fn get_cxx_value_serializer(&self) -> &CxxValueSerializer { self } } -impl<'a, 's> ValueSerializerHelper for ValueSerializerHeap<'a, 's> { - fn get_cxx_value_serializer(&mut self) -> &mut CxxValueSerializer { - &mut self.cxx_value_serializer +impl<'a> ValueSerializerHelper for ValueSerializerHeap<'a> { + fn get_cxx_value_serializer(&self) -> &CxxValueSerializer { + &self.cxx_value_serializer } } -impl<'a, 's> ValueSerializerHelper for ValueSerializer<'a, 's> { - fn get_cxx_value_serializer(&mut self) -> &mut CxxValueSerializer { - &mut self.value_serializer_heap.cxx_value_serializer +impl<'a> ValueSerializerHelper for ValueSerializer<'a> { + fn get_cxx_value_serializer(&self) -> &CxxValueSerializer { + &self.value_serializer_heap.cxx_value_serializer } } -pub struct ValueSerializer<'a, 's> { - value_serializer_heap: Pin>>, +pub struct ValueSerializer<'a> { + value_serializer_heap: Pin>>, + // 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 @@ -438,62 +475,80 @@ pub struct ValueSerializer<'a, 's> { /// The 'a lifetime is the lifetime of the ValueSerializerImpl implementation. /// The 's lifetime is the lifetime of the HandleScope which is used to retrieve /// a Local<'s, Context> for the CallbackScopes -impl<'a, 's> ValueSerializer<'a, 's> { +impl<'a> ValueSerializer<'a> { pub fn new( - scope: &mut HandleScope<'s>, + scope: &mut HandleScope, value_serializer_impl: Box, ) -> Self { + let context = scope.get_current_context(); // create dummy ValueSerializerHeap 'a, and move to heap + pin to address - let mut value_serializer_heap = Box::pin(ValueSerializerHeap { - value_serializer_impl, - cxx_value_serializer: CxxValueSerializer { - _cxx_vtable: CxxVTable(std::ptr::null()), - }, - cxx_value_serializer_delegate: CxxValueSerializerDelegate { - _cxx_vtable: CxxVTable(std::ptr::null()), - }, - buffer_size: 0, - context: scope.get_current_context(), - }); + let value_serializer_heap_ptr = + Box::into_raw(Box::new(ValueSerializerHeap { + value_serializer_impl, + cxx_value_serializer: CxxValueSerializer { + _cxx_vtable: CxxVTable(std::ptr::null()), + }, + cxx_value_serializer_delegate: CxxValueSerializerDelegate { + _cxx_vtable: CxxVTable(std::ptr::null()), + }, + buffer_size: AtomicUsize::new(0), + context: Global::new(scope, context), + isolate_ptr: scope.get_isolate_ptr(), + })); 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( - &mut value_serializer_heap.cxx_value_serializer_delegate - as *mut CxxValueSerializerDelegate - as *mut std::mem::MaybeUninit, + delegate_ptr + .cast::>(), ); v8__ValueSerializer__CONSTRUCT( - &mut value_serializer_heap.cxx_value_serializer - as *mut CxxValueSerializer - as *mut std::mem::MaybeUninit, + serializer_ptr.cast::>(), 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 { value_serializer_heap, + _phantom: std::marker::PhantomData, } } } -impl<'a, 's> ValueSerializer<'a, 's> { - pub fn release(mut self) -> Vec { +impl<'a> ValueSerializer<'a> { + pub fn release(&self) -> Vec { unsafe { let mut size: usize = 0; let mut ptr: *mut u8 = &mut 0; v8__ValueSerializer__Release( - &mut self.value_serializer_heap.cxx_value_serializer, + cast_to_ptr(self.get_cxx_value_serializer()), &mut ptr, &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( - &mut self, + &self, context: Local, value: Local, ) -> Option { diff --git a/tests/test_api.rs b/tests/test_api.rs index b443ade2..42db6827 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -7952,14 +7952,15 @@ fn bigint() { type ArrayBuffers = Vec>; struct Custom1Value<'a> { - array_buffers: &'a mut ArrayBuffers, + array_buffers: RefCell<&'a mut ArrayBuffers>, } impl<'a> Custom1Value<'a> { fn serializer<'s>( scope: &mut v8::HandleScope<'s>, 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 })) } @@ -7967,7 +7968,8 @@ impl<'a> Custom1Value<'a> { scope: &mut v8::HandleScope<'s>, data: &[u8], 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) } } @@ -7975,7 +7977,7 @@ impl<'a> Custom1Value<'a> { impl<'a> v8::ValueSerializerImpl for Custom1Value<'a> { #[allow(unused_variables)] fn throw_data_clone_error<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, message: v8::Local<'s, v8::String>, ) { @@ -7985,23 +7987,21 @@ impl<'a> v8::ValueSerializerImpl for Custom1Value<'a> { #[allow(unused_variables)] fn get_shared_array_buffer_id<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, shared_array_buffer: v8::Local<'s, v8::SharedArrayBuffer>, ) -> Option { - self - .array_buffers - .push(v8::SharedArrayBuffer::get_backing_store( - &shared_array_buffer, - )); - Some((self.array_buffers.len() as u32) - 1) + self.array_buffers.borrow_mut().push( + v8::SharedArrayBuffer::get_backing_store(&shared_array_buffer), + ); + Some((self.array_buffers.borrow().len() as u32) - 1) } fn write_host_object<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, object: v8::Local<'s, v8::Object>, - value_serializer: &mut dyn v8::ValueSerializerHelper, + value_serializer: &dyn v8::ValueSerializerHelper, ) -> Option { let key = v8::String::new(scope, "hostObject").unwrap(); let value = object @@ -8017,21 +8017,26 @@ impl<'a> v8::ValueSerializerImpl for Custom1Value<'a> { impl<'a> v8::ValueDeserializerImpl for Custom1Value<'a> { #[allow(unused_variables)] fn get_shared_array_buffer_from_id<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, transfer_id: u32, ) -> Option> { - 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( scope, - backing_store, + &backing_store, )) } fn read_host_object<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, - value_deserializer: &mut dyn v8::ValueDeserializerHelper, + value_deserializer: &dyn v8::ValueDeserializerHelper, ) -> Option> { let mut value = 0; value_deserializer.read_uint32(&mut value); @@ -8060,8 +8065,7 @@ fn value_serializer_and_deserializer() { let scope = &mut v8::ContextScope::new(scope, context); let buffer; { - let mut value_serializer = - Custom1Value::serializer(scope, &mut array_buffers); + let value_serializer = Custom1Value::serializer(scope, &mut array_buffers); value_serializer.write_header(); value_serializer.write_double(55.44); value_serializer.write_uint32(22); @@ -8071,7 +8075,7 @@ fn value_serializer_and_deserializer() { let mut double: f64 = 0.0; let mut int32: u32 = 0; { - let mut value_deserializer = + let value_deserializer = Custom1Value::deserializer(scope, &buffer, &mut array_buffers); assert_eq!(value_deserializer.read_header(context), Some(true)); assert!(value_deserializer.read_double(&mut double)); @@ -8117,8 +8121,7 @@ fn value_serializer_and_deserializer_js_objects() { ]"#, ) .unwrap(); - let mut value_serializer = - Custom1Value::serializer(scope, &mut array_buffers); + let value_serializer = Custom1Value::serializer(scope, &mut array_buffers); value_serializer.write_header(); 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 scope = &mut v8::ContextScope::new(scope, context); - let mut value_deserializer = + let value_deserializer = Custom1Value::deserializer(scope, &buffer, &mut array_buffers); assert_eq!(value_deserializer.read_header(context), Some(true)); let name = v8::String::new(scope, "objects").unwrap(); @@ -8224,8 +8227,7 @@ fn value_serializer_and_deserializer_array_buffers() { }"#, ) .unwrap(); - let mut value_serializer = - Custom1Value::serializer(scope, &mut array_buffers); + let value_serializer = Custom1Value::serializer(scope, &mut array_buffers); assert_eq!(value_serializer.write_value(context, objects), Some(true)); buffer = value_serializer.release(); @@ -8240,7 +8242,7 @@ fn value_serializer_and_deserializer_array_buffers() { let context = v8::Context::new(scope, Default::default()); let scope = &mut v8::ContextScope::new(scope, context); - let mut value_deserializer = + let value_deserializer = Custom1Value::deserializer(scope, &buffer, &mut array_buffers); let name = v8::String::new(scope, "objects").unwrap(); let objects: v8::Local = @@ -8286,8 +8288,7 @@ fn value_serializer_and_deserializer_embedder_host_object() { let value = v8::Integer::new_from_unsigned(scope, expected); host_object.set(scope, key.into(), value.into()); - let mut value_serializer = - Custom1Value::serializer(scope, &mut array_buffers); + let value_serializer = Custom1Value::serializer(scope, &mut array_buffers); assert_eq!( value_serializer.write_value(context, host_object.into()), Some(true) @@ -8305,7 +8306,7 @@ fn value_serializer_and_deserializer_embedder_host_object() { let context = v8::Context::new(scope, Default::default()); let scope = &mut v8::ContextScope::new(scope, context); - let mut value_deserializer = + let value_deserializer = Custom1Value::deserializer(scope, &buffer, &mut array_buffers); let host_object_out = value_deserializer .read_value(context) @@ -8328,7 +8329,7 @@ struct Custom2Value {} impl<'a> Custom2Value { fn serializer<'s>( scope: &mut v8::HandleScope<'s>, - ) -> v8::ValueSerializer<'a, 's> { + ) -> v8::ValueSerializer<'a> { v8::ValueSerializer::new(scope, Box::new(Self {})) } } @@ -8336,7 +8337,7 @@ impl<'a> Custom2Value { impl v8::ValueSerializerImpl for Custom2Value { #[allow(unused_variables)] fn throw_data_clone_error<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, message: v8::Local<'s, v8::String>, ) { @@ -8367,7 +8368,7 @@ fn value_serializer_not_implemented() { }"#, ) .unwrap(); - let mut value_serializer = Custom2Value::serializer(scope); + let value_serializer = Custom2Value::serializer(scope); assert_eq!(value_serializer.write_value(context, objects), None); assert!(scope.exception().is_some()); @@ -8388,14 +8389,14 @@ struct Custom3Value {} impl<'a> Custom3Value { fn serializer<'s>( scope: &mut v8::HandleScope<'s>, - ) -> v8::ValueSerializer<'a, 's> { + ) -> v8::ValueSerializer<'a> { v8::ValueSerializer::new(scope, Box::new(Self {})) } fn deserializer<'s>( scope: &mut v8::HandleScope<'s>, data: &[u8], - ) -> v8::ValueDeserializer<'a, 's> { + ) -> v8::ValueDeserializer<'a> { v8::ValueDeserializer::new(scope, Box::new(Self {}), data) } } @@ -8403,7 +8404,7 @@ impl<'a> Custom3Value { impl v8::ValueSerializerImpl for Custom3Value { #[allow(unused_variables)] fn throw_data_clone_error<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, message: v8::Local<'s, v8::String>, ) { @@ -8411,12 +8412,12 @@ impl v8::ValueSerializerImpl for Custom3Value { 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 } fn is_host_object<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, object: v8::Local<'s, v8::Object>, ) -> Option { @@ -8425,10 +8426,10 @@ impl v8::ValueSerializerImpl for Custom3Value { } fn write_host_object<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, object: v8::Local<'s, v8::Object>, - value_serializer: &mut dyn v8::ValueSerializerHelper, + value_serializer: &dyn v8::ValueSerializerHelper, ) -> Option { let key = v8::String::new(scope, "hostObject").unwrap(); let value = object @@ -8443,9 +8444,9 @@ impl v8::ValueSerializerImpl for Custom3Value { impl v8::ValueDeserializerImpl for Custom3Value { fn read_host_object<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, - value_deserializer: &mut dyn v8::ValueDeserializerHelper, + value_deserializer: &dyn v8::ValueDeserializerHelper, ) -> Option> { let mut value = 0; 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); host_object.set(scope, key.into(), value.into()); - let mut value_serializer = Custom3Value::serializer(scope); + let value_serializer = Custom3Value::serializer(scope); assert_eq!( value_serializer.write_value(context, host_object.into()), Some(true) @@ -8493,7 +8494,7 @@ fn value_serializer_and_deserializer_custom_host_object() { let context = v8::Context::new(scope, Default::default()); 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 .read_value(context) .unwrap() @@ -11743,17 +11744,17 @@ fn allow_scope_in_read_host_object() { struct Serializer; impl v8::ValueSerializerImpl for Serializer { fn write_host_object<'s>( - &mut self, + &self, _scope: &mut v8::HandleScope<'s>, _object: v8::Local<'s, v8::Object>, - _value_serializer: &mut dyn v8::ValueSerializerHelper, + _value_serializer: &dyn v8::ValueSerializerHelper, ) -> Option { // Doesn't look at the object or writes anything. Some(true) } fn throw_data_clone_error<'s>( - &mut self, + &self, _scope: &mut v8::HandleScope<'s>, _message: v8::Local<'s, v8::String>, ) { @@ -11764,9 +11765,9 @@ fn allow_scope_in_read_host_object() { struct Deserializer; impl v8::ValueDeserializerImpl for Deserializer { fn read_host_object<'s>( - &mut self, + &self, scope: &mut v8::HandleScope<'s>, - _value_deserializer: &mut dyn v8::ValueDeserializerHelper, + _value_deserializer: &dyn v8::ValueDeserializerHelper, ) -> Option> { let scope2 = &mut v8::AllowJavascriptExecutionScope::new(scope); 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 serialized = { - let mut serializer = - v8::ValueSerializer::new(&mut scope, Box::new(Serializer)); + let serializer = v8::ValueSerializer::new(&mut scope, Box::new(Serializer)); serializer .write_value(context, v8::Object::new(&mut scope).into()) .unwrap(); serializer.release() }; - let mut deserializer = + let deserializer = v8::ValueDeserializer::new(&mut scope, Box::new(Deserializer), &serialized); let value = deserializer.read_value(context).unwrap(); assert!(value.is_object());