From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Kenton Varda Date: Sat, 2 Mar 2024 09:00:18 -0600 Subject: Add ValueSerializer::SetTreatFunctionsAsHostObjects(). Previously, ValueSerializer would always refuse to serialize functions. This commit gives the embedder the option to handle them as host objects. 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. Signed-off-by: James M Snell diff --git a/include/v8-value-serializer.h b/include/v8-value-serializer.h index 596be18adeb3a5a81794aaa44b1d347dec6c0c7d..141f138e08de849e3e02b3b2b346e643b9e40c70 100644 --- a/include/v8-value-serializer.h +++ b/include/v8-value-serializer.h @@ -195,6 +195,15 @@ class V8_EXPORT ValueSerializer { */ void SetTreatArrayBufferViewsAsHostObjects(bool mode); + /** + * Indicate whether to treat Functions 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 Functions as host objects. + */ + void SetTreatFunctionsAsHostObjects(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 2c226e1467d952fd80c5356f7993f8af00c5f35d..877765bf5f57a2953aa2d1e0869ae5db12e8b6b1 100644 --- a/src/api/api.cc +++ b/src/api/api.cc @@ -3588,6 +3588,10 @@ void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) { private_->serializer.SetTreatArrayBufferViewsAsHostObjects(mode); } +void ValueSerializer::SetTreatFunctionsAsHostObjects(bool mode) { + private_->serializer.SetTreatFunctionsAsHostObjects(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 fc4dc2477d48c97145237e922d3bcba16140c47d..97b7f51664dda24ffb0c94e4033b2eff2ba4daee 100644 --- a/src/objects/value-serializer.cc +++ b/src/objects/value-serializer.cc @@ -335,6 +335,10 @@ void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) { treat_array_buffer_views_as_host_objects_ = mode; } +void ValueSerializer::SetTreatFunctionsAsHostObjects(bool mode) { + treat_functions_as_host_objects_ = mode; +} + void ValueSerializer::WriteTag(SerializationTag tag) { uint8_t raw_tag = static_cast(tag); WriteRawBytes(&raw_tag, sizeof(raw_tag)); @@ -604,13 +608,17 @@ Maybe ValueSerializer::WriteJSReceiver( // Eliminate callable and exotic objects, which should not be serialized. InstanceType instance_type = receiver->map()->instance_type(); - if (IsCallable(*receiver) || - (IsSpecialReceiverInstanceType(instance_type) && + if (IsCallable(*receiver)) { + if (treat_functions_as_host_objects_) { + return WriteHostObject(Cast(receiver)); + } + return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); + } else if (IsSpecialReceiverInstanceType(instance_type) && instance_type != JS_SPECIAL_API_OBJECT_TYPE #if V8_ENABLE_WEBASSEMBLY && instance_type != WASM_STRUCT_TYPE && instance_type != WASM_ARRAY_TYPE #endif - )) { + ) { return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); } diff --git a/src/objects/value-serializer.h b/src/objects/value-serializer.h index 06475f7b9c2a797066f5cfd32b232e5aa55f1f75..ddc5f27a80f93bae209f3fe8731d4df4baa58ead 100644 --- a/src/objects/value-serializer.h +++ b/src/objects/value-serializer.h @@ -102,6 +102,15 @@ class ValueSerializer { */ void SetTreatArrayBufferViewsAsHostObjects(bool mode); + /* + * Indicate whether to treat Functions 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 Functions as host objects. + */ + void SetTreatFunctionsAsHostObjects(bool mode); + private: // Managing allocations of the internal buffer. Maybe ExpandBuffer(size_t required_capacity); @@ -185,6 +194,7 @@ class ValueSerializer { size_t buffer_capacity_ = 0; bool has_custom_host_objects_ = false; bool treat_array_buffer_views_as_host_objects_ = false; + bool treat_functions_as_host_objects_ = false; bool out_of_memory_ = false; Zone zone_; uint32_t version_;