1'use strict'; 2 3const common = require('../common'); 4const assert = require('assert'); 5const { MessageChannel } = require('worker_threads'); 6 7// This tests various behaviors around transferring MessagePorts with closing 8// or closed handles. 9 10const { port1, port2 } = new MessageChannel(); 11 12const arrayBuf = new ArrayBuffer(10); 13port1.onmessage = common.mustNotCall(); 14port2.onmessage = common.mustNotCall(); 15 16function testSingle(closedPort, potentiallyOpenPort) { 17 assert.throws(common.mustCall(() => { 18 potentiallyOpenPort.postMessage(null, [arrayBuf, closedPort]); 19 }), common.mustCall((err) => { 20 assert.strictEqual(err.name, 'DataCloneError'); 21 assert.strictEqual(err.message, 22 'MessagePort in transfer list is already detached'); 23 assert.strictEqual(err.code, 25); 24 assert.ok(err instanceof Error); 25 26 const DOMException = err.constructor; 27 assert.ok(err instanceof DOMException); 28 assert.strictEqual(DOMException.name, 'DOMException'); 29 30 return true; 31 })); 32 33 // arrayBuf must not be transferred, even though it is present earlier in the 34 // transfer list than the closedPort. 35 assert.strictEqual(arrayBuf.byteLength, 10); 36} 37 38function testBothClosed() { 39 testSingle(port1, port2); 40 testSingle(port2, port1); 41} 42 43// Even though the port handles may not be completely closed in C++ land, the 44// observable behavior must be that the closing/detachment is synchronous and 45// instant. 46 47port1.close(common.mustCall(testBothClosed)); 48testSingle(port1, port2); 49port2.close(common.mustCall(testBothClosed)); 50testBothClosed(); 51 52function tickUnref(n, fn) { 53 if (n === 0) return fn(); 54 setImmediate(tickUnref, n - 1, fn).unref(); 55} 56 57tickUnref(10, common.mustNotCall('The communication channel is still open')); 58