1'use strict'; 2 3const common = require('../common'); 4const assert = require('assert'); 5const { 6 BroadcastChannel, 7} = require('worker_threads'); 8 9{ 10 const c1 = new BroadcastChannel('eventType').unref(); 11 const c2 = new BroadcastChannel('eventType'); 12 13 c2.onmessage = common.mustCall((e) => { 14 assert(e instanceof MessageEvent); 15 assert.strictEqual(e.target, c2); 16 assert.strictEqual(e.type, 'message'); 17 assert.strictEqual(e.data, 'hello world'); 18 c2.close(); 19 }); 20 c1.postMessage('hello world'); 21} 22 23{ 24 // Messages are delivered in port creation order. 25 // TODO(@jasnell): The ordering here is different than 26 // what the browsers would implement due to the different 27 // dispatching algorithm under the covers. What's not 28 // immediately clear is whether the ordering is spec 29 // mandated. In this test, c1 should receive events 30 // first, then c2, then c3. In the Node.js dispatching 31 // algorithm this means the ordering is: 32 // from c3 (c1 from c3) 33 // done (c1 from c2) 34 // from c1 (c2 from c1) 35 // from c3 (c2 from c3) 36 // from c1 (c3 from c1) 37 // done (c3 from c2) 38 // 39 // Whereas in the browser-ordering (as illustrated in the 40 // Web Platform Tests) it would be: 41 // from c1 (c2 from c1) 42 // from c1 (c3 from c1) 43 // from c3 (c1 from c3) 44 // from c3 (c2 from c3) 45 // done (c1 from c2) 46 // done (c3 from c2) 47 const c1 = new BroadcastChannel('order'); 48 const c2 = new BroadcastChannel('order'); 49 const c3 = new BroadcastChannel('order'); 50 51 const events = []; 52 let doneCount = 0; 53 const handler = common.mustCall((e) => { 54 events.push(e); 55 if (e.data === 'done') { 56 doneCount++; 57 if (doneCount === 2) { 58 assert.strictEqual(events.length, 6); 59 // TODO: Don't skip Windows once ordering is fixed per comment above. 60 // Right now, the ordering for Windows is unreliable. 61 if (!common.isWindows) { 62 assert.strictEqual(events[0].data, 'from c3'); 63 assert.strictEqual(events[1].data, 'done'); 64 assert.strictEqual(events[2].data, 'from c1'); 65 assert.strictEqual(events[3].data, 'from c3'); 66 assert.strictEqual(events[4].data, 'from c1'); 67 assert.strictEqual(events[5].data, 'done'); 68 } 69 c1.close(); 70 c2.close(); 71 c3.close(); 72 } 73 } 74 }, 6); 75 c1.onmessage = handler; 76 c2.onmessage = handler; 77 c3.onmessage = handler; 78 79 c1.postMessage('from c1'); 80 c3.postMessage('from c3'); 81 c2.postMessage('done'); 82} 83 84{ 85 // Messages aren't delivered to a closed port 86 const c1 = new BroadcastChannel('closed1').unref(); 87 const c2 = new BroadcastChannel('closed1'); 88 const c3 = new BroadcastChannel('closed1'); 89 90 c2.onmessage = common.mustNotCall(); 91 c2.close(); 92 c3.onmessage = common.mustCall(() => c3.close()); 93 c1.postMessage('test'); 94} 95 96{ 97 // Messages aren't delivered to a port closed after calling postMessage. 98 const c1 = new BroadcastChannel('closed2').unref(); 99 const c2 = new BroadcastChannel('closed2'); 100 const c3 = new BroadcastChannel('closed2'); 101 102 c2.onmessage = common.mustNotCall(); 103 c3.onmessage = common.mustCall(() => c3.close()); 104 c1.postMessage('test'); 105 c2.close(); 106} 107 108{ 109 // Closing and creating channels during message delivery works correctly 110 const c1 = new BroadcastChannel('create-in-onmessage').unref(); 111 const c2 = new BroadcastChannel('create-in-onmessage'); 112 113 c2.onmessage = common.mustCall((e) => { 114 assert.strictEqual(e.data, 'first'); 115 c2.close(); 116 const c3 = new BroadcastChannel('create-in-onmessage'); 117 c3.onmessage = common.mustCall((event) => { 118 assert.strictEqual(event.data, 'done'); 119 c3.close(); 120 }); 121 c1.postMessage('done'); 122 }); 123 c1.postMessage('first'); 124 c2.postMessage('second'); 125} 126 127{ 128 // TODO: Fix failure on Windows CI. Skipping for now. 129 if (!common.isWindows) { 130 // Closing a channel in onmessage prevents already queued tasks 131 // from firing onmessage events 132 const c1 = new BroadcastChannel('close-in-onmessage2').unref(); 133 const c2 = new BroadcastChannel('close-in-onmessage2'); 134 const c3 = new BroadcastChannel('close-in-onmessage2'); 135 const events = []; 136 c1.onmessage = (e) => events.push('c1: ' + e.data); 137 c2.onmessage = (e) => events.push('c2: ' + e.data); 138 c3.onmessage = (e) => events.push('c3: ' + e.data); 139 140 // c2 closes itself when it receives the first message 141 c2.addEventListener('message', common.mustCall(() => c2.close())); 142 143 c3.addEventListener('message', common.mustCall((e) => { 144 if (e.data === 'done') { 145 assert.deepStrictEqual(events, [ 146 'c2: first', 147 'c3: first', 148 'c3: done']); 149 c3.close(); 150 } 151 }, 2)); 152 c1.postMessage('first'); 153 c1.postMessage('done'); 154 } 155} 156