Skip to content
File

Blob: patches/v8/0015-Add-ValueSerializer-SetTreatProxiesAsHostObjects.patch

5.3 KB
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Kenton Varda <kenton@cloudflare.com>
3Date: Wed, 4 Dec 2024 22:36:05 -0600
4Subject: Add ValueSerializer::SetTreatProxiesAsHostObjects().
5 
6Previously, ValueSerializer would always refuse to serialize Proxy objects. This commit gives the embedder the option to handle them as host objects.
7 
8Similar 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 
10Signed-off-by: James M Snell <jsnell@cloudflare.com>
11 
12diff --git a/include/v8-value-serializer.h b/include/v8-value-serializer.h
13index 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
32diff --git a/src/api/api.cc b/src/api/api.cc
33index 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();
47diff --git a/src/objects/value-serializer.cc b/src/objects/value-serializer.cc
48index 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(
85diff --git a/src/objects/value-serializer.h b/src/objects/value-serializer.h
86index 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_;