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