Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

worker: support MessagePort to workers data #32278

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/api/worker_threads.md
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
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
@@ -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 });
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{
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);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

semicolon, excuse me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, thanks for the the new test and semicolon is not required (make lint-js passed on my machine)

{
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'
});
}