From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Kenton Varda Date: Wed, 4 Dec 2024 22:36:05 -0600 Subject: Add ValueSerializer::SetTreatProxiesAsHostObjects(). Previously, ValueSerializer would always refuse to serialize Proxy objects. This commit gives the embedder the option to handle them as host objects. Similar to the previous patch adding `SetTreatFunctionsAsHostObjects()`, this is intended for use in an RPC system, where an arbitrary object can be "serialized" by replacing it with a stub which, when invoked, performs an RPC back to the originating isolate in order to access the original object there. Signed-off-by: James M Snell diff --git a/include/v8-value-serializer.h b/include/v8-value-serializer.h index 141f138e08de849e3e02b3b2b346e643b9e40c70..bdcb2831c55e21c6d511f56dfc79a5076871f05a 100644 --- a/include/v8-value-serializer.h +++ b/include/v8-value-serializer.h @@ -204,6 +204,15 @@ class V8_EXPORT ValueSerializer { */ void SetTreatFunctionsAsHostObjects(bool mode); + /** + * Indicate whether to treat Proxies as host objects, + * i.e. pass them to Delegate::WriteHostObject. This should not be + * called when no Delegate was passed. + * + * The default is not to treat Proxies as host objects. + */ + void SetTreatProxiesAsHostObjects(bool mode); + /** * Write raw data in various common formats to the buffer. * Note that integer types are written in base-128 varint format, not with a diff --git a/src/api/api.cc b/src/api/api.cc index 178b429ad06ea349bb43dff578b27ae46ae14da7..8754d87f1db985d4021faf9ce275783ae1229dc8 100644 --- a/src/api/api.cc +++ b/src/api/api.cc @@ -3592,6 +3592,10 @@ void ValueSerializer::SetTreatFunctionsAsHostObjects(bool mode) { private_->serializer.SetTreatFunctionsAsHostObjects(mode); } +void ValueSerializer::SetTreatProxiesAsHostObjects(bool mode) { + private_->serializer.SetTreatProxiesAsHostObjects(mode); +} + Maybe ValueSerializer::WriteValue(Local context, Local value) { auto i_isolate = i::Isolate::Current(); diff --git a/src/objects/value-serializer.cc b/src/objects/value-serializer.cc index 8c0bf0824b200489919f46b18d240c8c5c15a8ec..13d1a1340de579b8242bc3193c8c9002ecfd0468 100644 --- a/src/objects/value-serializer.cc +++ b/src/objects/value-serializer.cc @@ -339,6 +339,10 @@ void ValueSerializer::SetTreatFunctionsAsHostObjects(bool mode) { treat_functions_as_host_objects_ = mode; } +void ValueSerializer::SetTreatProxiesAsHostObjects(bool mode) { + treat_proxies_as_host_objects_ = mode; +} + void ValueSerializer::WriteTag(SerializationTag tag) { uint8_t raw_tag = static_cast(tag); WriteRawBytes(&raw_tag, sizeof(raw_tag)); @@ -610,7 +614,12 @@ Maybe ValueSerializer::WriteJSReceiver( InstanceType instance_type = receiver->map()->instance_type(); if (IsCallable(*receiver)) { if (treat_functions_as_host_objects_) { - return WriteHostObject(Cast(receiver)); + return WriteHostObject(receiver); + } + return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); + } else if (instance_type == JS_PROXY_TYPE) { + if (treat_proxies_as_host_objects_) { + return WriteHostObject(receiver); } return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); } else if (IsSpecialReceiverInstanceType(instance_type) && @@ -1288,7 +1297,7 @@ Maybe ValueSerializer::WriteSharedObject( return ThrowIfOutOfMemory(); } -Maybe ValueSerializer::WriteHostObject(DirectHandle object) { +Maybe ValueSerializer::WriteHostObject(DirectHandle object) { WriteTag(SerializationTag::kHostObject); if (!delegate_) { isolate_->Throw(*isolate_->factory()->NewError( diff --git a/src/objects/value-serializer.h b/src/objects/value-serializer.h index ddc5f27a80f93bae209f3fe8731d4df4baa58ead..496aab365007a45806264c8d3b981bd7a494f903 100644 --- a/src/objects/value-serializer.h +++ b/src/objects/value-serializer.h @@ -111,6 +111,15 @@ class ValueSerializer { */ void SetTreatFunctionsAsHostObjects(bool mode); + /* + * Indicate whether to treat Proxies as host objects, + * i.e. pass them to Delegate::WriteHostObject. This should not be + * called when no Delegate was passed. + * + * The default is not to treat Proxies as host objects. + */ + void SetTreatProxiesAsHostObjects(bool mode); + private: // Managing allocations of the internal buffer. Maybe ExpandBuffer(size_t required_capacity); @@ -161,8 +170,7 @@ class ValueSerializer { #endif // V8_ENABLE_WEBASSEMBLY Maybe WriteSharedObject(DirectHandle object) V8_WARN_UNUSED_RESULT; - Maybe WriteHostObject(DirectHandle object) - V8_WARN_UNUSED_RESULT; + Maybe WriteHostObject(DirectHandle object) V8_WARN_UNUSED_RESULT; /* * Reads the specified keys from the object and writes key-value pairs to the @@ -195,6 +203,7 @@ class ValueSerializer { bool has_custom_host_objects_ = false; bool treat_array_buffer_views_as_host_objects_ = false; bool treat_functions_as_host_objects_ = false; + bool treat_proxies_as_host_objects_ = false; bool out_of_memory_ = false; Zone zone_; uint32_t version_;