diff options
author | Anna Henningsen <anna@addaleax.net> | 2020-06-06 17:11:31 +0300 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2020-06-14 15:53:39 +0300 |
commit | 9129cf21ab51432675521ea158191ae3f866cafb (patch) | |
tree | a495ade59782e28a4ba94ddee085349e083cdd09 /src/node_messaging.h | |
parent | 8ead0211d7ee534015a10cc99c01a14cc38cbd3a (diff) |
worker: allow passing JS wrapper objects via postMessage
Enable JS wrapper objects to be used as transferable or cloneable
objects in `postMessage()` calls, by having them extend a C++-backed
class.
This requires a few internal changes:
- This commit adds the possibility for transferred objects to
read/write JS values at the end of the serialization/deserialization
phases.
- This commit adds the possibility for transferred objects to list
sub-transferables, e.g. typically the public JS wrapper class
would list its C++ handle in there.
- This commit adds usage of `BaseObject` in a few more places, because
now during deserialization weakly held objects can also be involved,
in addition to `MessagePort`s.
PR-URL: https://github.com/nodejs/node/pull/33772
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Diffstat (limited to 'src/node_messaging.h')
-rw-r--r-- | src/node_messaging.h | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/node_messaging.h b/src/node_messaging.h index 649ee201045..378468b6f44 100644 --- a/src/node_messaging.h +++ b/src/node_messaging.h @@ -30,6 +30,12 @@ class TransferData : public MemoryRetainer { Environment* env, v8::Local<v8::Context> context, std::unique_ptr<TransferData> self) = 0; + // FinalizeTransferWrite() is the counterpart to + // BaseObject::FinalizeTransferRead(). It is called right after the transfer + // data was created, and defaults to doing nothing. After this function, + // this object should not hold any more Isolate-specific data. + virtual v8::Maybe<bool> FinalizeTransferWrite( + v8::Local<v8::Context> context, v8::ValueSerializer* serializer); }; // Represents a single communication message. @@ -239,6 +245,52 @@ class MessagePort : public HandleWrap { friend class MessagePortData; }; +// Provide a base class from which JS classes that should be transferable or +// cloneable by postMesssage() can inherit. +// See e.g. FileHandle in internal/fs/promises.js for an example. +class JSTransferable : public BaseObject { + public: + JSTransferable(Environment* env, v8::Local<v8::Object> obj); + static void New(const v8::FunctionCallbackInfo<v8::Value>& args); + + TransferMode GetTransferMode() const override; + std::unique_ptr<TransferData> TransferForMessaging() override; + std::unique_ptr<TransferData> CloneForMessaging() const override; + v8::Maybe<std::vector<BaseObjectPtr<BaseObject>>> + NestedTransferables() const override; + v8::Maybe<bool> FinalizeTransferRead( + v8::Local<v8::Context> context, + v8::ValueDeserializer* deserializer) override; + + SET_NO_MEMORY_INFO() + SET_MEMORY_INFO_NAME(JSTransferable) + SET_SELF_SIZE(JSTransferable) + + private: + std::unique_ptr<TransferData> TransferOrClone(TransferMode mode) const; + + class Data : public TransferData { + public: + Data(std::string&& deserialize_info, v8::Global<v8::Value>&& data); + + BaseObjectPtr<BaseObject> Deserialize( + Environment* env, + v8::Local<v8::Context> context, + std::unique_ptr<TransferData> self) override; + v8::Maybe<bool> FinalizeTransferWrite( + v8::Local<v8::Context> context, + v8::ValueSerializer* serializer) override; + + SET_NO_MEMORY_INFO() + SET_MEMORY_INFO_NAME(JSTransferableTransferData) + SET_SELF_SIZE(Data) + + private: + std::string deserialize_info_; + v8::Global<v8::Value> data_; + }; +}; + v8::Local<v8::FunctionTemplate> GetMessagePortConstructorTemplate( Environment* env); |