mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-21 15:04:33 -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:
parent
6a6064d9ff
commit
5989346753
4 changed files with 360 additions and 269 deletions
|
@ -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
|
||||
|
|
|
@ -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<Local<'s, Object>> {
|
||||
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<Local<'s, SharedArrayBuffer>> {
|
||||
|
@ -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<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
|
||||
/// 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<dyn ValueDeserializerImpl + 'a>,
|
||||
cxx_value_deserializer: CxxValueDeserializer,
|
||||
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(
|
||||
) -> FieldOffset<CxxValueDeserializerDelegate> {
|
||||
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
|
||||
#[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::<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) {
|
||||
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<Context>) -> Option<bool> {
|
||||
fn read_header(&self, context: Local<Context>) -> Option<bool> {
|
||||
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<Local<'s, Value>> {
|
||||
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<ArrayBuffer>,
|
||||
) {
|
||||
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<Box<ValueDeserializerHeap<'a, 's>>>,
|
||||
pub struct ValueDeserializer<'a> {
|
||||
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>(
|
||||
scope: &mut HandleScope<'s>,
|
||||
scope: &mut HandleScope,
|
||||
value_deserializer_impl: Box<D>,
|
||||
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<CxxValueDeserializerDelegate>,
|
||||
delegate_ptr
|
||||
.cast::<std::mem::MaybeUninit<CxxValueDeserializerDelegate>>(),
|
||||
);
|
||||
|
||||
v8__ValueDeserializer__CONSTRUCT(
|
||||
&mut value_deserializer_heap.cxx_value_deserializer
|
||||
as *mut CxxValueDeserializer
|
||||
as *mut std::mem::MaybeUninit<CxxValueDeserializer>,
|
||||
deserializer_ptr.cast::<std::mem::MaybeUninit<CxxValueDeserializer>>(),
|
||||
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<Local<'t, Value>> {
|
||||
self.value_deserializer_heap.read_value(context)
|
||||
|
|
|
@ -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<String>,
|
||||
) {
|
||||
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<Object>,
|
||||
) -> 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<Object>,
|
||||
) -> 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<SharedArrayBuffer>,
|
||||
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<WasmModuleObject>,
|
||||
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<bool> {
|
||||
|
@ -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<bool> {
|
||||
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<u32> {
|
||||
|
@ -277,7 +296,7 @@ pub trait ValueSerializerImpl {
|
|||
}
|
||||
|
||||
fn get_wasm_module_transfer_id(
|
||||
&mut self,
|
||||
&self,
|
||||
scope: &mut HandleScope<'_>,
|
||||
_module: Local<WasmModuleObject>,
|
||||
) -> Option<u32> {
|
||||
|
@ -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<dyn ValueSerializerImpl + 'a>,
|
||||
cxx_value_serializer_delegate: CxxValueSerializerDelegate,
|
||||
cxx_value_serializer: CxxValueSerializer,
|
||||
buffer_size: usize,
|
||||
context: Local<'s, Context>,
|
||||
buffer_size: AtomicUsize,
|
||||
context: Global<Context>,
|
||||
isolate_ptr: *mut Isolate,
|
||||
}
|
||||
|
||||
impl<'a, 's> ValueSerializerHeap<'a, 's> {
|
||||
impl<'a> ValueSerializerHeap<'a> {
|
||||
fn get_cxx_value_serializer_delegate_offset(
|
||||
) -> FieldOffset<CxxValueSerializerDelegate> {
|
||||
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
|
||||
#[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::<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) {
|
||||
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.
|
||||
/// 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<Context>,
|
||||
value: Local<Value>,
|
||||
) -> Option<bool> {
|
||||
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<ArrayBuffer>,
|
||||
) {
|
||||
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<Box<ValueSerializerHeap<'a, 's>>>,
|
||||
pub struct ValueSerializer<'a> {
|
||||
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
|
||||
|
@ -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<D: ValueSerializerImpl + 'a>(
|
||||
scope: &mut HandleScope<'s>,
|
||||
scope: &mut HandleScope,
|
||||
value_serializer_impl: Box<D>,
|
||||
) -> 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<CxxValueSerializerDelegate>,
|
||||
delegate_ptr
|
||||
.cast::<std::mem::MaybeUninit<CxxValueSerializerDelegate>>(),
|
||||
);
|
||||
|
||||
v8__ValueSerializer__CONSTRUCT(
|
||||
&mut value_serializer_heap.cxx_value_serializer
|
||||
as *mut CxxValueSerializer
|
||||
as *mut std::mem::MaybeUninit<CxxValueSerializer>,
|
||||
serializer_ptr.cast::<std::mem::MaybeUninit<CxxValueSerializer>>(),
|
||||
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<u8> {
|
||||
impl<'a> ValueSerializer<'a> {
|
||||
pub fn release(&self) -> Vec<u8> {
|
||||
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<Context>,
|
||||
value: Local<Value>,
|
||||
) -> Option<bool> {
|
||||
|
|
|
@ -7952,14 +7952,15 @@ fn bigint() {
|
|||
type ArrayBuffers = Vec<v8::SharedRef<v8::BackingStore>>;
|
||||
|
||||
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<u32> {
|
||||
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<bool> {
|
||||
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<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(
|
||||
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<v8::Local<'s, v8::Object>> {
|
||||
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<v8::Value> =
|
||||
|
@ -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<bool> {
|
||||
|
@ -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<bool> {
|
||||
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<v8::Local<'s, v8::Object>> {
|
||||
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<bool> {
|
||||
// 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<v8::Local<'s, v8::Object>> {
|
||||
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());
|
||||
|
|
Loading…
Reference in a new issue