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