Skip to content

Commit

Permalink
worker: support MessagePort to workers data
Browse files Browse the repository at this point in the history
PR-URL: #32278
Fixes: #32250
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
juanarbol authored and addaleax committed Apr 2, 2020
1 parent 579e6b9 commit ff2f47d
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
3 changes: 3 additions & 0 deletions doc/api/worker_threads.md
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,9 @@ if (isMainThread) {
<!-- YAML
added: v10.5.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/32278
description: The `transferList` option was introduced.
- version: v13.12.0
pr-url: https://github.com/nodejs/node/pull/31664
description: The `filename` parameter can be a WHATWG `URL` object using
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ class Worker extends EventEmitter {
this[kParentSideStdio] = { stdin, stdout, stderr };

const { port1, port2 } = new MessageChannel();
const transferList = [port2];
// If transferList is provided.
if (options.transferList)
transferList.push(...options.transferList);

this[kPublicPort] = port1;
this[kPublicPort].on('message', (message) => this.emit('message', message));
setupPortReferencing(this[kPublicPort], this, 'message');
Expand All @@ -198,7 +203,7 @@ class Worker extends EventEmitter {
require('internal/process/policy').src :
null,
hasStdin: !!options.stdin
}, [port2]);
}, transferList);
// Actually start the new thread now that everything is in place.
this[kHandle].startThread();
}
Expand Down
60 changes: 60 additions & 0 deletions test/parallel/test-worker-workerdata-messageport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use strict';

require('../common');
const assert = require('assert');

const {
Worker, MessageChannel
} = require('worker_threads');

const channel = new MessageChannel();
const workerData = { mesage: channel.port1 };
const transferList = [channel.port1];
const meowScript = () => 'meow';

{
// Should receive the transferList param.
new Worker(`${meowScript}`, { eval: true, workerData, transferList });
}

{
// Should work with more than one MessagePort.
const channel1 = new MessageChannel();
const channel2 = new MessageChannel();
const workerData = { message: channel1.port1, message2: channel2.port1 };
const transferList = [channel1.port1, channel2.port1];
new Worker(`${meowScript}`, { eval: true, workerData, transferList });
}

{
const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]);
assert.deepStrictEqual(uint8Array.length, 4);
new Worker(`
const { parentPort, workerData } = require('worker_threads');
parentPort.postMessage(workerData);
`, {
eval: true,
workerData: uint8Array,
transferList: [uint8Array.buffer]
}).on(
'message',
(message) =>
assert.deepStrictEqual(message, Uint8Array.of(1, 2, 3, 4))
);
assert.deepStrictEqual(uint8Array.length, 0);
}

{
// Should throw on non valid transferList input.
const channel1 = new MessageChannel();
const channel2 = new MessageChannel();
const workerData = { message: channel1.port1, message2: channel2.port1 };
assert.throws(() => new Worker(`${meowScript}`, {
eval: true,
workerData,
transferList: []
}), {
code: 'ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST',
message: 'MessagePort was found in message but not listed in transferList'
});
}

0 comments on commit ff2f47d

Please sign in to comment.