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:
parent
75a2646b89
commit
ec2c901895
3 changed files with 266 additions and 7 deletions
|
@ -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(
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue