11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciconst assert = require('assert');
51cb0ef41Sopenharmony_ciconst { MessageChannel } = require('worker_threads');
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci// This tests various behaviors around transferring MessagePorts with closing
81cb0ef41Sopenharmony_ci// or closed handles.
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciconst { port1, port2 } = new MessageChannel();
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciconst arrayBuf = new ArrayBuffer(10);
131cb0ef41Sopenharmony_ciport1.onmessage = common.mustNotCall();
141cb0ef41Sopenharmony_ciport2.onmessage = common.mustNotCall();
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cifunction testSingle(closedPort, potentiallyOpenPort) {
171cb0ef41Sopenharmony_ci  assert.throws(common.mustCall(() => {
181cb0ef41Sopenharmony_ci    potentiallyOpenPort.postMessage(null, [arrayBuf, closedPort]);
191cb0ef41Sopenharmony_ci  }), common.mustCall((err) => {
201cb0ef41Sopenharmony_ci    assert.strictEqual(err.name, 'DataCloneError');
211cb0ef41Sopenharmony_ci    assert.strictEqual(err.message,
221cb0ef41Sopenharmony_ci                       'MessagePort in transfer list is already detached');
231cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 25);
241cb0ef41Sopenharmony_ci    assert.ok(err instanceof Error);
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci    const DOMException = err.constructor;
271cb0ef41Sopenharmony_ci    assert.ok(err instanceof DOMException);
281cb0ef41Sopenharmony_ci    assert.strictEqual(DOMException.name, 'DOMException');
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci    return true;
311cb0ef41Sopenharmony_ci  }));
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  // arrayBuf must not be transferred, even though it is present earlier in the
341cb0ef41Sopenharmony_ci  // transfer list than the closedPort.
351cb0ef41Sopenharmony_ci  assert.strictEqual(arrayBuf.byteLength, 10);
361cb0ef41Sopenharmony_ci}
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cifunction testBothClosed() {
391cb0ef41Sopenharmony_ci  testSingle(port1, port2);
401cb0ef41Sopenharmony_ci  testSingle(port2, port1);
411cb0ef41Sopenharmony_ci}
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci// Even though the port handles may not be completely closed in C++ land, the
441cb0ef41Sopenharmony_ci// observable behavior must be that the closing/detachment is synchronous and
451cb0ef41Sopenharmony_ci// instant.
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ciport1.close(common.mustCall(testBothClosed));
481cb0ef41Sopenharmony_citestSingle(port1, port2);
491cb0ef41Sopenharmony_ciport2.close(common.mustCall(testBothClosed));
501cb0ef41Sopenharmony_citestBothClosed();
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_cifunction tickUnref(n, fn) {
531cb0ef41Sopenharmony_ci  if (n === 0) return fn();
541cb0ef41Sopenharmony_ci  setImmediate(tickUnref, n - 1, fn).unref();
551cb0ef41Sopenharmony_ci}
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_citickUnref(10, common.mustNotCall('The communication channel is still open'));
58