11cb0ef41Sopenharmony_ci// META: global=window,worker
21cb0ef41Sopenharmony_ci// META: script=../resources/test-utils.js
31cb0ef41Sopenharmony_ci// META: script=../resources/rs-utils.js
41cb0ef41Sopenharmony_ci'use strict';
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_citest(() => {
71cb0ef41Sopenharmony_ci  new TransformStream({ transform() { } });
81cb0ef41Sopenharmony_ci}, 'TransformStream can be constructed with a transform function');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_citest(() => {
111cb0ef41Sopenharmony_ci  new TransformStream();
121cb0ef41Sopenharmony_ci  new TransformStream({});
131cb0ef41Sopenharmony_ci}, 'TransformStream can be constructed with no transform function');
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_citest(() => {
161cb0ef41Sopenharmony_ci  const ts = new TransformStream({ transform() { } });
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
191cb0ef41Sopenharmony_ci  assert_equals(writer.desiredSize, 1, 'writer.desiredSize should be 1');
201cb0ef41Sopenharmony_ci}, 'TransformStream writable starts in the writable state');
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cipromise_test(() => {
231cb0ef41Sopenharmony_ci  const ts = new TransformStream();
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
261cb0ef41Sopenharmony_ci  writer.write('a');
271cb0ef41Sopenharmony_ci  assert_equals(writer.desiredSize, 0, 'writer.desiredSize should be 0 after write()');
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  return ts.readable.getReader().read().then(result => {
301cb0ef41Sopenharmony_ci    assert_equals(result.value, 'a',
311cb0ef41Sopenharmony_ci      'result from reading the readable is the same as was written to writable');
321cb0ef41Sopenharmony_ci    assert_false(result.done, 'stream should not be done');
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci    return delay(0).then(() => assert_equals(writer.desiredSize, 1, 'desiredSize should be 1 again'));
351cb0ef41Sopenharmony_ci  });
361cb0ef41Sopenharmony_ci}, 'Identity TransformStream: can read from readable what is put into writable');
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cipromise_test(() => {
391cb0ef41Sopenharmony_ci  let c;
401cb0ef41Sopenharmony_ci  const ts = new TransformStream({
411cb0ef41Sopenharmony_ci    start(controller) {
421cb0ef41Sopenharmony_ci      c = controller;
431cb0ef41Sopenharmony_ci    },
441cb0ef41Sopenharmony_ci    transform(chunk) {
451cb0ef41Sopenharmony_ci      c.enqueue(chunk.toUpperCase());
461cb0ef41Sopenharmony_ci    }
471cb0ef41Sopenharmony_ci  });
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
501cb0ef41Sopenharmony_ci  writer.write('a');
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  return ts.readable.getReader().read().then(result => {
531cb0ef41Sopenharmony_ci    assert_equals(result.value, 'A',
541cb0ef41Sopenharmony_ci      'result from reading the readable is the transformation of what was written to writable');
551cb0ef41Sopenharmony_ci    assert_false(result.done, 'stream should not be done');
561cb0ef41Sopenharmony_ci  });
571cb0ef41Sopenharmony_ci}, 'Uppercaser sync TransformStream: can read from readable transformed version of what is put into writable');
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_cipromise_test(() => {
601cb0ef41Sopenharmony_ci  let c;
611cb0ef41Sopenharmony_ci  const ts = new TransformStream({
621cb0ef41Sopenharmony_ci    start(controller) {
631cb0ef41Sopenharmony_ci      c = controller;
641cb0ef41Sopenharmony_ci    },
651cb0ef41Sopenharmony_ci    transform(chunk) {
661cb0ef41Sopenharmony_ci      c.enqueue(chunk.toUpperCase());
671cb0ef41Sopenharmony_ci      c.enqueue(chunk.toUpperCase());
681cb0ef41Sopenharmony_ci    }
691cb0ef41Sopenharmony_ci  });
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
721cb0ef41Sopenharmony_ci  writer.write('a');
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  const reader = ts.readable.getReader();
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  return reader.read().then(result1 => {
771cb0ef41Sopenharmony_ci    assert_equals(result1.value, 'A',
781cb0ef41Sopenharmony_ci      'the first chunk read is the transformation of the single chunk written');
791cb0ef41Sopenharmony_ci    assert_false(result1.done, 'stream should not be done');
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci    return reader.read().then(result2 => {
821cb0ef41Sopenharmony_ci      assert_equals(result2.value, 'A',
831cb0ef41Sopenharmony_ci        'the second chunk read is also the transformation of the single chunk written');
841cb0ef41Sopenharmony_ci      assert_false(result2.done, 'stream should not be done');
851cb0ef41Sopenharmony_ci    });
861cb0ef41Sopenharmony_ci  });
871cb0ef41Sopenharmony_ci}, 'Uppercaser-doubler sync TransformStream: can read both chunks put into the readable');
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_cipromise_test(() => {
901cb0ef41Sopenharmony_ci  let c;
911cb0ef41Sopenharmony_ci  const ts = new TransformStream({
921cb0ef41Sopenharmony_ci    start(controller) {
931cb0ef41Sopenharmony_ci      c = controller;
941cb0ef41Sopenharmony_ci    },
951cb0ef41Sopenharmony_ci    transform(chunk) {
961cb0ef41Sopenharmony_ci      return delay(0).then(() => c.enqueue(chunk.toUpperCase()));
971cb0ef41Sopenharmony_ci    }
981cb0ef41Sopenharmony_ci  });
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
1011cb0ef41Sopenharmony_ci  writer.write('a');
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  return ts.readable.getReader().read().then(result => {
1041cb0ef41Sopenharmony_ci    assert_equals(result.value, 'A',
1051cb0ef41Sopenharmony_ci      'result from reading the readable is the transformation of what was written to writable');
1061cb0ef41Sopenharmony_ci    assert_false(result.done, 'stream should not be done');
1071cb0ef41Sopenharmony_ci  });
1081cb0ef41Sopenharmony_ci}, 'Uppercaser async TransformStream: can read from readable transformed version of what is put into writable');
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_cipromise_test(() => {
1111cb0ef41Sopenharmony_ci  let doSecondEnqueue;
1121cb0ef41Sopenharmony_ci  let returnFromTransform;
1131cb0ef41Sopenharmony_ci  const ts = new TransformStream({
1141cb0ef41Sopenharmony_ci    transform(chunk, controller) {
1151cb0ef41Sopenharmony_ci      delay(0).then(() => controller.enqueue(chunk.toUpperCase()));
1161cb0ef41Sopenharmony_ci      doSecondEnqueue = () => controller.enqueue(chunk.toUpperCase());
1171cb0ef41Sopenharmony_ci      return new Promise(resolve => {
1181cb0ef41Sopenharmony_ci        returnFromTransform = resolve;
1191cb0ef41Sopenharmony_ci      });
1201cb0ef41Sopenharmony_ci    }
1211cb0ef41Sopenharmony_ci  });
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  const reader = ts.readable.getReader();
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
1261cb0ef41Sopenharmony_ci  writer.write('a');
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci  return reader.read().then(result1 => {
1291cb0ef41Sopenharmony_ci    assert_equals(result1.value, 'A',
1301cb0ef41Sopenharmony_ci      'the first chunk read is the transformation of the single chunk written');
1311cb0ef41Sopenharmony_ci    assert_false(result1.done, 'stream should not be done');
1321cb0ef41Sopenharmony_ci    doSecondEnqueue();
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci    return reader.read().then(result2 => {
1351cb0ef41Sopenharmony_ci      assert_equals(result2.value, 'A',
1361cb0ef41Sopenharmony_ci        'the second chunk read is also the transformation of the single chunk written');
1371cb0ef41Sopenharmony_ci      assert_false(result2.done, 'stream should not be done');
1381cb0ef41Sopenharmony_ci      returnFromTransform();
1391cb0ef41Sopenharmony_ci    });
1401cb0ef41Sopenharmony_ci  });
1411cb0ef41Sopenharmony_ci}, 'Uppercaser-doubler async TransformStream: can read both chunks put into the readable');
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_cipromise_test(() => {
1441cb0ef41Sopenharmony_ci  const ts = new TransformStream({ transform() { } });
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
1471cb0ef41Sopenharmony_ci  writer.close();
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  return Promise.all([writer.closed, ts.readable.getReader().closed]);
1501cb0ef41Sopenharmony_ci}, 'TransformStream: by default, closing the writable closes the readable (when there are no queued writes)');
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_cipromise_test(() => {
1531cb0ef41Sopenharmony_ci  let transformResolve;
1541cb0ef41Sopenharmony_ci  const transformPromise = new Promise(resolve => {
1551cb0ef41Sopenharmony_ci    transformResolve = resolve;
1561cb0ef41Sopenharmony_ci  });
1571cb0ef41Sopenharmony_ci  const ts = new TransformStream({
1581cb0ef41Sopenharmony_ci    transform() {
1591cb0ef41Sopenharmony_ci      return transformPromise;
1601cb0ef41Sopenharmony_ci    }
1611cb0ef41Sopenharmony_ci  }, undefined, { highWaterMark: 1 });
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
1641cb0ef41Sopenharmony_ci  writer.write('a');
1651cb0ef41Sopenharmony_ci  writer.close();
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  let rsClosed = false;
1681cb0ef41Sopenharmony_ci  ts.readable.getReader().closed.then(() => {
1691cb0ef41Sopenharmony_ci    rsClosed = true;
1701cb0ef41Sopenharmony_ci  });
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  return delay(0).then(() => {
1731cb0ef41Sopenharmony_ci    assert_equals(rsClosed, false, 'readable is not closed after a tick');
1741cb0ef41Sopenharmony_ci    transformResolve();
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci    return writer.closed.then(() => {
1771cb0ef41Sopenharmony_ci      // TODO: Is this expectation correct?
1781cb0ef41Sopenharmony_ci      assert_equals(rsClosed, true, 'readable is closed at that point');
1791cb0ef41Sopenharmony_ci    });
1801cb0ef41Sopenharmony_ci  });
1811cb0ef41Sopenharmony_ci}, 'TransformStream: by default, closing the writable waits for transforms to finish before closing both');
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_cipromise_test(() => {
1841cb0ef41Sopenharmony_ci  let c;
1851cb0ef41Sopenharmony_ci  const ts = new TransformStream({
1861cb0ef41Sopenharmony_ci    start(controller) {
1871cb0ef41Sopenharmony_ci      c = controller;
1881cb0ef41Sopenharmony_ci    },
1891cb0ef41Sopenharmony_ci    transform() {
1901cb0ef41Sopenharmony_ci      c.enqueue('x');
1911cb0ef41Sopenharmony_ci      c.enqueue('y');
1921cb0ef41Sopenharmony_ci      return delay(0);
1931cb0ef41Sopenharmony_ci    }
1941cb0ef41Sopenharmony_ci  });
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
1971cb0ef41Sopenharmony_ci  writer.write('a');
1981cb0ef41Sopenharmony_ci  writer.close();
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  const readableChunks = readableStreamToArray(ts.readable);
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  return writer.closed.then(() => {
2031cb0ef41Sopenharmony_ci    return readableChunks.then(chunks => {
2041cb0ef41Sopenharmony_ci      assert_array_equals(chunks, ['x', 'y'], 'both enqueued chunks can be read from the readable');
2051cb0ef41Sopenharmony_ci    });
2061cb0ef41Sopenharmony_ci  });
2071cb0ef41Sopenharmony_ci}, 'TransformStream: by default, closing the writable closes the readable after sync enqueues and async done');
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_cipromise_test(() => {
2101cb0ef41Sopenharmony_ci  let c;
2111cb0ef41Sopenharmony_ci  const ts = new TransformStream({
2121cb0ef41Sopenharmony_ci    start(controller) {
2131cb0ef41Sopenharmony_ci      c = controller;
2141cb0ef41Sopenharmony_ci    },
2151cb0ef41Sopenharmony_ci    transform() {
2161cb0ef41Sopenharmony_ci      return delay(0)
2171cb0ef41Sopenharmony_ci          .then(() => c.enqueue('x'))
2181cb0ef41Sopenharmony_ci          .then(() => c.enqueue('y'))
2191cb0ef41Sopenharmony_ci          .then(() => delay(0));
2201cb0ef41Sopenharmony_ci    }
2211cb0ef41Sopenharmony_ci  });
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
2241cb0ef41Sopenharmony_ci  writer.write('a');
2251cb0ef41Sopenharmony_ci  writer.close();
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci  const readableChunks = readableStreamToArray(ts.readable);
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  return writer.closed.then(() => {
2301cb0ef41Sopenharmony_ci    return readableChunks.then(chunks => {
2311cb0ef41Sopenharmony_ci      assert_array_equals(chunks, ['x', 'y'], 'both enqueued chunks can be read from the readable');
2321cb0ef41Sopenharmony_ci    });
2331cb0ef41Sopenharmony_ci  });
2341cb0ef41Sopenharmony_ci}, 'TransformStream: by default, closing the writable closes the readable after async enqueues and async done');
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_cipromise_test(() => {
2371cb0ef41Sopenharmony_ci  let c;
2381cb0ef41Sopenharmony_ci  const ts = new TransformStream({
2391cb0ef41Sopenharmony_ci    suffix: '-suffix',
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci    start(controller) {
2421cb0ef41Sopenharmony_ci      c = controller;
2431cb0ef41Sopenharmony_ci      c.enqueue('start' + this.suffix);
2441cb0ef41Sopenharmony_ci    },
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci    transform(chunk) {
2471cb0ef41Sopenharmony_ci      c.enqueue(chunk + this.suffix);
2481cb0ef41Sopenharmony_ci    },
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci    flush() {
2511cb0ef41Sopenharmony_ci      c.enqueue('flushed' + this.suffix);
2521cb0ef41Sopenharmony_ci    }
2531cb0ef41Sopenharmony_ci  });
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
2561cb0ef41Sopenharmony_ci  writer.write('a');
2571cb0ef41Sopenharmony_ci  writer.close();
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci  const readableChunks = readableStreamToArray(ts.readable);
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci  return writer.closed.then(() => {
2621cb0ef41Sopenharmony_ci    return readableChunks.then(chunks => {
2631cb0ef41Sopenharmony_ci      assert_array_equals(chunks, ['start-suffix', 'a-suffix', 'flushed-suffix'], 'all enqueued chunks have suffixes');
2641cb0ef41Sopenharmony_ci    });
2651cb0ef41Sopenharmony_ci  });
2661cb0ef41Sopenharmony_ci}, 'Transform stream should call transformer methods as methods');
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_cipromise_test(() => {
2691cb0ef41Sopenharmony_ci  function functionWithOverloads() {}
2701cb0ef41Sopenharmony_ci  functionWithOverloads.apply = () => assert_unreached('apply() should not be called');
2711cb0ef41Sopenharmony_ci  functionWithOverloads.call = () => assert_unreached('call() should not be called');
2721cb0ef41Sopenharmony_ci  const ts = new TransformStream({
2731cb0ef41Sopenharmony_ci    start: functionWithOverloads,
2741cb0ef41Sopenharmony_ci    transform: functionWithOverloads,
2751cb0ef41Sopenharmony_ci    flush: functionWithOverloads
2761cb0ef41Sopenharmony_ci  });
2771cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
2781cb0ef41Sopenharmony_ci  writer.write('a');
2791cb0ef41Sopenharmony_ci  writer.close();
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci  return readableStreamToArray(ts.readable);
2821cb0ef41Sopenharmony_ci}, 'methods should not not have .apply() or .call() called');
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_cipromise_test(t => {
2851cb0ef41Sopenharmony_ci  let startCalled = false;
2861cb0ef41Sopenharmony_ci  let startDone = false;
2871cb0ef41Sopenharmony_ci  let transformDone = false;
2881cb0ef41Sopenharmony_ci  let flushDone = false;
2891cb0ef41Sopenharmony_ci  const ts = new TransformStream({
2901cb0ef41Sopenharmony_ci    start() {
2911cb0ef41Sopenharmony_ci      startCalled = true;
2921cb0ef41Sopenharmony_ci      return flushAsyncEvents().then(() => {
2931cb0ef41Sopenharmony_ci        startDone = true;
2941cb0ef41Sopenharmony_ci      });
2951cb0ef41Sopenharmony_ci    },
2961cb0ef41Sopenharmony_ci    transform() {
2971cb0ef41Sopenharmony_ci      return t.step(() => {
2981cb0ef41Sopenharmony_ci        assert_true(startDone, 'transform() should not be called until the promise returned from start() has resolved');
2991cb0ef41Sopenharmony_ci        return flushAsyncEvents().then(() => {
3001cb0ef41Sopenharmony_ci          transformDone = true;
3011cb0ef41Sopenharmony_ci        });
3021cb0ef41Sopenharmony_ci      });
3031cb0ef41Sopenharmony_ci    },
3041cb0ef41Sopenharmony_ci    flush() {
3051cb0ef41Sopenharmony_ci      return t.step(() => {
3061cb0ef41Sopenharmony_ci        assert_true(transformDone,
3071cb0ef41Sopenharmony_ci                    'flush() should not be called until the promise returned from transform() has resolved');
3081cb0ef41Sopenharmony_ci        return flushAsyncEvents().then(() => {
3091cb0ef41Sopenharmony_ci          flushDone = true;
3101cb0ef41Sopenharmony_ci        });
3111cb0ef41Sopenharmony_ci      });
3121cb0ef41Sopenharmony_ci    }
3131cb0ef41Sopenharmony_ci  }, undefined, { highWaterMark: 1 });
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci  assert_true(startCalled, 'start() should be called synchronously');
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
3181cb0ef41Sopenharmony_ci  const writePromise = writer.write('a');
3191cb0ef41Sopenharmony_ci  return writer.close().then(() => {
3201cb0ef41Sopenharmony_ci    assert_true(flushDone, 'promise returned from flush() should have resolved');
3211cb0ef41Sopenharmony_ci    return writePromise;
3221cb0ef41Sopenharmony_ci  });
3231cb0ef41Sopenharmony_ci}, 'TransformStream start, transform, and flush should be strictly ordered');
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_cipromise_test(() => {
3261cb0ef41Sopenharmony_ci  let transformCalled = false;
3271cb0ef41Sopenharmony_ci  const ts = new TransformStream({
3281cb0ef41Sopenharmony_ci    transform() {
3291cb0ef41Sopenharmony_ci      transformCalled = true;
3301cb0ef41Sopenharmony_ci    }
3311cb0ef41Sopenharmony_ci  }, undefined, { highWaterMark: Infinity });
3321cb0ef41Sopenharmony_ci  // transform() is only called synchronously when there is no backpressure and all microtasks have run.
3331cb0ef41Sopenharmony_ci  return delay(0).then(() => {
3341cb0ef41Sopenharmony_ci    const writePromise = ts.writable.getWriter().write();
3351cb0ef41Sopenharmony_ci    assert_true(transformCalled, 'transform() should have been called');
3361cb0ef41Sopenharmony_ci    return writePromise;
3371cb0ef41Sopenharmony_ci  });
3381cb0ef41Sopenharmony_ci}, 'it should be possible to call transform() synchronously');
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_cipromise_test(() => {
3411cb0ef41Sopenharmony_ci  const ts = new TransformStream({}, undefined, { highWaterMark: 0 });
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
3441cb0ef41Sopenharmony_ci  writer.close();
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci  return Promise.all([writer.closed, ts.readable.getReader().closed]);
3471cb0ef41Sopenharmony_ci}, 'closing the writable should close the readable when there are no queued chunks, even with backpressure');
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_citest(() => {
3501cb0ef41Sopenharmony_ci  new TransformStream({
3511cb0ef41Sopenharmony_ci    start(controller) {
3521cb0ef41Sopenharmony_ci      controller.terminate();
3531cb0ef41Sopenharmony_ci      assert_throws_js(TypeError, () => controller.enqueue(), 'enqueue should throw');
3541cb0ef41Sopenharmony_ci    }
3551cb0ef41Sopenharmony_ci  });
3561cb0ef41Sopenharmony_ci}, 'enqueue() should throw after controller.terminate()');
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_cipromise_test(() => {
3591cb0ef41Sopenharmony_ci  let controller;
3601cb0ef41Sopenharmony_ci  const ts = new TransformStream({
3611cb0ef41Sopenharmony_ci    start(c) {
3621cb0ef41Sopenharmony_ci      controller = c;
3631cb0ef41Sopenharmony_ci    }
3641cb0ef41Sopenharmony_ci  });
3651cb0ef41Sopenharmony_ci  const cancelPromise = ts.readable.cancel();
3661cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => controller.enqueue(), 'enqueue should throw');
3671cb0ef41Sopenharmony_ci  return cancelPromise;
3681cb0ef41Sopenharmony_ci}, 'enqueue() should throw after readable.cancel()');
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_citest(() => {
3711cb0ef41Sopenharmony_ci  new TransformStream({
3721cb0ef41Sopenharmony_ci    start(controller) {
3731cb0ef41Sopenharmony_ci      controller.terminate();
3741cb0ef41Sopenharmony_ci      controller.terminate();
3751cb0ef41Sopenharmony_ci    }
3761cb0ef41Sopenharmony_ci  });
3771cb0ef41Sopenharmony_ci}, 'controller.terminate() should do nothing the second time it is called');
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_cipromise_test(t => {
3801cb0ef41Sopenharmony_ci  let controller;
3811cb0ef41Sopenharmony_ci  const ts = new TransformStream({
3821cb0ef41Sopenharmony_ci    start(c) {
3831cb0ef41Sopenharmony_ci      controller = c;
3841cb0ef41Sopenharmony_ci    }
3851cb0ef41Sopenharmony_ci  });
3861cb0ef41Sopenharmony_ci  const cancelReason = { name: 'cancelReason' };
3871cb0ef41Sopenharmony_ci  const cancelPromise = ts.readable.cancel(cancelReason);
3881cb0ef41Sopenharmony_ci  controller.terminate();
3891cb0ef41Sopenharmony_ci  return Promise.all([
3901cb0ef41Sopenharmony_ci    cancelPromise,
3911cb0ef41Sopenharmony_ci    promise_rejects_exactly(t, cancelReason, ts.writable.getWriter().closed, 'closed should reject with cancelReason')
3921cb0ef41Sopenharmony_ci  ]);
3931cb0ef41Sopenharmony_ci}, 'terminate() should do nothing after readable.cancel()');
3941cb0ef41Sopenharmony_ci
3951cb0ef41Sopenharmony_cipromise_test(() => {
3961cb0ef41Sopenharmony_ci  let calls = 0;
3971cb0ef41Sopenharmony_ci  new TransformStream({
3981cb0ef41Sopenharmony_ci    start() {
3991cb0ef41Sopenharmony_ci      ++calls;
4001cb0ef41Sopenharmony_ci    }
4011cb0ef41Sopenharmony_ci  });
4021cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
4031cb0ef41Sopenharmony_ci    assert_equals(calls, 1, 'start() should have been called exactly once');
4041cb0ef41Sopenharmony_ci  });
4051cb0ef41Sopenharmony_ci}, 'start() should not be called twice');
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_citest(() => {
4081cb0ef41Sopenharmony_ci  assert_throws_js(RangeError, () => new TransformStream({ readableType: 'bytes' }), 'constructor should throw');
4091cb0ef41Sopenharmony_ci}, 'specifying a defined readableType should throw');
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_citest(() => {
4121cb0ef41Sopenharmony_ci  assert_throws_js(RangeError, () => new TransformStream({ writableType: 'bytes' }), 'constructor should throw');
4131cb0ef41Sopenharmony_ci}, 'specifying a defined writableType should throw');
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_citest(() => {
4161cb0ef41Sopenharmony_ci  class Subclass extends TransformStream {
4171cb0ef41Sopenharmony_ci    extraFunction() {
4181cb0ef41Sopenharmony_ci      return true;
4191cb0ef41Sopenharmony_ci    }
4201cb0ef41Sopenharmony_ci  }
4211cb0ef41Sopenharmony_ci  assert_equals(
4221cb0ef41Sopenharmony_ci      Object.getPrototypeOf(Subclass.prototype), TransformStream.prototype,
4231cb0ef41Sopenharmony_ci      'Subclass.prototype\'s prototype should be TransformStream.prototype');
4241cb0ef41Sopenharmony_ci  assert_equals(Object.getPrototypeOf(Subclass), TransformStream,
4251cb0ef41Sopenharmony_ci                'Subclass\'s prototype should be TransformStream');
4261cb0ef41Sopenharmony_ci  const sub = new Subclass();
4271cb0ef41Sopenharmony_ci  assert_true(sub instanceof TransformStream,
4281cb0ef41Sopenharmony_ci              'Subclass object should be an instance of TransformStream');
4291cb0ef41Sopenharmony_ci  assert_true(sub instanceof Subclass,
4301cb0ef41Sopenharmony_ci              'Subclass object should be an instance of Subclass');
4311cb0ef41Sopenharmony_ci  const readableGetter = Object.getOwnPropertyDescriptor(
4321cb0ef41Sopenharmony_ci      TransformStream.prototype, 'readable').get;
4331cb0ef41Sopenharmony_ci  assert_equals(readableGetter.call(sub), sub.readable,
4341cb0ef41Sopenharmony_ci                'Subclass object should pass brand check');
4351cb0ef41Sopenharmony_ci  assert_true(sub.extraFunction(),
4361cb0ef41Sopenharmony_ci              'extraFunction() should be present on Subclass object');
4371cb0ef41Sopenharmony_ci}, 'Subclassing TransformStream should work');
438