'use strict'; const common = require('../common'); const assert = require('assert'); const { BroadcastChannel, } = require('worker_threads'); { const c1 = new BroadcastChannel('eventType').unref(); const c2 = new BroadcastChannel('eventType'); c2.onmessage = common.mustCall((e) => { assert(e instanceof MessageEvent); assert.strictEqual(e.target, c2); assert.strictEqual(e.type, 'message'); assert.strictEqual(e.data, 'hello world'); c2.close(); }); c1.postMessage('hello world'); } { // Messages are delivered in port creation order. // TODO(@jasnell): The ordering here is different than // what the browsers would implement due to the different // dispatching algorithm under the covers. What's not // immediately clear is whether the ordering is spec // mandated. In this test, c1 should receive events // first, then c2, then c3. In the Node.js dispatching // algorithm this means the ordering is: // from c3 (c1 from c3) // done (c1 from c2) // from c1 (c2 from c1) // from c3 (c2 from c3) // from c1 (c3 from c1) // done (c3 from c2) // // Whereas in the browser-ordering (as illustrated in the // Web Platform Tests) it would be: // from c1 (c2 from c1) // from c1 (c3 from c1) // from c3 (c1 from c3) // from c3 (c2 from c3) // done (c1 from c2) // done (c3 from c2) const c1 = new BroadcastChannel('order'); const c2 = new BroadcastChannel('order'); const c3 = new BroadcastChannel('order'); const events = []; let doneCount = 0; const handler = common.mustCall((e) => { events.push(e); if (e.data === 'done') { doneCount++; if (doneCount === 2) { assert.strictEqual(events.length, 6); // TODO: Don't skip Windows once ordering is fixed per comment above. // Right now, the ordering for Windows is unreliable. if (!common.isWindows) { assert.strictEqual(events[0].data, 'from c3'); assert.strictEqual(events[1].data, 'done'); assert.strictEqual(events[2].data, 'from c1'); assert.strictEqual(events[3].data, 'from c3'); assert.strictEqual(events[4].data, 'from c1'); assert.strictEqual(events[5].data, 'done'); } c1.close(); c2.close(); c3.close(); } } }, 6); c1.onmessage = handler; c2.onmessage = handler; c3.onmessage = handler; c1.postMessage('from c1'); c3.postMessage('from c3'); c2.postMessage('done'); } { // Messages aren't delivered to a closed port const c1 = new BroadcastChannel('closed1').unref(); const c2 = new BroadcastChannel('closed1'); const c3 = new BroadcastChannel('closed1'); c2.onmessage = common.mustNotCall(); c2.close(); c3.onmessage = common.mustCall(() => c3.close()); c1.postMessage('test'); } { // Messages aren't delivered to a port closed after calling postMessage. const c1 = new BroadcastChannel('closed2').unref(); const c2 = new BroadcastChannel('closed2'); const c3 = new BroadcastChannel('closed2'); c2.onmessage = common.mustNotCall(); c3.onmessage = common.mustCall(() => c3.close()); c1.postMessage('test'); c2.close(); } { // Closing and creating channels during message delivery works correctly const c1 = new BroadcastChannel('create-in-onmessage').unref(); const c2 = new BroadcastChannel('create-in-onmessage'); c2.onmessage = common.mustCall((e) => { assert.strictEqual(e.data, 'first'); c2.close(); const c3 = new BroadcastChannel('create-in-onmessage'); c3.onmessage = common.mustCall((event) => { assert.strictEqual(event.data, 'done'); c3.close(); }); c1.postMessage('done'); }); c1.postMessage('first'); c2.postMessage('second'); } { // TODO: Fix failure on Windows CI. Skipping for now. if (!common.isWindows) { // Closing a channel in onmessage prevents already queued tasks // from firing onmessage events const c1 = new BroadcastChannel('close-in-onmessage2').unref(); const c2 = new BroadcastChannel('close-in-onmessage2'); const c3 = new BroadcastChannel('close-in-onmessage2'); const events = []; c1.onmessage = (e) => events.push('c1: ' + e.data); c2.onmessage = (e) => events.push('c2: ' + e.data); c3.onmessage = (e) => events.push('c3: ' + e.data); // c2 closes itself when it receives the first message c2.addEventListener('message', common.mustCall(() => c2.close())); c3.addEventListener('message', common.mustCall((e) => { if (e.data === 'done') { assert.deepStrictEqual(events, [ 'c2: first', 'c3: first', 'c3: done']); c3.close(); } }, 2)); c1.postMessage('first'); c1.postMessage('done'); } }