• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3const assert = require('assert');
4
5const { MessageChannel, MessagePort } = require('worker_threads');
6
7{
8  const { port1, port2 } = new MessageChannel();
9  assert(port1 instanceof MessagePort);
10  assert(port2 instanceof MessagePort);
11
12  const input = { a: 1 };
13  port1.postMessage(input);
14  port2.on('message', common.mustCall((received) => {
15    assert.deepStrictEqual(received, input);
16    port2.close(common.mustCall());
17  }));
18}
19
20{
21  const { port1, port2 } = new MessageChannel();
22
23  port1.onmessage = common.mustCall((message) => {
24    assert.strictEqual(message.data, 4);
25    assert.strictEqual(message.target, port1);
26    port2.close(common.mustCall());
27  });
28
29  port1.postMessage(2);
30
31  port2.onmessage = common.mustCall((message) => {
32    port2.postMessage(message.data * 2);
33  });
34}
35
36{
37  const { port1, port2 } = new MessageChannel();
38
39  const input = { a: 1 };
40  port1.postMessage(input);
41  // Check that the message still gets delivered if `port2` has its
42  // `on('message')` handler attached at a later point in time.
43  setImmediate(() => {
44    port2.on('message', common.mustCall((received) => {
45      assert.deepStrictEqual(received, input);
46      port2.close(common.mustCall());
47    }));
48  });
49}
50
51{
52  const { port1, port2 } = new MessageChannel();
53
54  const input = { a: 1 };
55
56  const dummy = common.mustNotCall();
57  // Check that the message still gets delivered if `port2` has its
58  // `on('message')` handler attached at a later point in time, even if a
59  // listener was removed previously.
60  port2.addListener('message', dummy);
61  setImmediate(() => {
62    port2.removeListener('message', dummy);
63    port1.postMessage(input);
64    setImmediate(() => {
65      port2.on('message', common.mustCall((received) => {
66        assert.deepStrictEqual(received, input);
67        port2.close(common.mustCall());
68      }));
69    });
70  });
71}
72
73{
74  const { port1, port2 } = new MessageChannel();
75  port2.on('message', common.mustCall(6));
76  port1.postMessage(1, null);
77  port1.postMessage(2, undefined);
78  port1.postMessage(3, []);
79  port1.postMessage(4, {});
80  port1.postMessage(5, { transfer: undefined });
81  port1.postMessage(6, { transfer: [] });
82
83  const err = {
84    constructor: TypeError,
85    code: 'ERR_INVALID_ARG_TYPE',
86    message: 'Optional transferList argument must be an iterable'
87  };
88
89  assert.throws(() => port1.postMessage(5, 0), err);
90  assert.throws(() => port1.postMessage(5, false), err);
91  assert.throws(() => port1.postMessage(5, 'X'), err);
92  assert.throws(() => port1.postMessage(5, Symbol('X')), err);
93
94  const err2 = {
95    constructor: TypeError,
96    code: 'ERR_INVALID_ARG_TYPE',
97    message: 'Optional options.transfer argument must be an iterable'
98  };
99
100  assert.throws(() => port1.postMessage(5, { transfer: null }), err2);
101  assert.throws(() => port1.postMessage(5, { transfer: 0 }), err2);
102  assert.throws(() => port1.postMessage(5, { transfer: false }), err2);
103  assert.throws(() => port1.postMessage(5, { transfer: {} }), err2);
104  assert.throws(() => port1.postMessage(5, {
105    transfer: { [Symbol.iterator]() { return {}; } }
106  }), err2);
107  assert.throws(() => port1.postMessage(5, {
108    transfer: { [Symbol.iterator]() { return { next: 42 }; } }
109  }), err2);
110  assert.throws(() => port1.postMessage(5, {
111    transfer: { [Symbol.iterator]() { return { next: null }; } }
112  }), err2);
113  port1.close();
114}
115
116{
117  // Make sure these ArrayBuffers end up detached, i.e. are actually being
118  // transferred because the transfer list provides them.
119  const { port1, port2 } = new MessageChannel();
120  port2.on('message', common.mustCall((msg) => {
121    assert.strictEqual(msg.ab.byteLength, 10);
122  }, 4));
123
124  {
125    const ab = new ArrayBuffer(10);
126    port1.postMessage({ ab }, [ ab ]);
127    assert.strictEqual(ab.byteLength, 0);
128  }
129
130  {
131    const ab = new ArrayBuffer(10);
132    port1.postMessage({ ab }, { transfer: [ ab ] });
133    assert.strictEqual(ab.byteLength, 0);
134  }
135
136  {
137    const ab = new ArrayBuffer(10);
138    port1.postMessage({ ab }, (function*() { yield ab; })());
139    assert.strictEqual(ab.byteLength, 0);
140  }
141
142  {
143    const ab = new ArrayBuffer(10);
144    port1.postMessage({ ab }, {
145      transfer: (function*() { yield ab; })()
146    });
147    assert.strictEqual(ab.byteLength, 0);
148  }
149
150  port1.close();
151}
152
153{
154  assert.deepStrictEqual(
155    Object.getOwnPropertyNames(MessagePort.prototype).sort(),
156    [
157      'close', 'constructor', 'onmessage', 'postMessage', 'ref', 'start',
158      'unref'
159    ]);
160}
161