Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 0d35eaa

Browse filesBrowse files
committed
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: #33772 Backport-PR-URL: #33965 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
1 parent 8e1698a commit 0d35eaa
Copy full SHA for 0d35eaa

File tree

Expand file treeCollapse file tree

10 files changed

+384
-33
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

10 files changed

+384
-33
lines changed
Open diff view settings
Collapse file

‎lib/internal/bootstrap/node.js‎

Copy file name to clipboardExpand all lines: lib/internal/bootstrap/node.js
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ process._exiting = false;
5959

6060
// process.config is serialized config.gypi
6161
process.config = JSONParse(internalBinding('native_module').config);
62+
require('internal/worker/js_transferable').setup();
6263

6364
// Bootstrappers for all threads, including worker threads and main thread
6465
const perThreadSetup = require('internal/process/per_thread');
Collapse file
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
const {
3+
messaging_deserialize_symbol,
4+
messaging_transfer_symbol,
5+
messaging_clone_symbol,
6+
messaging_transfer_list_symbol
7+
} = internalBinding('symbols');
8+
const {
9+
JSTransferable,
10+
setDeserializerCreateObjectFunction
11+
} = internalBinding('messaging');
12+
13+
function setup() {
14+
// Register the handler that will be used when deserializing JS-based objects
15+
// from .postMessage() calls. The format of `deserializeInfo` is generally
16+
// 'module:Constructor', e.g. 'internal/fs/promises:FileHandle'.
17+
setDeserializerCreateObjectFunction((deserializeInfo) => {
18+
const [ module, ctor ] = deserializeInfo.split(':');
19+
const Ctor = require(module)[ctor];
20+
return new Ctor();
21+
});
22+
}
23+
24+
module.exports = {
25+
setup,
26+
JSTransferable,
27+
kClone: messaging_clone_symbol,
28+
kDeserialize: messaging_deserialize_symbol,
29+
kTransfer: messaging_transfer_symbol,
30+
kTransferList: messaging_transfer_list_symbol
31+
};
Collapse file

‎node.gyp‎

Copy file name to clipboardExpand all lines: node.gyp
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@
216216
'lib/internal/vm/module.js',
217217
'lib/internal/worker.js',
218218
'lib/internal/worker/io.js',
219+
'lib/internal/worker/js_transferable.js',
219220
'lib/internal/watchdog.js',
220221
'lib/internal/streams/lazy_transform.js',
221222
'lib/internal/streams/async_iterator.js',
Collapse file

‎src/base_object.h‎

Copy file name to clipboardExpand all lines: src/base_object.h
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,17 @@ class BaseObject : public MemoryRetainer {
123123
// make sure that they are not accidentally destroyed on the sending side.
124124
// TransferForMessaging() will be called to get a representation of the
125125
// object that is used for subsequent deserialization.
126+
// The NestedTransferables() method can be used to transfer other objects
127+
// along with this one, if a situation requires it.
126128
// - kCloneable:
127129
// This object can be cloned without being modified.
128130
// CloneForMessaging() will be called to get a representation of the
129131
// object that is used for subsequent deserialization, unless the
130132
// object is listed in transferList, in which case TransferForMessaging()
131133
// is attempted first.
134+
// After a successful clone, FinalizeTransferRead() is called on the receiving
135+
// end, and can read deserialize JS data possibly serialized by a previous
136+
// FinalizeTransferWrite() call.
132137
enum class TransferMode {
133138
kUntransferable,
134139
kTransferable,
@@ -137,6 +142,10 @@ class BaseObject : public MemoryRetainer {
137142
virtual TransferMode GetTransferMode() const;
138143
virtual std::unique_ptr<worker::TransferData> TransferForMessaging();
139144
virtual std::unique_ptr<worker::TransferData> CloneForMessaging() const;
145+
virtual v8::Maybe<std::vector<BaseObjectPtrImpl<BaseObject, false>>>
146+
NestedTransferables() const;
147+
virtual v8::Maybe<bool> FinalizeTransferRead(
148+
v8::Local<v8::Context> context, v8::ValueDeserializer* deserializer);
140149

141150
virtual inline void OnGCCollect();
142151

Collapse file

‎src/env.h‎

Copy file name to clipboardExpand all lines: src/env.h
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ constexpr size_t kFsStatsBufferLength =
167167
#define PER_ISOLATE_SYMBOL_PROPERTIES(V) \
168168
V(handle_onclose_symbol, "handle_onclose") \
169169
V(no_message_symbol, "no_message_symbol") \
170+
V(messaging_deserialize_symbol, "messaging_deserialize_symbol") \
171+
V(messaging_transfer_symbol, "messaging_transfer_symbol") \
172+
V(messaging_clone_symbol, "messaging_clone_symbol") \
173+
V(messaging_transfer_list_symbol, "messaging_transfer_list_symbol") \
170174
V(oninit_symbol, "oninit") \
171175
V(owner_symbol, "owner_symbol") \
172176
V(onpskexchange_symbol, "onpskexchange") \
@@ -209,6 +213,7 @@ constexpr size_t kFsStatsBufferLength =
209213
V(crypto_rsa_pss_string, "rsa-pss") \
210214
V(cwd_string, "cwd") \
211215
V(data_string, "data") \
216+
V(deserialize_info_string, "deserializeInfo") \
212217
V(dest_string, "dest") \
213218
V(destroyed_string, "destroyed") \
214219
V(detached_string, "detached") \
@@ -465,6 +470,7 @@ constexpr size_t kFsStatsBufferLength =
465470
V(internal_binding_loader, v8::Function) \
466471
V(immediate_callback_function, v8::Function) \
467472
V(inspector_console_extension_installer, v8::Function) \
473+
V(messaging_deserialize_create_object, v8::Function) \
468474
V(message_port, v8::Object) \
469475
V(native_module_require, v8::Function) \
470476
V(performance_entry_callback, v8::Function) \
Collapse file

‎src/node_errors.h‎

Copy file name to clipboardExpand all lines: src/node_errors.h
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ void OnFatalError(const char* location, const char* message);
9797
V(ERR_MEMORY_ALLOCATION_FAILED, "Failed to allocate memory") \
9898
V(ERR_OSSL_EVP_INVALID_DIGEST, "Invalid digest used") \
9999
V(ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST, \
100-
"MessagePort was found in message but not listed in transferList") \
100+
"Object that needs transfer was found in message but not listed " \
101+
"in transferList") \
101102
V(ERR_MISSING_PLATFORM_FOR_WORKER, \
102103
"The V8 platform used by this instance of Node does not support " \
103104
"creating Workers") \

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.