diff --git a/src/node_messaging.cc b/src/node_messaging.cc index b40868a1ceeff4..44519b57fabf0a 100644 --- a/src/node_messaging.cc +++ b/src/node_messaging.cc @@ -31,6 +31,7 @@ using v8::MaybeLocal; using v8::Nothing; using v8::Object; using v8::SharedArrayBuffer; +using v8::SharedValueConveyor; using v8::String; using v8::Symbol; using v8::Value; @@ -92,10 +93,12 @@ class DeserializerDelegate : public ValueDeserializer::Delegate { Environment* env, const std::vector>& host_objects, const std::vector>& shared_array_buffers, - const std::vector& wasm_modules) + const std::vector& wasm_modules, + const std::optional& shared_value_conveyor) : host_objects_(host_objects), shared_array_buffers_(shared_array_buffers), - wasm_modules_(wasm_modules) {} + wasm_modules_(wasm_modules), + shared_value_conveyor_(shared_value_conveyor) {} MaybeLocal ReadHostObject(Isolate* isolate) override { // Identifying the index in the message's BaseObject array is sufficient. @@ -128,12 +131,18 @@ class DeserializerDelegate : public ValueDeserializer::Delegate { isolate, wasm_modules_[transfer_id]); } + const SharedValueConveyor* GetSharedValueConveyor(Isolate* isolate) override { + CHECK(shared_value_conveyor_.has_value()); + return &shared_value_conveyor_.value(); + } + ValueDeserializer* deserializer = nullptr; private: const std::vector>& host_objects_; const std::vector>& shared_array_buffers_; const std::vector& wasm_modules_; + const std::optional& shared_value_conveyor_; }; } // anonymous namespace @@ -198,8 +207,12 @@ MaybeLocal Message::Deserialize(Environment* env, shared_array_buffers.push_back(sab); } - DeserializerDelegate delegate( - this, env, host_objects, shared_array_buffers, wasm_modules_); + DeserializerDelegate delegate(this, + env, + host_objects, + shared_array_buffers, + wasm_modules_, + shared_value_conveyor_); ValueDeserializer deserializer( env->isolate(), reinterpret_cast(main_message_buf_.data), @@ -243,6 +256,10 @@ uint32_t Message::AddWASMModule(CompiledWasmModule&& mod) { return wasm_modules_.size() - 1; } +void Message::AdoptSharedValueConveyor(SharedValueConveyor&& conveyor) { + shared_value_conveyor_.emplace(std::move(conveyor)); +} + namespace { MaybeLocal GetEmitMessageFunction(Local context) { @@ -347,6 +364,12 @@ class SerializerDelegate : public ValueSerializer::Delegate { return Just(msg_->AddWASMModule(module->GetCompiledModule())); } + bool AdoptSharedValueConveyor(Isolate* isolate, + SharedValueConveyor&& conveyor) override { + msg_->AdoptSharedValueConveyor(std::move(conveyor)); + return true; + } + Maybe Finish(Local context) { for (uint32_t i = 0; i < host_objects_.size(); i++) { BaseObjectPtr host_object = std::move(host_objects_[i]); diff --git a/src/node_messaging.h b/src/node_messaging.h index 6b65d4523e6ac3..1c2a564d8d58e1 100644 --- a/src/node_messaging.h +++ b/src/node_messaging.h @@ -88,6 +88,9 @@ class Message : public MemoryRetainer { // Internal method of Message that is called when a new WebAssembly.Module // object is encountered in the incoming value's structure. uint32_t AddWASMModule(v8::CompiledWasmModule&& mod); + // Internal method of Message that is called when a shared value is + // encountered for the first time in the incoming value's structure. + void AdoptSharedValueConveyor(v8::SharedValueConveyor&& conveyor); // The host objects that will be transferred, as recorded by Serialize() // (e.g. MessagePorts). @@ -114,6 +117,7 @@ class Message : public MemoryRetainer { std::vector> shared_array_buffers_; std::vector> transferables_; std::vector wasm_modules_; + std::optional shared_value_conveyor_; friend class MessagePort; }; diff --git a/test/parallel/test-experimental-shared-value-conveyor.js b/test/parallel/test-experimental-shared-value-conveyor.js new file mode 100644 index 00000000000000..e61c5efebd0eeb --- /dev/null +++ b/test/parallel/test-experimental-shared-value-conveyor.js @@ -0,0 +1,25 @@ +'use strict'; + +// Flags: --harmony-struct + +const common = require('../common'); +const assert = require('assert'); +const { Worker, parentPort } = require('worker_threads'); + +// Do not use isMainThread so that this test itself can be run inside a Worker. +if (!process.env.HAS_STARTED_WORKER) { + process.env.HAS_STARTED_WORKER = 1; + const m = new globalThis.SharedArray(16); + + const worker = new Worker(__filename); + worker.once('message', common.mustCall((message) => { + assert.strictEqual(message, m); + })); + + worker.postMessage(m); +} else { + parentPort.once('message', common.mustCall((message) => { + // Simple echo. + parentPort.postMessage(message); + })); +}