11cb0ef41Sopenharmony_ci// META: global=window,worker
21cb0ef41Sopenharmony_ci// META: script=../resources/recording-streams.js
31cb0ef41Sopenharmony_ci// META: script=../resources/test-utils.js
41cb0ef41Sopenharmony_ci'use strict';
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciconst error1 = new Error('error1 message');
71cb0ef41Sopenharmony_cierror1.name = 'error1';
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cipromise_test(() => {
101cb0ef41Sopenharmony_ci  const ts = recordingTransformStream();
111cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
121cb0ef41Sopenharmony_ci  // This call never resolves.
131cb0ef41Sopenharmony_ci  writer.write('a');
141cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
151cb0ef41Sopenharmony_ci    assert_array_equals(ts.events, [], 'transform should not be called');
161cb0ef41Sopenharmony_ci  });
171cb0ef41Sopenharmony_ci}, 'backpressure allows no transforms with a default identity transform and no reader');
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cipromise_test(() => {
201cb0ef41Sopenharmony_ci  const ts = recordingTransformStream({}, undefined, { highWaterMark: 1 });
211cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
221cb0ef41Sopenharmony_ci  // This call to write() resolves asynchronously.
231cb0ef41Sopenharmony_ci  writer.write('a');
241cb0ef41Sopenharmony_ci  // This call to write() waits for backpressure that is never relieved and never calls transform().
251cb0ef41Sopenharmony_ci  writer.write('b');
261cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
271cb0ef41Sopenharmony_ci    assert_array_equals(ts.events, ['transform', 'a'], 'transform should be called once');
281cb0ef41Sopenharmony_ci  });
291cb0ef41Sopenharmony_ci}, 'backpressure only allows one transform() with a identity transform with a readable HWM of 1 and no reader');
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cipromise_test(() => {
321cb0ef41Sopenharmony_ci  // Without a transform() implementation, recordingTransformStream() never enqueues anything.
331cb0ef41Sopenharmony_ci  const ts = recordingTransformStream({
341cb0ef41Sopenharmony_ci    transform() {
351cb0ef41Sopenharmony_ci      // Discard all chunks. As a result, the readable side is never full enough to exert backpressure and transform()
361cb0ef41Sopenharmony_ci      // keeps being called.
371cb0ef41Sopenharmony_ci    }
381cb0ef41Sopenharmony_ci  }, undefined, { highWaterMark: 1 });
391cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
401cb0ef41Sopenharmony_ci  const writePromises = [];
411cb0ef41Sopenharmony_ci  for (let i = 0; i < 4; ++i) {
421cb0ef41Sopenharmony_ci    writePromises.push(writer.write(i));
431cb0ef41Sopenharmony_ci  }
441cb0ef41Sopenharmony_ci  return Promise.all(writePromises).then(() => {
451cb0ef41Sopenharmony_ci    assert_array_equals(ts.events, ['transform', 0, 'transform', 1, 'transform', 2, 'transform', 3],
461cb0ef41Sopenharmony_ci                        'all 4 events should be transformed');
471cb0ef41Sopenharmony_ci  });
481cb0ef41Sopenharmony_ci}, 'transform() should keep being called as long as there is no backpressure');
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_cipromise_test(() => {
511cb0ef41Sopenharmony_ci  const ts = new TransformStream({}, undefined, { highWaterMark: 1 });
521cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
531cb0ef41Sopenharmony_ci  const reader = ts.readable.getReader();
541cb0ef41Sopenharmony_ci  const events = [];
551cb0ef41Sopenharmony_ci  const writerPromises = [
561cb0ef41Sopenharmony_ci    writer.write('a').then(() => events.push('a')),
571cb0ef41Sopenharmony_ci    writer.write('b').then(() => events.push('b')),
581cb0ef41Sopenharmony_ci    writer.close().then(() => events.push('closed'))];
591cb0ef41Sopenharmony_ci  return delay(0).then(() => {
601cb0ef41Sopenharmony_ci    assert_array_equals(events, ['a'], 'the first write should have resolved');
611cb0ef41Sopenharmony_ci    return reader.read();
621cb0ef41Sopenharmony_ci  }).then(({ value, done }) => {
631cb0ef41Sopenharmony_ci    assert_false(done, 'done should not be true');
641cb0ef41Sopenharmony_ci    assert_equals('a', value, 'value should be "a"');
651cb0ef41Sopenharmony_ci    return delay(0);
661cb0ef41Sopenharmony_ci  }).then(() => {
671cb0ef41Sopenharmony_ci    assert_array_equals(events, ['a', 'b', 'closed'], 'both writes and close() should have resolved');
681cb0ef41Sopenharmony_ci    return reader.read();
691cb0ef41Sopenharmony_ci  }).then(({ value, done }) => {
701cb0ef41Sopenharmony_ci    assert_false(done, 'done should still not be true');
711cb0ef41Sopenharmony_ci    assert_equals('b', value, 'value should be "b"');
721cb0ef41Sopenharmony_ci    return reader.read();
731cb0ef41Sopenharmony_ci  }).then(({ done }) => {
741cb0ef41Sopenharmony_ci    assert_true(done, 'done should be true');
751cb0ef41Sopenharmony_ci    return writerPromises;
761cb0ef41Sopenharmony_ci  });
771cb0ef41Sopenharmony_ci}, 'writes should resolve as soon as transform completes');
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_cipromise_test(() => {
801cb0ef41Sopenharmony_ci  const ts = new TransformStream(undefined, undefined, { highWaterMark: 0 });
811cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
821cb0ef41Sopenharmony_ci  const reader = ts.readable.getReader();
831cb0ef41Sopenharmony_ci  const readPromise = reader.read();
841cb0ef41Sopenharmony_ci  writer.write('a');
851cb0ef41Sopenharmony_ci  return readPromise.then(({ value, done }) => {
861cb0ef41Sopenharmony_ci    assert_false(done, 'not done');
871cb0ef41Sopenharmony_ci    assert_equals(value, 'a', 'value should be "a"');
881cb0ef41Sopenharmony_ci  });
891cb0ef41Sopenharmony_ci}, 'calling pull() before the first write() with backpressure should work');
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_cipromise_test(() => {
921cb0ef41Sopenharmony_ci  let reader;
931cb0ef41Sopenharmony_ci  const ts = recordingTransformStream({
941cb0ef41Sopenharmony_ci    transform(chunk, controller) {
951cb0ef41Sopenharmony_ci      controller.enqueue(chunk);
961cb0ef41Sopenharmony_ci      return reader.read();
971cb0ef41Sopenharmony_ci    }
981cb0ef41Sopenharmony_ci  }, undefined, { highWaterMark: 1 });
991cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
1001cb0ef41Sopenharmony_ci  reader = ts.readable.getReader();
1011cb0ef41Sopenharmony_ci  return writer.write('a');
1021cb0ef41Sopenharmony_ci}, 'transform() should be able to read the chunk it just enqueued');
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_cipromise_test(() => {
1051cb0ef41Sopenharmony_ci  let resolveTransform;
1061cb0ef41Sopenharmony_ci  const transformPromise = new Promise(resolve => {
1071cb0ef41Sopenharmony_ci    resolveTransform = resolve;
1081cb0ef41Sopenharmony_ci  });
1091cb0ef41Sopenharmony_ci  const ts = recordingTransformStream({
1101cb0ef41Sopenharmony_ci    transform() {
1111cb0ef41Sopenharmony_ci      return transformPromise;
1121cb0ef41Sopenharmony_ci    }
1131cb0ef41Sopenharmony_ci  }, undefined, new CountQueuingStrategy({ highWaterMark: Infinity }));
1141cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
1151cb0ef41Sopenharmony_ci  assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
1161cb0ef41Sopenharmony_ci  return delay(0).then(() => {
1171cb0ef41Sopenharmony_ci    writer.write('a');
1181cb0ef41Sopenharmony_ci    assert_array_equals(ts.events, ['transform', 'a']);
1191cb0ef41Sopenharmony_ci    assert_equals(writer.desiredSize, 0, 'desiredSize should be 0');
1201cb0ef41Sopenharmony_ci    return flushAsyncEvents();
1211cb0ef41Sopenharmony_ci  }).then(() => {
1221cb0ef41Sopenharmony_ci    assert_equals(writer.desiredSize, 0, 'desiredSize should still be 0');
1231cb0ef41Sopenharmony_ci    resolveTransform();
1241cb0ef41Sopenharmony_ci    return delay(0);
1251cb0ef41Sopenharmony_ci  }).then(() => {
1261cb0ef41Sopenharmony_ci    assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
1271cb0ef41Sopenharmony_ci  });
1281cb0ef41Sopenharmony_ci}, 'blocking transform() should cause backpressure');
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_cipromise_test(t => {
1311cb0ef41Sopenharmony_ci  const ts = new TransformStream();
1321cb0ef41Sopenharmony_ci  ts.readable.cancel(error1);
1331cb0ef41Sopenharmony_ci  return promise_rejects_exactly(t, error1, ts.writable.getWriter().closed, 'closed should reject');
1341cb0ef41Sopenharmony_ci}, 'writer.closed should resolve after readable is canceled during start');
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_cipromise_test(t => {
1371cb0ef41Sopenharmony_ci  const ts = new TransformStream({}, undefined, { highWaterMark: 0 });
1381cb0ef41Sopenharmony_ci  return delay(0).then(() => {
1391cb0ef41Sopenharmony_ci    ts.readable.cancel(error1);
1401cb0ef41Sopenharmony_ci    return promise_rejects_exactly(t, error1, ts.writable.getWriter().closed, 'closed should reject');
1411cb0ef41Sopenharmony_ci  });
1421cb0ef41Sopenharmony_ci}, 'writer.closed should resolve after readable is canceled with backpressure');
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_cipromise_test(t => {
1451cb0ef41Sopenharmony_ci  const ts = new TransformStream({}, undefined, { highWaterMark: 1 });
1461cb0ef41Sopenharmony_ci  return delay(0).then(() => {
1471cb0ef41Sopenharmony_ci    ts.readable.cancel(error1);
1481cb0ef41Sopenharmony_ci    return promise_rejects_exactly(t, error1, ts.writable.getWriter().closed, 'closed should reject');
1491cb0ef41Sopenharmony_ci  });
1501cb0ef41Sopenharmony_ci}, 'writer.closed should resolve after readable is canceled with no backpressure');
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_cipromise_test(() => {
1531cb0ef41Sopenharmony_ci  const ts = new TransformStream({}, undefined, { highWaterMark: 1 });
1541cb0ef41Sopenharmony_ci  const writer = ts.writable.getWriter();
1551cb0ef41Sopenharmony_ci  return delay(0).then(() => {
1561cb0ef41Sopenharmony_ci    const writePromise = writer.write('a');
1571cb0ef41Sopenharmony_ci    ts.readable.cancel(error1);
1581cb0ef41Sopenharmony_ci    return writePromise;
1591cb0ef41Sopenharmony_ci  });
1601cb0ef41Sopenharmony_ci}, 'cancelling the readable should cause a pending write to resolve');
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_cipromise_test(t => {
1631cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
1641cb0ef41Sopenharmony_ci  const ts = new TransformStream();
1651cb0ef41Sopenharmony_ci  const pipePromise = rs.pipeTo(ts.writable);
1661cb0ef41Sopenharmony_ci  ts.readable.cancel(error1);
1671cb0ef41Sopenharmony_ci  return promise_rejects_exactly(t, error1, pipePromise, 'promise returned from pipeTo() should be rejected');
1681cb0ef41Sopenharmony_ci}, 'cancelling the readable side of a TransformStream should abort an empty pipe');
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_cipromise_test(t => {
1711cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
1721cb0ef41Sopenharmony_ci  const ts = new TransformStream();
1731cb0ef41Sopenharmony_ci  const pipePromise = rs.pipeTo(ts.writable);
1741cb0ef41Sopenharmony_ci  return delay(0).then(() => {
1751cb0ef41Sopenharmony_ci    ts.readable.cancel(error1);
1761cb0ef41Sopenharmony_ci    return promise_rejects_exactly(t, error1, pipePromise, 'promise returned from pipeTo() should be rejected');
1771cb0ef41Sopenharmony_ci  });
1781cb0ef41Sopenharmony_ci}, 'cancelling the readable side of a TransformStream should abort an empty pipe after startup');
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_cipromise_test(t => {
1811cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
1821cb0ef41Sopenharmony_ci    start(controller) {
1831cb0ef41Sopenharmony_ci      controller.enqueue('a');
1841cb0ef41Sopenharmony_ci      controller.enqueue('b');
1851cb0ef41Sopenharmony_ci      controller.enqueue('c');
1861cb0ef41Sopenharmony_ci    }
1871cb0ef41Sopenharmony_ci  });
1881cb0ef41Sopenharmony_ci  const ts = new TransformStream();
1891cb0ef41Sopenharmony_ci  const pipePromise = rs.pipeTo(ts.writable);
1901cb0ef41Sopenharmony_ci  // Allow data to flow into the pipe.
1911cb0ef41Sopenharmony_ci  return delay(0).then(() => {
1921cb0ef41Sopenharmony_ci    ts.readable.cancel(error1);
1931cb0ef41Sopenharmony_ci    return promise_rejects_exactly(t, error1, pipePromise, 'promise returned from pipeTo() should be rejected');
1941cb0ef41Sopenharmony_ci  });
1951cb0ef41Sopenharmony_ci}, 'cancelling the readable side of a TransformStream should abort a full pipe');
196