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

feat: Support custom host objects in ValueSerializer (#1322)

Add v8::ValueSerializerImpl::{has_custom_host_object,is_host_object} 
equivalents for v8::ValueSerializer::Delegate::{HasCustomHostObject,IsCustomHostObject}.

This enables serializing custom host objects without embedder fields.
This commit is contained in:
Laurence Rowe 2023-11-20 15:24:59 -08:00 committed by GitHub
parent 75a2646b89
commit ec2c901895
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 266 additions and 7 deletions

View file

@ -3197,6 +3197,13 @@ extern "C" {
void v8__ValueSerializer__Delegate__ThrowDataCloneError(
v8::ValueSerializer::Delegate* self, v8::Local<v8::String> message);
bool v8__ValueSerializer__Delegate__HasCustomHostObject(
v8::ValueSerializer::Delegate* self, v8::Isolate* isolate);
MaybeBool v8__ValueSerializer__Delegate__IsHostObject(
v8::ValueSerializer::Delegate* self, v8::Isolate* isolate,
v8::Local<v8::Object> object);
MaybeBool v8__ValueSerializer__Delegate__WriteHostObject(
v8::ValueSerializer::Delegate* self, v8::Isolate* isolate,
v8::Local<v8::Object> object);
@ -3222,6 +3229,16 @@ struct v8__ValueSerializer__Delegate : public v8::ValueSerializer::Delegate {
v8__ValueSerializer__Delegate__ThrowDataCloneError(this, message);
}
bool HasCustomHostObject(v8::Isolate* isolate) override {
return v8__ValueSerializer__Delegate__HasCustomHostObject(this, isolate);
}
v8::Maybe<bool> IsHostObject(v8::Isolate* isolate,
v8::Local<v8::Object> object) override {
return maybe_bool_to_maybe(
v8__ValueSerializer__Delegate__IsHostObject(this, isolate, object));
}
v8::Maybe<bool> WriteHostObject(v8::Isolate* isolate,
v8::Local<v8::Object> object) override {
return maybe_bool_to_maybe(

View file

@ -45,6 +45,32 @@ pub unsafe extern "C" fn v8__ValueSerializer__Delegate__ThrowDataCloneError(
.throw_data_clone_error(scope, message)
}
#[no_mangle]
pub unsafe extern "C" fn v8__ValueSerializer__Delegate__HasCustomHostObject(
this: &mut CxxValueSerializerDelegate,
isolate: *mut Isolate,
) -> bool {
let value_serializer_heap = ValueSerializerHeap::dispatch_mut(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,
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))
}
#[no_mangle]
pub unsafe extern "C" fn v8__ValueSerializer__Delegate__WriteHostObject(
this: &mut CxxValueSerializerDelegate,
@ -211,6 +237,23 @@ pub trait ValueSerializerImpl {
message: Local<'s, String>,
);
fn has_custom_host_object(&mut self, _isolate: &mut Isolate) -> bool {
false
}
fn is_host_object<'s>(
&mut self,
scope: &mut HandleScope<'s>,
_object: Local<'s, Object>,
) -> Option<bool> {
let msg =
String::new(scope, "Deno serializer: is_host_object not implemented")
.unwrap();
let exc = Exception::error(scope, msg);
scope.throw_exception(exc);
None
}
fn write_host_object<'s>(
&mut self,
scope: &mut HandleScope<'s>,

View file

@ -7731,12 +7731,18 @@ impl<'a> v8::ValueSerializerImpl for Custom1Value<'a> {
fn write_host_object<'s>(
&mut self,
_scope: &mut v8::HandleScope<'s>,
_object: v8::Local<'s, v8::Object>,
scope: &mut v8::HandleScope<'s>,
object: v8::Local<'s, v8::Object>,
value_serializer: &mut dyn v8::ValueSerializerHelper,
) -> Option<bool> {
value_serializer.write_uint64(1);
None
let key = v8::String::new(scope, "hostObject").unwrap();
let value = object
.get(scope, key.into())
.unwrap()
.uint32_value(scope)
.unwrap();
value_serializer.write_uint32(value);
Some(true)
}
}
@ -7756,12 +7762,18 @@ impl<'a> v8::ValueDeserializerImpl for Custom1Value<'a> {
fn read_host_object<'s>(
&mut self,
_scope: &mut v8::HandleScope<'s>,
scope: &mut v8::HandleScope<'s>,
value_deserializer: &mut dyn v8::ValueDeserializerHelper,
) -> Option<v8::Local<'s, v8::Object>> {
let mut value = 0;
value_deserializer.read_uint64(&mut value);
None
value_deserializer.read_uint32(&mut value);
let template = v8::ObjectTemplate::new(scope);
template.set_internal_field_count(1);
let host_object = template.new_instance(scope).unwrap();
let key = v8::String::new(scope, "readHostObject").unwrap();
let value = v8::Integer::new_from_unsigned(scope, value);
host_object.set(scope, key.into(), value.into());
Some(host_object)
}
}
@ -7985,6 +7997,64 @@ fn value_serializer_and_deserializer_array_buffers() {
}
}
#[test]
fn value_serializer_and_deserializer_embedder_host_object() {
let buffer;
let expected: u32 = 123;
let mut array_buffers = ArrayBuffers::new();
{
let _setup_guard = setup::parallel_test();
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
let template = v8::ObjectTemplate::new(scope);
template.set_internal_field_count(1);
let host_object = template.new_instance(scope).unwrap();
let key = v8::String::new(scope, "hostObject").unwrap();
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);
assert_eq!(
value_serializer.write_value(context, host_object.into()),
Some(true)
);
buffer = value_serializer.release();
}
{
let _setup_guard = setup::parallel_test();
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
let mut value_deserializer =
Custom1Value::deserializer(scope, &buffer, &mut array_buffers);
let host_object_out = value_deserializer
.read_value(context)
.unwrap()
.to_object(scope)
.unwrap();
drop(value_deserializer);
let key = v8::String::new(scope, "readHostObject").unwrap();
let value = host_object_out
.get(scope, key.into())
.unwrap()
.uint32_value(scope)
.unwrap();
assert_eq!(value, expected);
}
}
struct Custom2Value {}
impl<'a> Custom2Value {
@ -8044,6 +8114,135 @@ fn value_serializer_not_implemented() {
);
}
struct Custom3Value {}
impl<'a> Custom3Value {
fn serializer<'s>(
scope: &mut v8::HandleScope<'s>,
) -> v8::ValueSerializer<'a, 's> {
v8::ValueSerializer::new(scope, Box::new(Self {}))
}
fn deserializer<'s>(
scope: &mut v8::HandleScope<'s>,
data: &[u8],
) -> v8::ValueDeserializer<'a, 's> {
v8::ValueDeserializer::new(scope, Box::new(Self {}), data)
}
}
impl v8::ValueSerializerImpl for Custom3Value {
#[allow(unused_variables)]
fn throw_data_clone_error<'s>(
&mut self,
scope: &mut v8::HandleScope<'s>,
message: v8::Local<'s, v8::String>,
) {
let error = v8::Exception::error(scope, message);
scope.throw_exception(error);
}
fn has_custom_host_object(&mut self, _isolate: &mut v8::Isolate) -> bool {
true
}
fn is_host_object<'s>(
&mut self,
scope: &mut v8::HandleScope<'s>,
object: v8::Local<'s, v8::Object>,
) -> Option<bool> {
let key = v8::String::new(scope, "hostObject").unwrap();
object.has_own_property(scope, key.into())
}
fn write_host_object<'s>(
&mut self,
scope: &mut v8::HandleScope<'s>,
object: v8::Local<'s, v8::Object>,
value_serializer: &mut dyn v8::ValueSerializerHelper,
) -> Option<bool> {
let key = v8::String::new(scope, "hostObject").unwrap();
let value = object
.get(scope, key.into())
.unwrap()
.uint32_value(scope)
.unwrap();
value_serializer.write_uint32(value);
Some(true)
}
}
impl v8::ValueDeserializerImpl for Custom3Value {
fn read_host_object<'s>(
&mut self,
scope: &mut v8::HandleScope<'s>,
value_deserializer: &mut dyn v8::ValueDeserializerHelper,
) -> Option<v8::Local<'s, v8::Object>> {
let mut value = 0;
value_deserializer.read_uint32(&mut value);
let host_object = v8::Object::new(scope);
let key = v8::String::new(scope, "readHostObject").unwrap();
let value = v8::Integer::new_from_unsigned(scope, value);
host_object.set(scope, key.into(), value.into());
Some(host_object)
}
}
#[test]
fn value_serializer_and_deserializer_custom_host_object() {
let buffer;
let expected: u32 = 123;
{
let _setup_guard = setup::parallel_test();
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
let host_object = v8::Object::new(scope);
let key = v8::String::new(scope, "hostObject").unwrap();
let value = v8::Integer::new_from_unsigned(scope, expected);
host_object.set(scope, key.into(), value.into());
let mut value_serializer = Custom3Value::serializer(scope);
assert_eq!(
value_serializer.write_value(context, host_object.into()),
Some(true)
);
buffer = value_serializer.release();
}
{
let _setup_guard = setup::parallel_test();
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
let mut value_deserializer = Custom3Value::deserializer(scope, &buffer);
let host_object_out = value_deserializer
.read_value(context)
.unwrap()
.to_object(scope)
.unwrap();
drop(value_deserializer);
let key = v8::String::new(scope, "readHostObject").unwrap();
let has_prop = host_object_out.has_own_property(scope, key.into()).unwrap();
assert!(has_prop);
let value = host_object_out
.get(scope, key.into())
.unwrap()
.uint32_value(scope)
.unwrap();
assert_eq!(value, expected);
}
}
#[test]
fn memory_pressure_notification() {
let _setup_guard = setup::parallel_test();