File
Blob: patches/v8/0015-Add-ValueSerializer-SetTreatProxiesAsHostObjects.patch
| 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| 2 | From: Kenton Varda <kenton@cloudflare.com> |
| 3 | Date: Wed, 4 Dec 2024 22:36:05 -0600 |
| 4 | Subject: Add ValueSerializer::SetTreatProxiesAsHostObjects(). |
| 5 | |
| 6 | Previously, ValueSerializer would always refuse to serialize Proxy objects. This commit gives the embedder the option to handle them as host objects. |
| 7 | |
| 8 | 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. |
| 9 | |
| 10 | Signed-off-by: James M Snell <jsnell@cloudflare.com> |
| 11 | |
| 12 | diff --git a/include/v8-value-serializer.h b/include/v8-value-serializer.h |
| 13 | index 141f138e08de849e3e02b3b2b346e643b9e40c70..bdcb2831c55e21c6d511f56dfc79a5076871f05a 100644 |
| 14 | --- a/include/v8-value-serializer.h |
| 15 | +++ b/include/v8-value-serializer.h |
| 16 | @@ -204,6 +204,15 @@ class V8_EXPORT ValueSerializer { |
| 17 | */ |
| 18 | void SetTreatFunctionsAsHostObjects(bool mode); |
| 19 | |
| 20 | + /** |
| 21 | + * Indicate whether to treat Proxies as host objects, |
| 22 | + * i.e. pass them to Delegate::WriteHostObject. This should not be |
| 23 | + * called when no Delegate was passed. |
| 24 | + * |
| 25 | + * The default is not to treat Proxies as host objects. |
| 26 | + */ |
| 27 | + void SetTreatProxiesAsHostObjects(bool mode); |
| 28 | + |
| 29 | /** |
| 30 | * Write raw data in various common formats to the buffer. |
| 31 | * Note that integer types are written in base-128 varint format, not with a |
| 32 | diff --git a/src/api/api.cc b/src/api/api.cc |
| 33 | index 178b429ad06ea349bb43dff578b27ae46ae14da7..8754d87f1db985d4021faf9ce275783ae1229dc8 100644 |
| 34 | --- a/src/api/api.cc |
| 35 | +++ b/src/api/api.cc |
| 36 | @@ -3592,6 +3592,10 @@ void ValueSerializer::SetTreatFunctionsAsHostObjects(bool mode) { |
| 37 | private_->serializer.SetTreatFunctionsAsHostObjects(mode); |
| 38 | } |
| 39 | |
| 40 | +void ValueSerializer::SetTreatProxiesAsHostObjects(bool mode) { |
| 41 | + private_->serializer.SetTreatProxiesAsHostObjects(mode); |
| 42 | +} |
| 43 | + |
| 44 | Maybe<bool> ValueSerializer::WriteValue(Local<Context> context, |
| 45 | Local<Value> value) { |
| 46 | auto i_isolate = i::Isolate::Current(); |
| 47 | diff --git a/src/objects/value-serializer.cc b/src/objects/value-serializer.cc |
| 48 | index 8c0bf0824b200489919f46b18d240c8c5c15a8ec..13d1a1340de579b8242bc3193c8c9002ecfd0468 100644 |
| 49 | --- a/src/objects/value-serializer.cc |
| 50 | +++ b/src/objects/value-serializer.cc |
| 51 | @@ -339,6 +339,10 @@ void ValueSerializer::SetTreatFunctionsAsHostObjects(bool mode) { |
| 52 | treat_functions_as_host_objects_ = mode; |
| 53 | } |
| 54 | |
| 55 | +void ValueSerializer::SetTreatProxiesAsHostObjects(bool mode) { |
| 56 | + treat_proxies_as_host_objects_ = mode; |
| 57 | +} |
| 58 | + |
| 59 | void ValueSerializer::WriteTag(SerializationTag tag) { |
| 60 | uint8_t raw_tag = static_cast<uint8_t>(tag); |
| 61 | WriteRawBytes(&raw_tag, sizeof(raw_tag)); |
| 62 | @@ -610,7 +614,12 @@ Maybe<bool> ValueSerializer::WriteJSReceiver( |
| 63 | InstanceType instance_type = receiver->map()->instance_type(); |
| 64 | if (IsCallable(*receiver)) { |
| 65 | if (treat_functions_as_host_objects_) { |
| 66 | - return WriteHostObject(Cast<JSObject>(receiver)); |
| 67 | + return WriteHostObject(receiver); |
| 68 | + } |
| 69 | + return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); |
| 70 | + } else if (instance_type == JS_PROXY_TYPE) { |
| 71 | + if (treat_proxies_as_host_objects_) { |
| 72 | + return WriteHostObject(receiver); |
| 73 | } |
| 74 | return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); |
| 75 | } else if (IsSpecialReceiverInstanceType(instance_type) && |
| 76 | @@ -1288,7 +1297,7 @@ Maybe<bool> ValueSerializer::WriteSharedObject( |
| 77 | return ThrowIfOutOfMemory(); |
| 78 | } |
| 79 | |
| 80 | -Maybe<bool> ValueSerializer::WriteHostObject(DirectHandle<JSObject> object) { |
| 81 | +Maybe<bool> ValueSerializer::WriteHostObject(DirectHandle<JSReceiver> object) { |
| 82 | WriteTag(SerializationTag::kHostObject); |
| 83 | if (!delegate_) { |
| 84 | isolate_->Throw(*isolate_->factory()->NewError( |
| 85 | diff --git a/src/objects/value-serializer.h b/src/objects/value-serializer.h |
| 86 | index ddc5f27a80f93bae209f3fe8731d4df4baa58ead..496aab365007a45806264c8d3b981bd7a494f903 100644 |
| 87 | --- a/src/objects/value-serializer.h |
| 88 | +++ b/src/objects/value-serializer.h |
| 89 | @@ -111,6 +111,15 @@ class ValueSerializer { |
| 90 | */ |
| 91 | void SetTreatFunctionsAsHostObjects(bool mode); |
| 92 | |
| 93 | + /* |
| 94 | + * Indicate whether to treat Proxies as host objects, |
| 95 | + * i.e. pass them to Delegate::WriteHostObject. This should not be |
| 96 | + * called when no Delegate was passed. |
| 97 | + * |
| 98 | + * The default is not to treat Proxies as host objects. |
| 99 | + */ |
| 100 | + void SetTreatProxiesAsHostObjects(bool mode); |
| 101 | + |
| 102 | private: |
| 103 | // Managing allocations of the internal buffer. |
| 104 | Maybe<bool> ExpandBuffer(size_t required_capacity); |
| 105 | @@ -161,8 +170,7 @@ class ValueSerializer { |
| 106 | #endif // V8_ENABLE_WEBASSEMBLY |
| 107 | Maybe<bool> WriteSharedObject(DirectHandle<HeapObject> object) |
| 108 | V8_WARN_UNUSED_RESULT; |
| 109 | - Maybe<bool> WriteHostObject(DirectHandle<JSObject> object) |
| 110 | - V8_WARN_UNUSED_RESULT; |
| 111 | + Maybe<bool> WriteHostObject(DirectHandle<JSReceiver> object) V8_WARN_UNUSED_RESULT; |
| 112 | |
| 113 | /* |
| 114 | * Reads the specified keys from the object and writes key-value pairs to the |
| 115 | @@ -195,6 +203,7 @@ class ValueSerializer { |
| 116 | bool has_custom_host_objects_ = false; |
| 117 | bool treat_array_buffer_views_as_host_objects_ = false; |
| 118 | bool treat_functions_as_host_objects_ = false; |
| 119 | + bool treat_proxies_as_host_objects_ = false; |
| 120 | bool out_of_memory_ = false; |
| 121 | Zone zone_; |
| 122 | uint32_t version_; |