0
0
mirror of https://github.com/nodejs/node.git synced 2024-12-01 16:10:02 +01:00
nodejs/test/parallel/test-worker-message-port.js
Anna Henningsen 72650bcf72 worker: make transfer list behave like web MessagePort
Allow generic iterables as transfer list arguments, as well
as an options object with a `transfer` option, for web compatibility.

PR-URL: https://github.com/nodejs/node/pull/29319
Refs: https://github.com/nodejs/node/pull/28033#discussion_r289964991
Reviewed-By: James M Snell <jasnell@gmail.com>
2019-09-06 06:12:47 +02:00

161 lines
4.4 KiB
JavaScript

'use strict';
const common = require('../common');
const assert = require('assert');
const { MessageChannel, MessagePort } = require('worker_threads');
{
const { port1, port2 } = new MessageChannel();
assert(port1 instanceof MessagePort);
assert(port2 instanceof MessagePort);
const input = { a: 1 };
port1.postMessage(input);
port2.on('message', common.mustCall((received) => {
assert.deepStrictEqual(received, input);
port2.close(common.mustCall());
}));
}
{
const { port1, port2 } = new MessageChannel();
port1.onmessage = common.mustCall((message) => {
assert.strictEqual(message.data, 4);
assert.strictEqual(message.target, port1);
port2.close(common.mustCall());
});
port1.postMessage(2);
port2.onmessage = common.mustCall((message) => {
port2.postMessage(message.data * 2);
});
}
{
const { port1, port2 } = new MessageChannel();
const input = { a: 1 };
port1.postMessage(input);
// Check that the message still gets delivered if `port2` has its
// `on('message')` handler attached at a later point in time.
setImmediate(() => {
port2.on('message', common.mustCall((received) => {
assert.deepStrictEqual(received, input);
port2.close(common.mustCall());
}));
});
}
{
const { port1, port2 } = new MessageChannel();
const input = { a: 1 };
const dummy = common.mustNotCall();
// Check that the message still gets delivered if `port2` has its
// `on('message')` handler attached at a later point in time, even if a
// listener was removed previously.
port2.addListener('message', dummy);
setImmediate(() => {
port2.removeListener('message', dummy);
port1.postMessage(input);
setImmediate(() => {
port2.on('message', common.mustCall((received) => {
assert.deepStrictEqual(received, input);
port2.close(common.mustCall());
}));
});
});
}
{
const { port1, port2 } = new MessageChannel();
port2.on('message', common.mustCall(6));
port1.postMessage(1, null);
port1.postMessage(2, undefined);
port1.postMessage(3, []);
port1.postMessage(4, {});
port1.postMessage(5, { transfer: undefined });
port1.postMessage(6, { transfer: [] });
const err = {
constructor: TypeError,
code: 'ERR_INVALID_ARG_TYPE',
message: 'Optional transferList argument must be an iterable'
};
assert.throws(() => port1.postMessage(5, 0), err);
assert.throws(() => port1.postMessage(5, false), err);
assert.throws(() => port1.postMessage(5, 'X'), err);
assert.throws(() => port1.postMessage(5, Symbol('X')), err);
const err2 = {
constructor: TypeError,
code: 'ERR_INVALID_ARG_TYPE',
message: 'Optional options.transfer argument must be an iterable'
};
assert.throws(() => port1.postMessage(5, { transfer: null }), err2);
assert.throws(() => port1.postMessage(5, { transfer: 0 }), err2);
assert.throws(() => port1.postMessage(5, { transfer: false }), err2);
assert.throws(() => port1.postMessage(5, { transfer: {} }), err2);
assert.throws(() => port1.postMessage(5, {
transfer: { [Symbol.iterator]() { return {}; } }
}), err2);
assert.throws(() => port1.postMessage(5, {
transfer: { [Symbol.iterator]() { return { next: 42 }; } }
}), err2);
assert.throws(() => port1.postMessage(5, {
transfer: { [Symbol.iterator]() { return { next: null }; } }
}), err2);
port1.close();
}
{
// Make sure these ArrayBuffers end up detached, i.e. are actually being
// transferred because the transfer list provides them.
const { port1, port2 } = new MessageChannel();
port2.on('message', common.mustCall((msg) => {
assert.strictEqual(msg.ab.byteLength, 10);
}, 4));
{
const ab = new ArrayBuffer(10);
port1.postMessage({ ab }, [ ab ]);
assert.strictEqual(ab.byteLength, 0);
}
{
const ab = new ArrayBuffer(10);
port1.postMessage({ ab }, { transfer: [ ab ] });
assert.strictEqual(ab.byteLength, 0);
}
{
const ab = new ArrayBuffer(10);
port1.postMessage({ ab }, (function*() { yield ab; })());
assert.strictEqual(ab.byteLength, 0);
}
{
const ab = new ArrayBuffer(10);
port1.postMessage({ ab }, {
transfer: (function*() { yield ab; })()
});
assert.strictEqual(ab.byteLength, 0);
}
port1.close();
}
{
assert.deepStrictEqual(
Object.getOwnPropertyNames(MessagePort.prototype).sort(),
[
'close', 'constructor', 'onmessage', 'postMessage', 'ref', 'start',
'unref'
]);
}