11cb0ef41Sopenharmony_ci// META: global=window,worker
21cb0ef41Sopenharmony_ci// META: script=../resources/rs-utils.js
31cb0ef41Sopenharmony_ci// META: script=../resources/test-utils.js
41cb0ef41Sopenharmony_ci// META: script=../resources/recording-streams.js
51cb0ef41Sopenharmony_ci'use strict';
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_cifunction duckTypedPassThroughTransform() {
81cb0ef41Sopenharmony_ci  let enqueueInReadable;
91cb0ef41Sopenharmony_ci  let closeReadable;
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci  return {
121cb0ef41Sopenharmony_ci    writable: new WritableStream({
131cb0ef41Sopenharmony_ci      write(chunk) {
141cb0ef41Sopenharmony_ci        enqueueInReadable(chunk);
151cb0ef41Sopenharmony_ci      },
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci      close() {
181cb0ef41Sopenharmony_ci        closeReadable();
191cb0ef41Sopenharmony_ci      }
201cb0ef41Sopenharmony_ci    }),
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci    readable: new ReadableStream({
231cb0ef41Sopenharmony_ci      start(c) {
241cb0ef41Sopenharmony_ci        enqueueInReadable = c.enqueue.bind(c);
251cb0ef41Sopenharmony_ci        closeReadable = c.close.bind(c);
261cb0ef41Sopenharmony_ci      }
271cb0ef41Sopenharmony_ci    })
281cb0ef41Sopenharmony_ci  };
291cb0ef41Sopenharmony_ci}
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cifunction uninterestingReadableWritablePair() {
321cb0ef41Sopenharmony_ci  return { writable: new WritableStream(), readable: new ReadableStream() };
331cb0ef41Sopenharmony_ci}
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_cipromise_test(() => {
361cb0ef41Sopenharmony_ci  const readableEnd = sequentialReadableStream(5).pipeThrough(duckTypedPassThroughTransform());
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  return readableStreamToArray(readableEnd).then(chunks =>
391cb0ef41Sopenharmony_ci    assert_array_equals(chunks, [1, 2, 3, 4, 5]), 'chunks should match');
401cb0ef41Sopenharmony_ci}, 'Piping through a duck-typed pass-through transform stream should work');
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cipromise_test(() => {
431cb0ef41Sopenharmony_ci  const transform = {
441cb0ef41Sopenharmony_ci    writable: new WritableStream({
451cb0ef41Sopenharmony_ci      start(c) {
461cb0ef41Sopenharmony_ci        c.error(new Error('this rejection should not be reported as unhandled'));
471cb0ef41Sopenharmony_ci      }
481cb0ef41Sopenharmony_ci    }),
491cb0ef41Sopenharmony_ci    readable: new ReadableStream()
501cb0ef41Sopenharmony_ci  };
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  sequentialReadableStream(5).pipeThrough(transform);
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  // The test harness should complain about unhandled rejections by then.
551cb0ef41Sopenharmony_ci  return flushAsyncEvents();
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci}, 'Piping through a transform errored on the writable end does not cause an unhandled promise rejection');
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_citest(() => {
601cb0ef41Sopenharmony_ci  let calledPipeTo = false;
611cb0ef41Sopenharmony_ci  class BadReadableStream extends ReadableStream {
621cb0ef41Sopenharmony_ci    pipeTo() {
631cb0ef41Sopenharmony_ci      calledPipeTo = true;
641cb0ef41Sopenharmony_ci    }
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  const brs = new BadReadableStream({
681cb0ef41Sopenharmony_ci    start(controller) {
691cb0ef41Sopenharmony_ci      controller.close();
701cb0ef41Sopenharmony_ci    }
711cb0ef41Sopenharmony_ci  });
721cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
731cb0ef41Sopenharmony_ci  const writable = new WritableStream();
741cb0ef41Sopenharmony_ci  const result = brs.pipeThrough({ readable, writable });
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  assert_false(calledPipeTo, 'the overridden pipeTo should not have been called');
771cb0ef41Sopenharmony_ci  assert_equals(result, readable, 'return value should be the passed readable property');
781cb0ef41Sopenharmony_ci}, 'pipeThrough should not call pipeTo on this');
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_citest(t => {
811cb0ef41Sopenharmony_ci  let calledFakePipeTo = false;
821cb0ef41Sopenharmony_ci  const realPipeTo = ReadableStream.prototype.pipeTo;
831cb0ef41Sopenharmony_ci  t.add_cleanup(() => {
841cb0ef41Sopenharmony_ci    ReadableStream.prototype.pipeTo = realPipeTo;
851cb0ef41Sopenharmony_ci  });
861cb0ef41Sopenharmony_ci  ReadableStream.prototype.pipeTo = () => {
871cb0ef41Sopenharmony_ci    calledFakePipeTo = true;
881cb0ef41Sopenharmony_ci  };
891cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
901cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
911cb0ef41Sopenharmony_ci  const writable = new WritableStream();
921cb0ef41Sopenharmony_ci  const result = rs.pipeThrough({ readable, writable });
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci  assert_false(calledFakePipeTo, 'the monkey-patched pipeTo should not have been called');
951cb0ef41Sopenharmony_ci  assert_equals(result, readable, 'return value should be the passed readable property');
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci}, 'pipeThrough should not call pipeTo on the ReadableStream prototype');
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ciconst badReadables = [null, undefined, 0, NaN, true, 'ReadableStream', Object.create(ReadableStream.prototype)];
1001cb0ef41Sopenharmony_cifor (const readable of badReadables) {
1011cb0ef41Sopenharmony_ci  test(() => {
1021cb0ef41Sopenharmony_ci    assert_throws_js(TypeError,
1031cb0ef41Sopenharmony_ci                     ReadableStream.prototype.pipeThrough.bind(readable, uninterestingReadableWritablePair()),
1041cb0ef41Sopenharmony_ci                     'pipeThrough should throw');
1051cb0ef41Sopenharmony_ci  }, `pipeThrough should brand-check this and not allow '${readable}'`);
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  test(() => {
1081cb0ef41Sopenharmony_ci    const rs = new ReadableStream();
1091cb0ef41Sopenharmony_ci    let writableGetterCalled = false;
1101cb0ef41Sopenharmony_ci    assert_throws_js(
1111cb0ef41Sopenharmony_ci      TypeError,
1121cb0ef41Sopenharmony_ci      () => rs.pipeThrough({
1131cb0ef41Sopenharmony_ci        get writable() {
1141cb0ef41Sopenharmony_ci          writableGetterCalled = true;
1151cb0ef41Sopenharmony_ci          return new WritableStream();
1161cb0ef41Sopenharmony_ci        },
1171cb0ef41Sopenharmony_ci        readable
1181cb0ef41Sopenharmony_ci      }),
1191cb0ef41Sopenharmony_ci      'pipeThrough should brand-check readable'
1201cb0ef41Sopenharmony_ci    );
1211cb0ef41Sopenharmony_ci    assert_false(writableGetterCalled, 'writable should not have been accessed');
1221cb0ef41Sopenharmony_ci  }, `pipeThrough should brand-check readable and not allow '${readable}'`);
1231cb0ef41Sopenharmony_ci}
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ciconst badWritables = [null, undefined, 0, NaN, true, 'WritableStream', Object.create(WritableStream.prototype)];
1261cb0ef41Sopenharmony_cifor (const writable of badWritables) {
1271cb0ef41Sopenharmony_ci  test(() => {
1281cb0ef41Sopenharmony_ci    const rs = new ReadableStream({
1291cb0ef41Sopenharmony_ci      start(c) {
1301cb0ef41Sopenharmony_ci        c.close();
1311cb0ef41Sopenharmony_ci      }
1321cb0ef41Sopenharmony_ci    });
1331cb0ef41Sopenharmony_ci    let readableGetterCalled = false;
1341cb0ef41Sopenharmony_ci    assert_throws_js(TypeError, () => rs.pipeThrough({
1351cb0ef41Sopenharmony_ci      get readable() {
1361cb0ef41Sopenharmony_ci        readableGetterCalled = true;
1371cb0ef41Sopenharmony_ci        return new ReadableStream();
1381cb0ef41Sopenharmony_ci      },
1391cb0ef41Sopenharmony_ci      writable
1401cb0ef41Sopenharmony_ci    }),
1411cb0ef41Sopenharmony_ci                  'pipeThrough should brand-check writable');
1421cb0ef41Sopenharmony_ci    assert_true(readableGetterCalled, 'readable should have been accessed');
1431cb0ef41Sopenharmony_ci  }, `pipeThrough should brand-check writable and not allow '${writable}'`);
1441cb0ef41Sopenharmony_ci}
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_citest(t => {
1471cb0ef41Sopenharmony_ci  const error = new Error();
1481cb0ef41Sopenharmony_ci  error.name = 'custom';
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
1511cb0ef41Sopenharmony_ci    pull: t.unreached_func('pull should not be called')
1521cb0ef41Sopenharmony_ci  }, { highWaterMark: 0 });
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  const throwingWritable = {
1551cb0ef41Sopenharmony_ci    readable: rs,
1561cb0ef41Sopenharmony_ci    get writable() {
1571cb0ef41Sopenharmony_ci      throw error;
1581cb0ef41Sopenharmony_ci    }
1591cb0ef41Sopenharmony_ci  };
1601cb0ef41Sopenharmony_ci  assert_throws_exactly(error,
1611cb0ef41Sopenharmony_ci                        () => ReadableStream.prototype.pipeThrough.call(rs, throwingWritable, {}),
1621cb0ef41Sopenharmony_ci                        'pipeThrough should rethrow the error thrown by the writable getter');
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  const throwingReadable = {
1651cb0ef41Sopenharmony_ci    get readable() {
1661cb0ef41Sopenharmony_ci      throw error;
1671cb0ef41Sopenharmony_ci    },
1681cb0ef41Sopenharmony_ci    writable: {}
1691cb0ef41Sopenharmony_ci  };
1701cb0ef41Sopenharmony_ci  assert_throws_exactly(error,
1711cb0ef41Sopenharmony_ci                        () => ReadableStream.prototype.pipeThrough.call(rs, throwingReadable, {}),
1721cb0ef41Sopenharmony_ci                        'pipeThrough should rethrow the error thrown by the readable getter');
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci}, 'pipeThrough should rethrow errors from accessing readable or writable');
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ciconst badSignals = [null, 0, NaN, true, 'AbortSignal', Object.create(AbortSignal.prototype)];
1771cb0ef41Sopenharmony_cifor (const signal of badSignals) {
1781cb0ef41Sopenharmony_ci  test(() => {
1791cb0ef41Sopenharmony_ci    const rs = new ReadableStream();
1801cb0ef41Sopenharmony_ci    assert_throws_js(TypeError, () => rs.pipeThrough(uninterestingReadableWritablePair(), { signal }),
1811cb0ef41Sopenharmony_ci                     'pipeThrough should throw');
1821cb0ef41Sopenharmony_ci  }, `invalid values of signal should throw; specifically '${signal}'`);
1831cb0ef41Sopenharmony_ci}
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_citest(() => {
1861cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
1871cb0ef41Sopenharmony_ci  const controller = new AbortController();
1881cb0ef41Sopenharmony_ci  const signal = controller.signal;
1891cb0ef41Sopenharmony_ci  rs.pipeThrough(uninterestingReadableWritablePair(), { signal });
1901cb0ef41Sopenharmony_ci}, 'pipeThrough should accept a real AbortSignal');
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_citest(() => {
1931cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
1941cb0ef41Sopenharmony_ci  rs.getReader();
1951cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => rs.pipeThrough(uninterestingReadableWritablePair()),
1961cb0ef41Sopenharmony_ci                   'pipeThrough should throw');
1971cb0ef41Sopenharmony_ci}, 'pipeThrough should throw if this is locked');
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_citest(() => {
2001cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
2011cb0ef41Sopenharmony_ci  const writable = new WritableStream();
2021cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
2031cb0ef41Sopenharmony_ci  writable.getWriter();
2041cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => rs.pipeThrough({writable, readable}),
2051cb0ef41Sopenharmony_ci                   'pipeThrough should throw');
2061cb0ef41Sopenharmony_ci}, 'pipeThrough should throw if writable is locked');
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_citest(() => {
2091cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
2101cb0ef41Sopenharmony_ci  const writable = new WritableStream();
2111cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
2121cb0ef41Sopenharmony_ci  readable.getReader();
2131cb0ef41Sopenharmony_ci  assert_equals(rs.pipeThrough({ writable, readable }), readable,
2141cb0ef41Sopenharmony_ci                'pipeThrough should not throw');
2151cb0ef41Sopenharmony_ci}, 'pipeThrough should not care if readable is locked');
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_cipromise_test(() => {
2181cb0ef41Sopenharmony_ci  const rs = recordingReadableStream();
2191cb0ef41Sopenharmony_ci  const writable = new WritableStream({
2201cb0ef41Sopenharmony_ci    start(controller) {
2211cb0ef41Sopenharmony_ci      controller.error();
2221cb0ef41Sopenharmony_ci    }
2231cb0ef41Sopenharmony_ci  });
2241cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
2251cb0ef41Sopenharmony_ci  rs.pipeThrough({ writable, readable }, { preventCancel: true });
2261cb0ef41Sopenharmony_ci  return flushAsyncEvents(0).then(() => {
2271cb0ef41Sopenharmony_ci    assert_array_equals(rs.events, ['pull'], 'cancel should not have been called');
2281cb0ef41Sopenharmony_ci  });
2291cb0ef41Sopenharmony_ci}, 'preventCancel should work');
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_cipromise_test(() => {
2321cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
2331cb0ef41Sopenharmony_ci    start(controller) {
2341cb0ef41Sopenharmony_ci      controller.close();
2351cb0ef41Sopenharmony_ci    }
2361cb0ef41Sopenharmony_ci  });
2371cb0ef41Sopenharmony_ci  const writable = recordingWritableStream();
2381cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
2391cb0ef41Sopenharmony_ci  rs.pipeThrough({ writable, readable }, { preventClose: true });
2401cb0ef41Sopenharmony_ci  return flushAsyncEvents(0).then(() => {
2411cb0ef41Sopenharmony_ci    assert_array_equals(writable.events, [], 'writable should not be closed');
2421cb0ef41Sopenharmony_ci  });
2431cb0ef41Sopenharmony_ci}, 'preventClose should work');
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_cipromise_test(() => {
2461cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
2471cb0ef41Sopenharmony_ci    start(controller) {
2481cb0ef41Sopenharmony_ci      controller.error();
2491cb0ef41Sopenharmony_ci    }
2501cb0ef41Sopenharmony_ci  });
2511cb0ef41Sopenharmony_ci  const writable = recordingWritableStream();
2521cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
2531cb0ef41Sopenharmony_ci  rs.pipeThrough({ writable, readable }, { preventAbort: true });
2541cb0ef41Sopenharmony_ci  return flushAsyncEvents(0).then(() => {
2551cb0ef41Sopenharmony_ci    assert_array_equals(writable.events, [], 'writable should not be aborted');
2561cb0ef41Sopenharmony_ci  });
2571cb0ef41Sopenharmony_ci}, 'preventAbort should work');
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_citest(() => {
2601cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
2611cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
2621cb0ef41Sopenharmony_ci  const writable = new WritableStream();
2631cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => rs.pipeThrough({readable, writable}, {
2641cb0ef41Sopenharmony_ci    get preventAbort() {
2651cb0ef41Sopenharmony_ci      writable.getWriter();
2661cb0ef41Sopenharmony_ci    }
2671cb0ef41Sopenharmony_ci  }), 'pipeThrough should throw');
2681cb0ef41Sopenharmony_ci}, 'pipeThrough() should throw if an option getter grabs a writer');
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_citest(() => {
2711cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
2721cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
2731cb0ef41Sopenharmony_ci  const writable = new WritableStream();
2741cb0ef41Sopenharmony_ci  rs.pipeThrough({readable, writable}, null);
2751cb0ef41Sopenharmony_ci}, 'pipeThrough() should not throw if option is null');
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_citest(() => {
2781cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
2791cb0ef41Sopenharmony_ci  const readable = new ReadableStream();
2801cb0ef41Sopenharmony_ci  const writable = new WritableStream();
2811cb0ef41Sopenharmony_ci  rs.pipeThrough({readable, writable}, {signal:undefined});
2821cb0ef41Sopenharmony_ci}, 'pipeThrough() should not throw if signal is undefined');
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_cifunction tryPipeThrough(pair, options)
2851cb0ef41Sopenharmony_ci{
2861cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
2871cb0ef41Sopenharmony_ci  if (!pair)
2881cb0ef41Sopenharmony_ci    pair = {readable:new ReadableStream(), writable:new WritableStream()};
2891cb0ef41Sopenharmony_ci  try {
2901cb0ef41Sopenharmony_ci    rs.pipeThrough(pair, options)
2911cb0ef41Sopenharmony_ci  } catch (e) {
2921cb0ef41Sopenharmony_ci    return e;
2931cb0ef41Sopenharmony_ci  }
2941cb0ef41Sopenharmony_ci}
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_citest(() => {
2971cb0ef41Sopenharmony_ci  let result = tryPipeThrough({
2981cb0ef41Sopenharmony_ci    get readable() {
2991cb0ef41Sopenharmony_ci      return new ReadableStream();
3001cb0ef41Sopenharmony_ci    },
3011cb0ef41Sopenharmony_ci    get writable() {
3021cb0ef41Sopenharmony_ci      throw "writable threw";
3031cb0ef41Sopenharmony_ci    }
3041cb0ef41Sopenharmony_ci  }, { });
3051cb0ef41Sopenharmony_ci  assert_equals(result, "writable threw");
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci  result = tryPipeThrough({
3081cb0ef41Sopenharmony_ci    get readable() {
3091cb0ef41Sopenharmony_ci      throw "readable threw";
3101cb0ef41Sopenharmony_ci    },
3111cb0ef41Sopenharmony_ci    get writable() {
3121cb0ef41Sopenharmony_ci      throw "writable threw";
3131cb0ef41Sopenharmony_ci    }
3141cb0ef41Sopenharmony_ci  }, { });
3151cb0ef41Sopenharmony_ci  assert_equals(result, "readable threw");
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci  result = tryPipeThrough({
3181cb0ef41Sopenharmony_ci    get readable() {
3191cb0ef41Sopenharmony_ci      throw "readable threw";
3201cb0ef41Sopenharmony_ci    },
3211cb0ef41Sopenharmony_ci    get writable() {
3221cb0ef41Sopenharmony_ci      throw "writable threw";
3231cb0ef41Sopenharmony_ci    }
3241cb0ef41Sopenharmony_ci  }, {
3251cb0ef41Sopenharmony_ci    get preventAbort() {
3261cb0ef41Sopenharmony_ci      throw "preventAbort threw";
3271cb0ef41Sopenharmony_ci    }
3281cb0ef41Sopenharmony_ci  });
3291cb0ef41Sopenharmony_ci  assert_equals(result, "readable threw");
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_ci}, 'pipeThrough() should throw if readable/writable getters throw');
332