11cb0ef41Sopenharmony_ci// Flags: --expose-internals --no-warnings
21cb0ef41Sopenharmony_ci'use strict';
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ciconst common = require('../common');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciconst {
71cb0ef41Sopenharmony_ci  ReadableStream,
81cb0ef41Sopenharmony_ci  WritableStream,
91cb0ef41Sopenharmony_ci  TransformStream,
101cb0ef41Sopenharmony_ci} = require('stream/web');
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciconst {
131cb0ef41Sopenharmony_ci  Worker
141cb0ef41Sopenharmony_ci} = require('worker_threads');
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciconst {
171cb0ef41Sopenharmony_ci  isReadableStream,
181cb0ef41Sopenharmony_ci  isReadableByteStreamController,
191cb0ef41Sopenharmony_ci} = require('internal/webstreams/readablestream');
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciconst {
221cb0ef41Sopenharmony_ci  isWritableStream,
231cb0ef41Sopenharmony_ci} = require('internal/webstreams/writablestream');
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ciconst {
261cb0ef41Sopenharmony_ci  isTransformStream,
271cb0ef41Sopenharmony_ci} = require('internal/webstreams/transformstream');
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ciconst {
301cb0ef41Sopenharmony_ci  kState,
311cb0ef41Sopenharmony_ci} = require('internal/webstreams/util');
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciconst {
341cb0ef41Sopenharmony_ci  makeTransferable,
351cb0ef41Sopenharmony_ci  kClone,
361cb0ef41Sopenharmony_ci  kTransfer,
371cb0ef41Sopenharmony_ci  kDeserialize,
381cb0ef41Sopenharmony_ci} = require('internal/worker/js_transferable');
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ciconst assert = require('assert');
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ciconst theData = 'hello';
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci{
451cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
461cb0ef41Sopenharmony_ci  port1.onmessageerror = common.mustNotCall();
471cb0ef41Sopenharmony_ci  port2.onmessageerror = common.mustNotCall();
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  // This test takes the ReadableStream and transfers it to the
501cb0ef41Sopenharmony_ci  // port1 first, then again to port2, which reads the data.
511cb0ef41Sopenharmony_ci  // Internally, this sets up a pipelined data flow that is
521cb0ef41Sopenharmony_ci  // important to understand in case this test fails..
531cb0ef41Sopenharmony_ci  //
541cb0ef41Sopenharmony_ci  // Specifically:
551cb0ef41Sopenharmony_ci  //
561cb0ef41Sopenharmony_ci  // 1. We start with ReadableStream R1,
571cb0ef41Sopenharmony_ci  // 2. Calling port2.postMessage causes a new internal WritableStream W1
581cb0ef41Sopenharmony_ci  //    and a new ReadableStream R2 to be created, both of which are coupled
591cb0ef41Sopenharmony_ci  //    to each other via a pair of MessagePorts P1 and P2.
601cb0ef41Sopenharmony_ci  // 3. ReadableStream R2 is passed to the port1.onmessage callback as the
611cb0ef41Sopenharmony_ci  //    data property of the MessageEvent, and R1 is configured to pipeTo W1.
621cb0ef41Sopenharmony_ci  // 4. Within port1.onmessage, we transfer ReadableStream R2 to port1, which
631cb0ef41Sopenharmony_ci  //    creates a new internal WritableStream W2 and a new ReadableStream R3,
641cb0ef41Sopenharmony_ci  //    both of which are coupled to each other via a pair of MessagePorts
651cb0ef41Sopenharmony_ci  //    P3 and P4.
661cb0ef41Sopenharmony_ci  // 5. ReadableStream R3 is passed to the port2.onmessage callback as the
671cb0ef41Sopenharmony_ci  //    data property of the MessageEvent, and R2 is configured to pipeTo W2.
681cb0ef41Sopenharmony_ci  // 6. Once the reader is attached to R3 in the port2.onmessage callback,
691cb0ef41Sopenharmony_ci  //    a message is sent along the path: R3 -> P4 -> P3 -> R2 -> P2 -> P1 -> R1
701cb0ef41Sopenharmony_ci  //    to begin pulling the data. The data is then pushed along the pipeline
711cb0ef41Sopenharmony_ci  //    R1 -> W1 -> P1 -> P2 -> R2 -> W2 -> P3 -> P4 -> R3
721cb0ef41Sopenharmony_ci  // 7. The MessagePorts P1, P2, P3, and P4 serve as a control channel for
731cb0ef41Sopenharmony_ci  //    passing data and control instructions, potentially across realms,
741cb0ef41Sopenharmony_ci  //    to the other ReadableStream and WritableStream instances.
751cb0ef41Sopenharmony_ci  //
761cb0ef41Sopenharmony_ci  // If this test experiences timeouts (hangs without finishing), it's most
771cb0ef41Sopenharmony_ci  // likely because the control instructions are somehow broken and the
781cb0ef41Sopenharmony_ci  // MessagePorts are not being closed properly or it could be caused by
791cb0ef41Sopenharmony_ci  // failing the close R1's controller which signals the end of the data
801cb0ef41Sopenharmony_ci  // flow.
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  const readable = new ReadableStream({
831cb0ef41Sopenharmony_ci    start: common.mustCall((controller) => {
841cb0ef41Sopenharmony_ci      controller.enqueue(theData);
851cb0ef41Sopenharmony_ci      controller.close();
861cb0ef41Sopenharmony_ci    }),
871cb0ef41Sopenharmony_ci  });
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  port2.onmessage = common.mustCall(({ data }) => {
901cb0ef41Sopenharmony_ci    assert(isReadableStream(data));
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci    const reader = data.getReader();
931cb0ef41Sopenharmony_ci    reader.read().then(common.mustCall((chunk) => {
941cb0ef41Sopenharmony_ci      assert.deepStrictEqual(chunk, { done: false, value: theData });
951cb0ef41Sopenharmony_ci    }));
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci    port2.close();
981cb0ef41Sopenharmony_ci  });
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall(({ data }) => {
1011cb0ef41Sopenharmony_ci    assert(isReadableStream(data));
1021cb0ef41Sopenharmony_ci    assert(!data.locked);
1031cb0ef41Sopenharmony_ci    port1.postMessage(data, [data]);
1041cb0ef41Sopenharmony_ci    assert(data.locked);
1051cb0ef41Sopenharmony_ci  });
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  assert.throws(() => port2.postMessage(readable), {
1081cb0ef41Sopenharmony_ci    code: 'ERR_MISSING_TRANSFERABLE_IN_TRANSFER_LIST',
1091cb0ef41Sopenharmony_ci  });
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  port2.postMessage(readable, [readable]);
1121cb0ef41Sopenharmony_ci  assert(readable.locked);
1131cb0ef41Sopenharmony_ci}
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci{
1161cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
1171cb0ef41Sopenharmony_ci  port1.onmessageerror = common.mustNotCall();
1181cb0ef41Sopenharmony_ci  port2.onmessageerror = common.mustNotCall();
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  // This test repeats the test above, but with a readable byte stream.
1211cb0ef41Sopenharmony_ci  // Note transferring a readable byte stream results in a regular
1221cb0ef41Sopenharmony_ci  // value-oriented stream on the other side:
1231cb0ef41Sopenharmony_ci  // https://streams.spec.whatwg.org/#abstract-opdef-setupcrossrealmtransformwritable
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  const theByteData = new Uint8Array([1, 2, 3]);
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  const readable = new ReadableStream({
1281cb0ef41Sopenharmony_ci    type: 'bytes',
1291cb0ef41Sopenharmony_ci    start: common.mustCall((controller) => {
1301cb0ef41Sopenharmony_ci      // `enqueue` will detach its argument's buffer, so clone first
1311cb0ef41Sopenharmony_ci      controller.enqueue(theByteData.slice());
1321cb0ef41Sopenharmony_ci      controller.close();
1331cb0ef41Sopenharmony_ci    }),
1341cb0ef41Sopenharmony_ci  });
1351cb0ef41Sopenharmony_ci  assert(isReadableByteStreamController(readable[kState].controller));
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  port2.onmessage = common.mustCall(({ data }) => {
1381cb0ef41Sopenharmony_ci    assert(isReadableStream(data));
1391cb0ef41Sopenharmony_ci    assert(!isReadableByteStreamController(data[kState].controller));
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci    const reader = data.getReader();
1421cb0ef41Sopenharmony_ci    reader.read().then(common.mustCall((chunk) => {
1431cb0ef41Sopenharmony_ci      assert.deepStrictEqual(chunk, { done: false, value: theByteData });
1441cb0ef41Sopenharmony_ci    }));
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci    port2.close();
1471cb0ef41Sopenharmony_ci  });
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall(({ data }) => {
1501cb0ef41Sopenharmony_ci    assert(isReadableStream(data));
1511cb0ef41Sopenharmony_ci    assert(!isReadableByteStreamController(data[kState].controller));
1521cb0ef41Sopenharmony_ci    assert(!data.locked);
1531cb0ef41Sopenharmony_ci    port1.postMessage(data, [data]);
1541cb0ef41Sopenharmony_ci    assert(data.locked);
1551cb0ef41Sopenharmony_ci  });
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  assert.throws(() => port2.postMessage(readable), {
1581cb0ef41Sopenharmony_ci    code: 'ERR_MISSING_TRANSFERABLE_IN_TRANSFER_LIST',
1591cb0ef41Sopenharmony_ci  });
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  port2.postMessage(readable, [readable]);
1621cb0ef41Sopenharmony_ci  assert(readable.locked);
1631cb0ef41Sopenharmony_ci}
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci{
1661cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
1671cb0ef41Sopenharmony_ci  port1.onmessageerror = common.mustNotCall();
1681cb0ef41Sopenharmony_ci  port2.onmessageerror = common.mustNotCall();
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  // Like the ReadableStream test above, this sets up a pipeline
1711cb0ef41Sopenharmony_ci  // through which the data flows...
1721cb0ef41Sopenharmony_ci  //
1731cb0ef41Sopenharmony_ci  // We start with WritableStream W1, which is transferred to port1.
1741cb0ef41Sopenharmony_ci  // Doing so creates an internal ReadableStream R1 and WritableStream W2,
1751cb0ef41Sopenharmony_ci  // which are coupled together with MessagePorts P1 and P2.
1761cb0ef41Sopenharmony_ci  // The port1.onmessage callback receives WritableStream W2 and
1771cb0ef41Sopenharmony_ci  // immediately transfers that to port2. Doing so creates an internal
1781cb0ef41Sopenharmony_ci  // ReadableStream R2 and WritableStream W3, which are coupled together
1791cb0ef41Sopenharmony_ci  // with MessagePorts P3 and P4. WritableStream W3 is handed off to
1801cb0ef41Sopenharmony_ci  // port2.onmessage.
1811cb0ef41Sopenharmony_ci  //
1821cb0ef41Sopenharmony_ci  // When the writer on port2.onmessage writes the chunk of data, it
1831cb0ef41Sopenharmony_ci  // gets passed along the pipeline:
1841cb0ef41Sopenharmony_ci  // W3 -> P4 -> P3 -> R2 -> W2 -> P2 -> P1 -> R1 -> W1
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci  const writable = new WritableStream({
1871cb0ef41Sopenharmony_ci    write: common.mustCall((chunk) => {
1881cb0ef41Sopenharmony_ci      assert.strictEqual(chunk, theData);
1891cb0ef41Sopenharmony_ci    }),
1901cb0ef41Sopenharmony_ci  });
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  port2.onmessage = common.mustCall(({ data }) => {
1931cb0ef41Sopenharmony_ci    assert(isWritableStream(data));
1941cb0ef41Sopenharmony_ci    assert(!data.locked);
1951cb0ef41Sopenharmony_ci    const writer = data.getWriter();
1961cb0ef41Sopenharmony_ci    writer.write(theData).then(common.mustCall());
1971cb0ef41Sopenharmony_ci    writer.close();
1981cb0ef41Sopenharmony_ci    port2.close();
1991cb0ef41Sopenharmony_ci  });
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall(({ data }) => {
2021cb0ef41Sopenharmony_ci    assert(isWritableStream(data));
2031cb0ef41Sopenharmony_ci    assert(!data.locked);
2041cb0ef41Sopenharmony_ci    port1.postMessage(data, [data]);
2051cb0ef41Sopenharmony_ci    assert(data.locked);
2061cb0ef41Sopenharmony_ci  });
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  assert.throws(() => port2.postMessage(writable), {
2091cb0ef41Sopenharmony_ci    code: 'ERR_MISSING_TRANSFERABLE_IN_TRANSFER_LIST',
2101cb0ef41Sopenharmony_ci  });
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci  port2.postMessage(writable, [writable]);
2131cb0ef41Sopenharmony_ci  assert(writable.locked);
2141cb0ef41Sopenharmony_ci}
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci{
2171cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
2181cb0ef41Sopenharmony_ci  port1.onmessageerror = common.mustNotCall();
2191cb0ef41Sopenharmony_ci  port2.onmessageerror = common.mustNotCall();
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci  // The data flow here is actually quite complicated, and is a combination
2221cb0ef41Sopenharmony_ci  // of the WritableStream and ReadableStream examples above.
2231cb0ef41Sopenharmony_ci  //
2241cb0ef41Sopenharmony_ci  // We start with TransformStream T1, which creates ReadableStream R1,
2251cb0ef41Sopenharmony_ci  // and WritableStream W1.
2261cb0ef41Sopenharmony_ci  //
2271cb0ef41Sopenharmony_ci  // When T1 is transferred to port1.onmessage, R1 and W1 are individually
2281cb0ef41Sopenharmony_ci  // transferred.
2291cb0ef41Sopenharmony_ci  //
2301cb0ef41Sopenharmony_ci  // When R1 is transferred, it creates internal WritableStream W2, and
2311cb0ef41Sopenharmony_ci  // new ReadableStream R2, coupled together via MessagePorts P1 and P2.
2321cb0ef41Sopenharmony_ci  //
2331cb0ef41Sopenharmony_ci  // When W1 is transferred, it creates internal ReadableStream R3 and
2341cb0ef41Sopenharmony_ci  // new WritableStream W3, coupled together via MessagePorts P3 and P4.
2351cb0ef41Sopenharmony_ci  //
2361cb0ef41Sopenharmony_ci  // A new TransformStream T2 is created that owns ReadableStream R2 and
2371cb0ef41Sopenharmony_ci  // WritableStream W3. The port1.onmessage callback immediately transfers
2381cb0ef41Sopenharmony_ci  // that to port2.onmessage.
2391cb0ef41Sopenharmony_ci  //
2401cb0ef41Sopenharmony_ci  // When T2 is transferred, R2 and W3 are individually transferred.
2411cb0ef41Sopenharmony_ci  //
2421cb0ef41Sopenharmony_ci  // When R2 is transferred, it creates internal WritableStream W4, and
2431cb0ef41Sopenharmony_ci  // ReadableStream R4, coupled together via MessagePorts P5 and P6.
2441cb0ef41Sopenharmony_ci  //
2451cb0ef41Sopenharmony_ci  // When W3 is transferred, it creates internal ReadableStream R5, and
2461cb0ef41Sopenharmony_ci  // WritableStream W5, coupled together via MessagePorts P7 and P8.
2471cb0ef41Sopenharmony_ci  //
2481cb0ef41Sopenharmony_ci  // A new TransformStream T3 is created that owns ReadableStream R4 and
2491cb0ef41Sopenharmony_ci  // WritableStream W5.
2501cb0ef41Sopenharmony_ci  //
2511cb0ef41Sopenharmony_ci  // port1.onmessage then writes a chunk of data. That chunk of data
2521cb0ef41Sopenharmony_ci  // flows through the pipeline to T1:
2531cb0ef41Sopenharmony_ci  //
2541cb0ef41Sopenharmony_ci  // W5 -> P8 -> P7 -> R5 -> W3 -> P4 -> P3 -> R3 -> W1 -> T1
2551cb0ef41Sopenharmony_ci  //
2561cb0ef41Sopenharmony_ci  // T1 performs the transformation, then pushes the chunk back out
2571cb0ef41Sopenharmony_ci  // along the pipeline:
2581cb0ef41Sopenharmony_ci  //
2591cb0ef41Sopenharmony_ci  // T1 -> R1 -> W2 -> P1 -> P2 -> R2 -> W4 -> P5 -> P6 -> R4
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci  const transform = new TransformStream({
2621cb0ef41Sopenharmony_ci    transform(chunk, controller) {
2631cb0ef41Sopenharmony_ci      controller.enqueue(chunk.toUpperCase());
2641cb0ef41Sopenharmony_ci    }
2651cb0ef41Sopenharmony_ci  });
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci  port2.onmessage = common.mustCall(({ data }) => {
2681cb0ef41Sopenharmony_ci    assert(isTransformStream(data));
2691cb0ef41Sopenharmony_ci    const writer = data.writable.getWriter();
2701cb0ef41Sopenharmony_ci    const reader = data.readable.getReader();
2711cb0ef41Sopenharmony_ci    Promise.all([
2721cb0ef41Sopenharmony_ci      writer.write(theData),
2731cb0ef41Sopenharmony_ci      writer.close(),
2741cb0ef41Sopenharmony_ci      reader.read().then(common.mustCall((result) => {
2751cb0ef41Sopenharmony_ci        assert(!result.done);
2761cb0ef41Sopenharmony_ci        assert.strictEqual(result.value, theData.toUpperCase());
2771cb0ef41Sopenharmony_ci      })),
2781cb0ef41Sopenharmony_ci      reader.read().then(common.mustCall((result) => {
2791cb0ef41Sopenharmony_ci        assert(result.done);
2801cb0ef41Sopenharmony_ci      })),
2811cb0ef41Sopenharmony_ci    ]).then(common.mustCall());
2821cb0ef41Sopenharmony_ci    port2.close();
2831cb0ef41Sopenharmony_ci  });
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall(({ data }) => {
2861cb0ef41Sopenharmony_ci    assert(isTransformStream(data));
2871cb0ef41Sopenharmony_ci    assert(!data.readable.locked);
2881cb0ef41Sopenharmony_ci    assert(!data.writable.locked);
2891cb0ef41Sopenharmony_ci    port1.postMessage(data, [data]);
2901cb0ef41Sopenharmony_ci    assert(data.readable.locked);
2911cb0ef41Sopenharmony_ci    assert(data.writable.locked);
2921cb0ef41Sopenharmony_ci  });
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_ci  assert.throws(() => port2.postMessage(transform), {
2951cb0ef41Sopenharmony_ci    code: 'ERR_MISSING_TRANSFERABLE_IN_TRANSFER_LIST',
2961cb0ef41Sopenharmony_ci  });
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci  port2.postMessage(transform, [transform]);
2991cb0ef41Sopenharmony_ci  assert(transform.readable.locked);
3001cb0ef41Sopenharmony_ci  assert(transform.writable.locked);
3011cb0ef41Sopenharmony_ci}
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci{
3041cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
3051cb0ef41Sopenharmony_ci  let controller;
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci  const readable = new ReadableStream({
3081cb0ef41Sopenharmony_ci    start(c) { controller = c; },
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci    cancel: common.mustCall((error) => {
3111cb0ef41Sopenharmony_ci      assert.strictEqual(error.code, 25);
3121cb0ef41Sopenharmony_ci      assert.strictEqual(error.name, 'DataCloneError');
3131cb0ef41Sopenharmony_ci    }),
3141cb0ef41Sopenharmony_ci  });
3151cb0ef41Sopenharmony_ci
3161cb0ef41Sopenharmony_ci  port1.onmessage = ({ data }) => {
3171cb0ef41Sopenharmony_ci    const reader = data.getReader();
3181cb0ef41Sopenharmony_ci    assert.rejects(reader.read(), {
3191cb0ef41Sopenharmony_ci      code: 25,
3201cb0ef41Sopenharmony_ci      name: 'DataCloneError',
3211cb0ef41Sopenharmony_ci    });
3221cb0ef41Sopenharmony_ci    port1.close();
3231cb0ef41Sopenharmony_ci  };
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci  port2.postMessage(readable, [readable]);
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci  const notActuallyTransferable = makeTransferable({
3281cb0ef41Sopenharmony_ci    [kClone]() {
3291cb0ef41Sopenharmony_ci      return {
3301cb0ef41Sopenharmony_ci        data: {},
3311cb0ef41Sopenharmony_ci        deserializeInfo: 'nothing that will work',
3321cb0ef41Sopenharmony_ci      };
3331cb0ef41Sopenharmony_ci    },
3341cb0ef41Sopenharmony_ci    [kDeserialize]: common.mustNotCall(),
3351cb0ef41Sopenharmony_ci  });
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci  controller.enqueue(notActuallyTransferable);
3381cb0ef41Sopenharmony_ci}
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci{
3411cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci  const source = {
3441cb0ef41Sopenharmony_ci    abort: common.mustCall((error) => {
3451cb0ef41Sopenharmony_ci      process.nextTick(() => {
3461cb0ef41Sopenharmony_ci        assert.strictEqual(error.code, 25);
3471cb0ef41Sopenharmony_ci        assert.strictEqual(error.name, 'DataCloneError');
3481cb0ef41Sopenharmony_ci      });
3491cb0ef41Sopenharmony_ci    })
3501cb0ef41Sopenharmony_ci  };
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci  const writable = new WritableStream(source);
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci  const notActuallyTransferable = makeTransferable({
3551cb0ef41Sopenharmony_ci    [kClone]() {
3561cb0ef41Sopenharmony_ci      return {
3571cb0ef41Sopenharmony_ci        data: {},
3581cb0ef41Sopenharmony_ci        deserializeInfo: 'nothing that will work',
3591cb0ef41Sopenharmony_ci      };
3601cb0ef41Sopenharmony_ci    },
3611cb0ef41Sopenharmony_ci    [kDeserialize]: common.mustNotCall(),
3621cb0ef41Sopenharmony_ci  });
3631cb0ef41Sopenharmony_ci
3641cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall(({ data }) => {
3651cb0ef41Sopenharmony_ci    const writer = data.getWriter();
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci    assert.rejects(writer.closed, {
3681cb0ef41Sopenharmony_ci      code: 25,
3691cb0ef41Sopenharmony_ci      name: 'DataCloneError',
3701cb0ef41Sopenharmony_ci    });
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_ci    writer.write(notActuallyTransferable).then(common.mustCall());
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ci    port1.close();
3751cb0ef41Sopenharmony_ci  });
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci  port2.postMessage(writable, [writable]);
3781cb0ef41Sopenharmony_ci}
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci{
3811cb0ef41Sopenharmony_ci  const error = new Error('boom');
3821cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci  const source = {
3851cb0ef41Sopenharmony_ci    abort: common.mustCall((reason) => {
3861cb0ef41Sopenharmony_ci      process.nextTick(() => {
3871cb0ef41Sopenharmony_ci        assert.deepStrictEqual(reason, error);
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci        // Reason is a clone of the original error.
3901cb0ef41Sopenharmony_ci        assert.notStrictEqual(reason, error);
3911cb0ef41Sopenharmony_ci      });
3921cb0ef41Sopenharmony_ci    }),
3931cb0ef41Sopenharmony_ci  };
3941cb0ef41Sopenharmony_ci
3951cb0ef41Sopenharmony_ci  const writable = new WritableStream(source);
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall(({ data }) => {
3981cb0ef41Sopenharmony_ci    const writer = data.getWriter();
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ci    assert.rejects(writer.closed, error);
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci    writer.abort(error).then(common.mustCall());
4031cb0ef41Sopenharmony_ci    port1.close();
4041cb0ef41Sopenharmony_ci  });
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  port2.postMessage(writable, [writable]);
4071cb0ef41Sopenharmony_ci}
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci{
4101cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci  const source = {
4131cb0ef41Sopenharmony_ci    abort: common.mustCall((error) => {
4141cb0ef41Sopenharmony_ci      process.nextTick(() => {
4151cb0ef41Sopenharmony_ci        assert.strictEqual(error.code, 25);
4161cb0ef41Sopenharmony_ci        assert.strictEqual(error.name, 'DataCloneError');
4171cb0ef41Sopenharmony_ci      });
4181cb0ef41Sopenharmony_ci    })
4191cb0ef41Sopenharmony_ci  };
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ci  const writable = new WritableStream(source);
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall(({ data }) => {
4241cb0ef41Sopenharmony_ci    const writer = data.getWriter();
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci    const m = new WebAssembly.Memory({ initial: 1 });
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci    assert.rejects(writer.abort(m), {
4291cb0ef41Sopenharmony_ci      code: 25,
4301cb0ef41Sopenharmony_ci      name: 'DataCloneError',
4311cb0ef41Sopenharmony_ci    });
4321cb0ef41Sopenharmony_ci    port1.close();
4331cb0ef41Sopenharmony_ci  });
4341cb0ef41Sopenharmony_ci
4351cb0ef41Sopenharmony_ci  port2.postMessage(writable, [writable]);
4361cb0ef41Sopenharmony_ci}
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ci{
4391cb0ef41Sopenharmony_ci  // Verify that the communication works across worker threads...
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci  const worker = new Worker(`
4421cb0ef41Sopenharmony_ci    const {
4431cb0ef41Sopenharmony_ci      isReadableStream,
4441cb0ef41Sopenharmony_ci    } = require('internal/webstreams/readablestream');
4451cb0ef41Sopenharmony_ci
4461cb0ef41Sopenharmony_ci    const {
4471cb0ef41Sopenharmony_ci      parentPort,
4481cb0ef41Sopenharmony_ci    } = require('worker_threads');
4491cb0ef41Sopenharmony_ci
4501cb0ef41Sopenharmony_ci    const assert = require('assert');
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_ci    const tracker = new assert.CallTracker();
4531cb0ef41Sopenharmony_ci    process.on('exit', () => {
4541cb0ef41Sopenharmony_ci      tracker.verify();
4551cb0ef41Sopenharmony_ci    });
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci    parentPort.onmessage = tracker.calls(({ data }) => {
4581cb0ef41Sopenharmony_ci      assert(isReadableStream(data));
4591cb0ef41Sopenharmony_ci      const reader = data.getReader();
4601cb0ef41Sopenharmony_ci      reader.read().then(tracker.calls((result) => {
4611cb0ef41Sopenharmony_ci        assert(!result.done);
4621cb0ef41Sopenharmony_ci        assert(result.value instanceof Uint8Array);
4631cb0ef41Sopenharmony_ci      }));
4641cb0ef41Sopenharmony_ci      parentPort.close();
4651cb0ef41Sopenharmony_ci    });
4661cb0ef41Sopenharmony_ci    parentPort.onmessageerror = () => assert.fail('should not be called');
4671cb0ef41Sopenharmony_ci  `, { eval: true });
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ci  worker.on('error', common.mustNotCall());
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ci  const readable = new ReadableStream({
4721cb0ef41Sopenharmony_ci    start(controller) {
4731cb0ef41Sopenharmony_ci      controller.enqueue(new Uint8Array(10));
4741cb0ef41Sopenharmony_ci      controller.close();
4751cb0ef41Sopenharmony_ci    }
4761cb0ef41Sopenharmony_ci  });
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci  worker.postMessage(readable, [readable]);
4791cb0ef41Sopenharmony_ci}
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci{
4821cb0ef41Sopenharmony_ci  const source = {
4831cb0ef41Sopenharmony_ci    cancel: common.mustCall(),
4841cb0ef41Sopenharmony_ci  };
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_ci  const readable = new ReadableStream(source);
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall(({ data }) => {
4911cb0ef41Sopenharmony_ci    data.cancel().then(common.mustCall());
4921cb0ef41Sopenharmony_ci    port1.close();
4931cb0ef41Sopenharmony_ci  });
4941cb0ef41Sopenharmony_ci
4951cb0ef41Sopenharmony_ci  port2.postMessage(readable, [readable]);
4961cb0ef41Sopenharmony_ci}
4971cb0ef41Sopenharmony_ci
4981cb0ef41Sopenharmony_ci{
4991cb0ef41Sopenharmony_ci  const source = {
5001cb0ef41Sopenharmony_ci    cancel: common.mustCall((error) => {
5011cb0ef41Sopenharmony_ci      process.nextTick(() => {
5021cb0ef41Sopenharmony_ci        assert.strictEqual(error.code, 25);
5031cb0ef41Sopenharmony_ci        assert.strictEqual(error.name, 'DataCloneError');
5041cb0ef41Sopenharmony_ci      });
5051cb0ef41Sopenharmony_ci    }),
5061cb0ef41Sopenharmony_ci  };
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_ci  const readable = new ReadableStream(source);
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall(({ data }) => {
5131cb0ef41Sopenharmony_ci    const m = new WebAssembly.Memory({ initial: 1 });
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ci    const reader = data.getReader();
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_ci    const cancel = reader.cancel(m);
5181cb0ef41Sopenharmony_ci
5191cb0ef41Sopenharmony_ci    reader.closed.then(common.mustCall());
5201cb0ef41Sopenharmony_ci
5211cb0ef41Sopenharmony_ci    assert.rejects(cancel, {
5221cb0ef41Sopenharmony_ci      code: 25,
5231cb0ef41Sopenharmony_ci      name: 'DataCloneError',
5241cb0ef41Sopenharmony_ci    });
5251cb0ef41Sopenharmony_ci
5261cb0ef41Sopenharmony_ci    port1.close();
5271cb0ef41Sopenharmony_ci  });
5281cb0ef41Sopenharmony_ci
5291cb0ef41Sopenharmony_ci  port2.postMessage(readable, [readable]);
5301cb0ef41Sopenharmony_ci}
5311cb0ef41Sopenharmony_ci
5321cb0ef41Sopenharmony_ci{
5331cb0ef41Sopenharmony_ci  const source = {
5341cb0ef41Sopenharmony_ci    abort: common.mustCall((error) => {
5351cb0ef41Sopenharmony_ci      process.nextTick(() => {
5361cb0ef41Sopenharmony_ci        assert.strictEqual(error.code, 25);
5371cb0ef41Sopenharmony_ci        assert.strictEqual(error.name, 'DataCloneError');
5381cb0ef41Sopenharmony_ci      });
5391cb0ef41Sopenharmony_ci    }),
5401cb0ef41Sopenharmony_ci  };
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci  const writable = new WritableStream(source);
5431cb0ef41Sopenharmony_ci
5441cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_ci  port1.onmessage = common.mustCall(({ data }) => {
5471cb0ef41Sopenharmony_ci    const m = new WebAssembly.Memory({ initial: 1 });
5481cb0ef41Sopenharmony_ci    const writer = data.getWriter();
5491cb0ef41Sopenharmony_ci    const write = writer.write(m);
5501cb0ef41Sopenharmony_ci    assert.rejects(write, { code: 25, name: 'DataCloneError' });
5511cb0ef41Sopenharmony_ci    port1.close();
5521cb0ef41Sopenharmony_ci  });
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  port2.postMessage(writable, [writable]);
5551cb0ef41Sopenharmony_ci}
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_ci{
5581cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
5591cb0ef41Sopenharmony_ci  readable.getReader();
5601cb0ef41Sopenharmony_ci  assert.throws(() => readable[kTransfer](), {
5611cb0ef41Sopenharmony_ci    code: 25,
5621cb0ef41Sopenharmony_ci    name: 'DataCloneError',
5631cb0ef41Sopenharmony_ci  });
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci  const writable = new WritableStream();
5661cb0ef41Sopenharmony_ci  writable.getWriter();
5671cb0ef41Sopenharmony_ci  assert.throws(() => writable[kTransfer](), {
5681cb0ef41Sopenharmony_ci    code: 25,
5691cb0ef41Sopenharmony_ci    name: 'DataCloneError',
5701cb0ef41Sopenharmony_ci  });
5711cb0ef41Sopenharmony_ci}
572