File
Blob: patches/v8/0009-Add-ValueSerializer-SetTreatFunctionsAsHostObjects.patch
| 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| 2 | From: Kenton Varda <kenton@cloudflare.com> |
| 3 | Date: Sat, 2 Mar 2024 09:00:18 -0600 |
| 4 | Subject: Add ValueSerializer::SetTreatFunctionsAsHostObjects(). |
| 5 | |
| 6 | Previously, ValueSerializer would always refuse to serialize functions. This commit gives the embedder the option to handle them as host objects. |
| 7 | |
| 8 | This is intended for use in an RPC system, where a function can be "serialized" by replacing it with a stub which, when invoked, performs an RPC back to the originating isolate in order to execute the original function 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 596be18adeb3a5a81794aaa44b1d347dec6c0c7d..141f138e08de849e3e02b3b2b346e643b9e40c70 100644 |
| 14 | --- a/include/v8-value-serializer.h |
| 15 | +++ b/include/v8-value-serializer.h |
| 16 | @@ -195,6 +195,15 @@ class V8_EXPORT ValueSerializer { |
| 17 | */ |
| 18 | void SetTreatArrayBufferViewsAsHostObjects(bool mode); |
| 19 | |
| 20 | + /** |
| 21 | + * Indicate whether to treat Functions 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 Functions as host objects. |
| 26 | + */ |
| 27 | + void SetTreatFunctionsAsHostObjects(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 2c226e1467d952fd80c5356f7993f8af00c5f35d..877765bf5f57a2953aa2d1e0869ae5db12e8b6b1 100644 |
| 34 | --- a/src/api/api.cc |
| 35 | +++ b/src/api/api.cc |
| 36 | @@ -3588,6 +3588,10 @@ void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) { |
| 37 | private_->serializer.SetTreatArrayBufferViewsAsHostObjects(mode); |
| 38 | } |
| 39 | |
| 40 | +void ValueSerializer::SetTreatFunctionsAsHostObjects(bool mode) { |
| 41 | + private_->serializer.SetTreatFunctionsAsHostObjects(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 fc4dc2477d48c97145237e922d3bcba16140c47d..97b7f51664dda24ffb0c94e4033b2eff2ba4daee 100644 |
| 49 | --- a/src/objects/value-serializer.cc |
| 50 | +++ b/src/objects/value-serializer.cc |
| 51 | @@ -335,6 +335,10 @@ void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) { |
| 52 | treat_array_buffer_views_as_host_objects_ = mode; |
| 53 | } |
| 54 | |
| 55 | +void ValueSerializer::SetTreatFunctionsAsHostObjects(bool mode) { |
| 56 | + treat_functions_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 | @@ -604,13 +608,17 @@ Maybe<bool> ValueSerializer::WriteJSReceiver( |
| 63 | |
| 64 | // Eliminate callable and exotic objects, which should not be serialized. |
| 65 | InstanceType instance_type = receiver->map()->instance_type(); |
| 66 | - if (IsCallable(*receiver) || |
| 67 | - (IsSpecialReceiverInstanceType(instance_type) && |
| 68 | + if (IsCallable(*receiver)) { |
| 69 | + if (treat_functions_as_host_objects_) { |
| 70 | + return WriteHostObject(Cast<JSObject>(receiver)); |
| 71 | + } |
| 72 | + return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); |
| 73 | + } else if (IsSpecialReceiverInstanceType(instance_type) && |
| 74 | instance_type != JS_SPECIAL_API_OBJECT_TYPE |
| 75 | #if V8_ENABLE_WEBASSEMBLY |
| 76 | && instance_type != WASM_STRUCT_TYPE && instance_type != WASM_ARRAY_TYPE |
| 77 | #endif |
| 78 | - )) { |
| 79 | + ) { |
| 80 | return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); |
| 81 | } |
| 82 | |
| 83 | diff --git a/src/objects/value-serializer.h b/src/objects/value-serializer.h |
| 84 | index 06475f7b9c2a797066f5cfd32b232e5aa55f1f75..ddc5f27a80f93bae209f3fe8731d4df4baa58ead 100644 |
| 85 | --- a/src/objects/value-serializer.h |
| 86 | +++ b/src/objects/value-serializer.h |
| 87 | @@ -102,6 +102,15 @@ class ValueSerializer { |
| 88 | */ |
| 89 | void SetTreatArrayBufferViewsAsHostObjects(bool mode); |
| 90 | |
| 91 | + /* |
| 92 | + * Indicate whether to treat Functions as host objects, |
| 93 | + * i.e. pass them to Delegate::WriteHostObject. This should not be |
| 94 | + * called when no Delegate was passed. |
| 95 | + * |
| 96 | + * The default is not to treat Functions as host objects. |
| 97 | + */ |
| 98 | + void SetTreatFunctionsAsHostObjects(bool mode); |
| 99 | + |
| 100 | private: |
| 101 | // Managing allocations of the internal buffer. |
| 102 | Maybe<bool> ExpandBuffer(size_t required_capacity); |
| 103 | @@ -185,6 +194,7 @@ class ValueSerializer { |
| 104 | size_t buffer_capacity_ = 0; |
| 105 | bool has_custom_host_objects_ = false; |
| 106 | bool treat_array_buffer_views_as_host_objects_ = false; |
| 107 | + bool treat_functions_as_host_objects_ = false; |
| 108 | bool out_of_memory_ = false; |
| 109 | Zone zone_; |
| 110 | uint32_t version_; |