11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst assert = require('assert');
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciconst { MessageChannel, MessagePort } = require('worker_threads');
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci{
81cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
91cb0ef41Sopenharmony_ci  assert(port1 instanceof MessagePort);
101cb0ef41Sopenharmony_ci  assert(port2 instanceof MessagePort);
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci  const input = { a: 1 };
131cb0ef41Sopenharmony_ci  port1.postMessage(input);
141cb0ef41Sopenharmony_ci  port2.on('message', common.mustCall((received) => {
151cb0ef41Sopenharmony_ci    assert.deepStrictEqual(received, input);
161cb0ef41Sopenharmony_ci    port2.close(common.mustCall());
171cb0ef41Sopenharmony_ci  }));
181cb0ef41Sopenharmony_ci}
191cb0ef41Sopenharmony_ci{
201cb0ef41Sopenharmony_ci  // Test emitting non-message events on a port
211cb0ef41Sopenharmony_ci  const { port2 } = new MessageChannel();
221cb0ef41Sopenharmony_ci  port2.addEventListener('foo', common.mustCall((received) => {
231cb0ef41Sopenharmony_ci    assert.strictEqual(received.type, 'foo');
241cb0ef41Sopenharmony_ci    assert.strictEqual(received.detail, 'bar');
251cb0ef41Sopenharmony_ci  }));
261cb0ef41Sopenharmony_ci  port2.on('foo', common.mustCall((received) => {
271cb0ef41Sopenharmony_ci    assert.strictEqual(received, 'bar');
281cb0ef41Sopenharmony_ci  }));
291cb0ef41Sopenharmony_ci  port2.emit('foo', 'bar');
301cb0ef41Sopenharmony_ci}
311cb0ef41Sopenharmony_ci{
321cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall((message) => {
351cb0ef41Sopenharmony_ci    assert.strictEqual(message.data, 4);
361cb0ef41Sopenharmony_ci    assert.strictEqual(message.target, port1);
371cb0ef41Sopenharmony_ci    assert.deepStrictEqual(message.ports, []);
381cb0ef41Sopenharmony_ci    port2.close(common.mustCall());
391cb0ef41Sopenharmony_ci  });
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  port1.postMessage(2);
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci  port2.onmessage = common.mustCall((message) => {
441cb0ef41Sopenharmony_ci    port2.postMessage(message.data * 2);
451cb0ef41Sopenharmony_ci  });
461cb0ef41Sopenharmony_ci}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci{
491cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  const input = { a: 1 };
521cb0ef41Sopenharmony_ci  port1.postMessage(input);
531cb0ef41Sopenharmony_ci  // Check that the message still gets delivered if `port2` has its
541cb0ef41Sopenharmony_ci  // `on('message')` handler attached at a later point in time.
551cb0ef41Sopenharmony_ci  setImmediate(() => {
561cb0ef41Sopenharmony_ci    port2.on('message', common.mustCall((received) => {
571cb0ef41Sopenharmony_ci      assert.deepStrictEqual(received, input);
581cb0ef41Sopenharmony_ci      port2.close(common.mustCall());
591cb0ef41Sopenharmony_ci    }));
601cb0ef41Sopenharmony_ci  });
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci{
641cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  const input = { a: 1 };
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  const dummy = common.mustNotCall();
691cb0ef41Sopenharmony_ci  // Check that the message still gets delivered if `port2` has its
701cb0ef41Sopenharmony_ci  // `on('message')` handler attached at a later point in time, even if a
711cb0ef41Sopenharmony_ci  // listener was removed previously.
721cb0ef41Sopenharmony_ci  port2.addListener('message', dummy);
731cb0ef41Sopenharmony_ci  setImmediate(() => {
741cb0ef41Sopenharmony_ci    port2.removeListener('message', dummy);
751cb0ef41Sopenharmony_ci    port1.postMessage(input);
761cb0ef41Sopenharmony_ci    setImmediate(() => {
771cb0ef41Sopenharmony_ci      port2.on('message', common.mustCall((received) => {
781cb0ef41Sopenharmony_ci        assert.deepStrictEqual(received, input);
791cb0ef41Sopenharmony_ci        port2.close(common.mustCall());
801cb0ef41Sopenharmony_ci      }));
811cb0ef41Sopenharmony_ci    });
821cb0ef41Sopenharmony_ci  });
831cb0ef41Sopenharmony_ci}
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci{
861cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
871cb0ef41Sopenharmony_ci  port2.on('message', common.mustCall(6));
881cb0ef41Sopenharmony_ci  port1.postMessage(1, null);
891cb0ef41Sopenharmony_ci  port1.postMessage(2, undefined);
901cb0ef41Sopenharmony_ci  port1.postMessage(3, []);
911cb0ef41Sopenharmony_ci  port1.postMessage(4, {});
921cb0ef41Sopenharmony_ci  port1.postMessage(5, { transfer: undefined });
931cb0ef41Sopenharmony_ci  port1.postMessage(6, { transfer: [] });
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  const err = {
961cb0ef41Sopenharmony_ci    constructor: TypeError,
971cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
981cb0ef41Sopenharmony_ci    message: 'Optional transferList argument must be an iterable'
991cb0ef41Sopenharmony_ci  };
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, 0), err);
1021cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, false), err);
1031cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, 'X'), err);
1041cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, Symbol('X')), err);
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  const err2 = {
1071cb0ef41Sopenharmony_ci    constructor: TypeError,
1081cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
1091cb0ef41Sopenharmony_ci    message: 'Optional options.transfer argument must be an iterable'
1101cb0ef41Sopenharmony_ci  };
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, { transfer: null }), err2);
1131cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, { transfer: 0 }), err2);
1141cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, { transfer: false }), err2);
1151cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, { transfer: {} }), err2);
1161cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, {
1171cb0ef41Sopenharmony_ci    transfer: { [Symbol.iterator]() { return {}; } }
1181cb0ef41Sopenharmony_ci  }), err2);
1191cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, {
1201cb0ef41Sopenharmony_ci    transfer: { [Symbol.iterator]() { return { next: 42 }; } }
1211cb0ef41Sopenharmony_ci  }), err2);
1221cb0ef41Sopenharmony_ci  assert.throws(() => port1.postMessage(5, {
1231cb0ef41Sopenharmony_ci    transfer: { [Symbol.iterator]() { return { next: null }; } }
1241cb0ef41Sopenharmony_ci  }), err2);
1251cb0ef41Sopenharmony_ci  port1.close();
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci{
1291cb0ef41Sopenharmony_ci  // Make sure these ArrayBuffers end up detached, i.e. are actually being
1301cb0ef41Sopenharmony_ci  // transferred because the transfer list provides them.
1311cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
1321cb0ef41Sopenharmony_ci  port2.on('message', common.mustCall((msg) => {
1331cb0ef41Sopenharmony_ci    assert.strictEqual(msg.ab.byteLength, 10);
1341cb0ef41Sopenharmony_ci  }, 4));
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  {
1371cb0ef41Sopenharmony_ci    const ab = new ArrayBuffer(10);
1381cb0ef41Sopenharmony_ci    port1.postMessage({ ab }, [ ab ]);
1391cb0ef41Sopenharmony_ci    assert.strictEqual(ab.byteLength, 0);
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  {
1431cb0ef41Sopenharmony_ci    const ab = new ArrayBuffer(10);
1441cb0ef41Sopenharmony_ci    port1.postMessage({ ab }, { transfer: [ ab ] });
1451cb0ef41Sopenharmony_ci    assert.strictEqual(ab.byteLength, 0);
1461cb0ef41Sopenharmony_ci  }
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  {
1491cb0ef41Sopenharmony_ci    const ab = new ArrayBuffer(10);
1501cb0ef41Sopenharmony_ci    port1.postMessage({ ab }, (function*() { yield ab; })());
1511cb0ef41Sopenharmony_ci    assert.strictEqual(ab.byteLength, 0);
1521cb0ef41Sopenharmony_ci  }
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  {
1551cb0ef41Sopenharmony_ci    const ab = new ArrayBuffer(10);
1561cb0ef41Sopenharmony_ci    port1.postMessage({ ab }, {
1571cb0ef41Sopenharmony_ci      transfer: (function*() { yield ab; })()
1581cb0ef41Sopenharmony_ci    });
1591cb0ef41Sopenharmony_ci    assert.strictEqual(ab.byteLength, 0);
1601cb0ef41Sopenharmony_ci  }
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  port1.close();
1631cb0ef41Sopenharmony_ci}
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci{
1661cb0ef41Sopenharmony_ci  // Test MessageEvent#ports
1671cb0ef41Sopenharmony_ci  const c1 = new MessageChannel();
1681cb0ef41Sopenharmony_ci  const c2 = new MessageChannel();
1691cb0ef41Sopenharmony_ci  c1.port1.postMessage({ port: c2.port2 }, [ c2.port2 ]);
1701cb0ef41Sopenharmony_ci  c1.port2.addEventListener('message', common.mustCall((ev) => {
1711cb0ef41Sopenharmony_ci    assert.strictEqual(ev.ports.length, 1);
1721cb0ef41Sopenharmony_ci    assert.strictEqual(ev.ports[0].constructor, MessagePort);
1731cb0ef41Sopenharmony_ci    c1.port1.close();
1741cb0ef41Sopenharmony_ci    c2.port1.close();
1751cb0ef41Sopenharmony_ci  }));
1761cb0ef41Sopenharmony_ci}
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci{
1791cb0ef41Sopenharmony_ci  assert.deepStrictEqual(
1801cb0ef41Sopenharmony_ci    Object.getOwnPropertyNames(MessagePort.prototype).sort(),
1811cb0ef41Sopenharmony_ci    [
1821cb0ef41Sopenharmony_ci      'close', 'constructor', 'hasRef', 'onmessage', 'onmessageerror',
1831cb0ef41Sopenharmony_ci      'postMessage', 'ref', 'start', 'unref',
1841cb0ef41Sopenharmony_ci    ]);
1851cb0ef41Sopenharmony_ci}
186