• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const common = require('../common');
4const {
5  BroadcastChannel,
6  Worker,
7  receiveMessageOnPort
8} = require('worker_threads');
9const assert = require('assert');
10
11assert.throws(() => new BroadcastChannel(Symbol('test')), {
12  message: /Cannot convert a Symbol value to a string/
13});
14
15assert.throws(() => new BroadcastChannel(), {
16  message: /The "name" argument must be specified/
17});
18
19// These should all just work
20[undefined, 1, null, 'test', 1n, false, Infinity].forEach((i) => {
21  const bc = new BroadcastChannel(i);
22  assert.strictEqual(bc.name, `${i}`);
23  bc.close();
24});
25
26{
27  // Empty postMessage throws
28  const bc = new BroadcastChannel('whatever');
29  assert.throws(() => bc.postMessage(), {
30    message: /The "message" argument must be specified/
31  });
32  bc.close();
33  // Calling close multiple times should not throw
34  bc.close();
35
36  // Calling postMessage after close should throw
37  assert.throws(() => bc.postMessage(null), {
38    message: /BroadcastChannel is closed/
39  });
40}
41
42{
43  const bc1 = new BroadcastChannel('channel1');
44  const bc2 = new BroadcastChannel('channel1');
45  const bc3 = new BroadcastChannel('channel1');
46  const bc4 = new BroadcastChannel('channel2');
47  assert.strictEqual(bc1.name, 'channel1');
48  assert.strictEqual(bc2.name, 'channel1');
49  assert.strictEqual(bc3.name, 'channel1');
50  assert.strictEqual(bc4.name, 'channel2');
51  bc1.addEventListener('message', common.mustCall((event) => {
52    assert.strictEqual(event.data, 'hello');
53    bc1.close();
54    bc2.close();
55    bc4.close();
56  }));
57  bc3.addEventListener('message', common.mustCall((event) => {
58    assert.strictEqual(event.data, 'hello');
59    bc3.close();
60  }));
61  bc2.addEventListener('message', common.mustNotCall());
62  bc4.addEventListener('message', common.mustNotCall());
63  bc2.postMessage('hello');
64}
65
66{
67  const bc1 = new BroadcastChannel('onmessage-channel1');
68  const bc2 = new BroadcastChannel('onmessage-channel1');
69  const bc3 = new BroadcastChannel('onmessage-channel1');
70  const bc4 = new BroadcastChannel('onmessage-channel2');
71  assert.strictEqual(bc1.name, 'onmessage-channel1');
72  assert.strictEqual(bc2.name, 'onmessage-channel1');
73  assert.strictEqual(bc3.name, 'onmessage-channel1');
74  assert.strictEqual(bc4.name, 'onmessage-channel2');
75  bc1.onmessage = common.mustCall((event) => {
76    assert.strictEqual(event.data, 'hello');
77    bc1.close();
78    bc2.close();
79    bc4.close();
80  });
81  bc3.onmessage = common.mustCall((event) => {
82    assert.strictEqual(event.data, 'hello');
83    bc3.close();
84  });
85  bc2.onmessage = common.mustNotCall();
86  bc4.onmessage = common.mustNotCall();
87  bc2.postMessage('hello');
88}
89
90{
91  const bc = new BroadcastChannel('worker1');
92  new Worker(`
93    const assert = require('assert');
94    const { BroadcastChannel } = require('worker_threads');
95    const bc = new BroadcastChannel('worker1');
96    bc.addEventListener('message', (event) => {
97      assert.strictEqual(event.data, 123);
98      // If this close() is not executed, the test should hang and timeout.
99      // If the test does hang and timeout in CI, then the first step should
100      // be to check that the two bc.close() calls are being made.
101      bc.close();
102    });
103    bc.postMessage(321);
104  `, { eval: true });
105  bc.addEventListener('message', common.mustCall(({ data }) => {
106    assert.strictEqual(data, 321);
107    bc.postMessage(123);
108    bc.close();
109  }));
110}
111
112{
113  const bc1 = new BroadcastChannel('channel3');
114  const bc2 = new BroadcastChannel('channel3');
115  const bc3 = new BroadcastChannel('channel3');
116  bc3.postMessage(new SharedArrayBuffer(10));
117  let received = 0;
118  for (const bc of [bc1, bc2]) {
119    bc.addEventListener('message', common.mustCall(({ data }) => {
120      assert(data instanceof SharedArrayBuffer);
121      if (++received === 2) {
122        bc1.close();
123        bc2.close();
124        bc3.close();
125      }
126    }));
127  }
128}
129
130{
131  const bc1 = new BroadcastChannel('channel3');
132  const mc = new MessageChannel();
133  assert.throws(() => bc1.postMessage(mc), {
134    message: /Object that needs transfer was found/
135  });
136  assert.throws(() => bc1.postMessage(Symbol()), {
137    message: /Symbol\(\) could not be cloned/
138  });
139  bc1.close();
140  assert.throws(() => bc1.postMessage(Symbol()), {
141    message: /BroadcastChannel is closed/
142  });
143}
144
145{
146  const bc1 = new BroadcastChannel('channel4');
147  const bc2 = new BroadcastChannel('channel4');
148  bc1.postMessage('some data');
149  assert.strictEqual(receiveMessageOnPort(bc2).message, 'some data');
150  assert.strictEqual(receiveMessageOnPort(bc2), undefined);
151  bc1.close();
152  bc2.close();
153}
154
155{
156  assert.throws(() => Reflect.get(BroadcastChannel.prototype, 'name', {}), {
157    code: 'ERR_INVALID_THIS',
158  });
159
160  [
161    'close',
162    'postMessage',
163    'ref',
164    'unref',
165  ].forEach((i) => {
166    assert.throws(() => Reflect.apply(BroadcastChannel.prototype[i], [], {}), {
167      code: 'ERR_INVALID_THIS',
168    });
169  });
170}
171