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_ciconst error1 = new Error('error1');
71cb0ef41Sopenharmony_cierror1.name = 'error1';
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_citest(() => {
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci  new ReadableStream(); // ReadableStream constructed with no parameters
121cb0ef41Sopenharmony_ci  new ReadableStream({ }); // ReadableStream constructed with an empty object as parameter
131cb0ef41Sopenharmony_ci  new ReadableStream({ type: undefined }); // ReadableStream constructed with undefined type
141cb0ef41Sopenharmony_ci  new ReadableStream(undefined); // ReadableStream constructed with undefined as parameter
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci  let x;
171cb0ef41Sopenharmony_ci  new ReadableStream(x); // ReadableStream constructed with an undefined variable as parameter
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci}, 'ReadableStream can be constructed with no errors');
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_citest(() => {
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => new ReadableStream(null), 'constructor should throw when the source is null');
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci}, 'ReadableStream can\'t be constructed with garbage');
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_citest(() => {
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => new ReadableStream({ type: null }),
301cb0ef41Sopenharmony_ci    'constructor should throw when the type is null');
311cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => new ReadableStream({ type: '' }),
321cb0ef41Sopenharmony_ci    'constructor should throw when the type is empty string');
331cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => new ReadableStream({ type: 'asdf' }),
341cb0ef41Sopenharmony_ci    'constructor should throw when the type is asdf');
351cb0ef41Sopenharmony_ci  assert_throws_exactly(
361cb0ef41Sopenharmony_ci    error1,
371cb0ef41Sopenharmony_ci    () => new ReadableStream({ type: { get toString() { throw error1; } } }),
381cb0ef41Sopenharmony_ci    'constructor should throw when ToString() throws'
391cb0ef41Sopenharmony_ci  );
401cb0ef41Sopenharmony_ci  assert_throws_exactly(
411cb0ef41Sopenharmony_ci    error1,
421cb0ef41Sopenharmony_ci    () => new ReadableStream({ type: { toString() { throw error1; } } }),
431cb0ef41Sopenharmony_ci    'constructor should throw when ToString() throws'
441cb0ef41Sopenharmony_ci  );
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci}, 'ReadableStream can\'t be constructed with an invalid type');
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_citest(() => {
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => {
511cb0ef41Sopenharmony_ci    new ReadableStream({ start: 'potato' });
521cb0ef41Sopenharmony_ci  }, 'constructor should throw when start is not a function');
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci}, 'ReadableStream constructor should throw for non-function start arguments');
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_citest(() => {
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => new ReadableStream({ cancel: '2' }), 'constructor should throw');
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci}, 'ReadableStream constructor will not tolerate initial garbage as cancel argument');
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_citest(() => {
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => new ReadableStream({ pull: { } }), 'constructor should throw');
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci}, 'ReadableStream constructor will not tolerate initial garbage as pull argument');
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_citest(() => {
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  let startCalled = false;
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  const source = {
731cb0ef41Sopenharmony_ci    start() {
741cb0ef41Sopenharmony_ci      assert_equals(this, source, 'source is this during start');
751cb0ef41Sopenharmony_ci      startCalled = true;
761cb0ef41Sopenharmony_ci    }
771cb0ef41Sopenharmony_ci  };
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  new ReadableStream(source);
801cb0ef41Sopenharmony_ci  assert_true(startCalled);
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci}, 'ReadableStream start should be called with the proper thisArg');
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_citest(() => {
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  let startCalled = false;
871cb0ef41Sopenharmony_ci  const source = {
881cb0ef41Sopenharmony_ci    start(controller) {
891cb0ef41Sopenharmony_ci      const properties = ['close', 'constructor', 'desiredSize', 'enqueue', 'error'];
901cb0ef41Sopenharmony_ci      assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), properties,
911cb0ef41Sopenharmony_ci        'prototype should have the right properties');
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci      controller.test = '';
941cb0ef41Sopenharmony_ci      assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), properties,
951cb0ef41Sopenharmony_ci        'prototype should still have the right properties');
961cb0ef41Sopenharmony_ci      assert_not_equals(Object.getOwnPropertyNames(controller).indexOf('test'), -1,
971cb0ef41Sopenharmony_ci        '"test" should be a property of the controller');
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci      startCalled = true;
1001cb0ef41Sopenharmony_ci    }
1011cb0ef41Sopenharmony_ci  };
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  new ReadableStream(source);
1041cb0ef41Sopenharmony_ci  assert_true(startCalled);
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci}, 'ReadableStream start controller parameter should be extensible');
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_citest(() => {
1091cb0ef41Sopenharmony_ci  (new ReadableStream()).getReader(undefined);
1101cb0ef41Sopenharmony_ci  (new ReadableStream()).getReader({});
1111cb0ef41Sopenharmony_ci  (new ReadableStream()).getReader({ mode: undefined, notmode: 'ignored' });
1121cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => (new ReadableStream()).getReader({ mode: 'potato' }));
1131cb0ef41Sopenharmony_ci}, 'default ReadableStream getReader() should only accept mode:undefined');
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_cipromise_test(() => {
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  function SimpleStreamSource() {}
1181cb0ef41Sopenharmony_ci  let resolve;
1191cb0ef41Sopenharmony_ci  const promise = new Promise(r => resolve = r);
1201cb0ef41Sopenharmony_ci  SimpleStreamSource.prototype = {
1211cb0ef41Sopenharmony_ci    start: resolve
1221cb0ef41Sopenharmony_ci  };
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  new ReadableStream(new SimpleStreamSource());
1251cb0ef41Sopenharmony_ci  return promise;
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci}, 'ReadableStream should be able to call start method within prototype chain of its source');
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_cipromise_test(() => {
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
1321cb0ef41Sopenharmony_ci    start(c) {
1331cb0ef41Sopenharmony_ci      return delay(5).then(() => {
1341cb0ef41Sopenharmony_ci        c.enqueue('a');
1351cb0ef41Sopenharmony_ci        c.close();
1361cb0ef41Sopenharmony_ci      });
1371cb0ef41Sopenharmony_ci    }
1381cb0ef41Sopenharmony_ci  });
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  const reader = rs.getReader();
1411cb0ef41Sopenharmony_ci  return reader.read().then(r => {
1421cb0ef41Sopenharmony_ci    assert_object_equals(r, { value: 'a', done: false }, 'value read should be the one enqueued');
1431cb0ef41Sopenharmony_ci    return reader.closed;
1441cb0ef41Sopenharmony_ci  });
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci}, 'ReadableStream start should be able to return a promise');
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_cipromise_test(() => {
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  const theError = new Error('rejected!');
1511cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
1521cb0ef41Sopenharmony_ci    start() {
1531cb0ef41Sopenharmony_ci      return delay(1).then(() => {
1541cb0ef41Sopenharmony_ci        throw theError;
1551cb0ef41Sopenharmony_ci      });
1561cb0ef41Sopenharmony_ci    }
1571cb0ef41Sopenharmony_ci  });
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  return rs.getReader().closed.then(() => {
1601cb0ef41Sopenharmony_ci    assert_unreached('closed promise should be rejected');
1611cb0ef41Sopenharmony_ci  }, e => {
1621cb0ef41Sopenharmony_ci    assert_equals(e, theError, 'promise should be rejected with the same error');
1631cb0ef41Sopenharmony_ci  });
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci}, 'ReadableStream start should be able to return a promise and reject it');
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_cipromise_test(() => {
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  const objects = [
1701cb0ef41Sopenharmony_ci    { potato: 'Give me more!' },
1711cb0ef41Sopenharmony_ci    'test',
1721cb0ef41Sopenharmony_ci    1
1731cb0ef41Sopenharmony_ci  ];
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
1761cb0ef41Sopenharmony_ci    start(c) {
1771cb0ef41Sopenharmony_ci      for (const o of objects) {
1781cb0ef41Sopenharmony_ci        c.enqueue(o);
1791cb0ef41Sopenharmony_ci      }
1801cb0ef41Sopenharmony_ci      c.close();
1811cb0ef41Sopenharmony_ci    }
1821cb0ef41Sopenharmony_ci  });
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  const reader = rs.getReader();
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci  return Promise.all([reader.read(), reader.read(), reader.read(), reader.closed]).then(r => {
1871cb0ef41Sopenharmony_ci    assert_object_equals(r[0], { value: objects[0], done: false }, 'value read should be the one enqueued');
1881cb0ef41Sopenharmony_ci    assert_object_equals(r[1], { value: objects[1], done: false }, 'value read should be the one enqueued');
1891cb0ef41Sopenharmony_ci    assert_object_equals(r[2], { value: objects[2], done: false }, 'value read should be the one enqueued');
1901cb0ef41Sopenharmony_ci  });
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci}, 'ReadableStream should be able to enqueue different objects.');
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_cipromise_test(() => {
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  const error = new Error('pull failure');
1971cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
1981cb0ef41Sopenharmony_ci    pull() {
1991cb0ef41Sopenharmony_ci      return Promise.reject(error);
2001cb0ef41Sopenharmony_ci    }
2011cb0ef41Sopenharmony_ci  });
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci  const reader = rs.getReader();
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  let closed = false;
2061cb0ef41Sopenharmony_ci  let read = false;
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  return Promise.all([
2091cb0ef41Sopenharmony_ci    reader.closed.then(() => {
2101cb0ef41Sopenharmony_ci      assert_unreached('closed should be rejected');
2111cb0ef41Sopenharmony_ci    }, e => {
2121cb0ef41Sopenharmony_ci      closed = true;
2131cb0ef41Sopenharmony_ci      assert_false(read);
2141cb0ef41Sopenharmony_ci      assert_equals(e, error, 'closed should be rejected with the thrown error');
2151cb0ef41Sopenharmony_ci    }),
2161cb0ef41Sopenharmony_ci    reader.read().then(() => {
2171cb0ef41Sopenharmony_ci      assert_unreached('read() should be rejected');
2181cb0ef41Sopenharmony_ci    }, e => {
2191cb0ef41Sopenharmony_ci      read = true;
2201cb0ef41Sopenharmony_ci      assert_true(closed);
2211cb0ef41Sopenharmony_ci      assert_equals(e, error, 'read() should be rejected with the thrown error');
2221cb0ef41Sopenharmony_ci    })
2231cb0ef41Sopenharmony_ci  ]);
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci}, 'ReadableStream: if pull rejects, it should error the stream');
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_cipromise_test(() => {
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  let pullCount = 0;
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci  new ReadableStream({
2321cb0ef41Sopenharmony_ci    pull() {
2331cb0ef41Sopenharmony_ci      pullCount++;
2341cb0ef41Sopenharmony_ci    }
2351cb0ef41Sopenharmony_ci  });
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
2381cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should be called once start finishes');
2391cb0ef41Sopenharmony_ci    return delay(10);
2401cb0ef41Sopenharmony_ci  }).then(() => {
2411cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should be called exactly once');
2421cb0ef41Sopenharmony_ci  });
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci}, 'ReadableStream: should only call pull once upon starting the stream');
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_cipromise_test(() => {
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci  let pullCount = 0;
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
2511cb0ef41Sopenharmony_ci    pull(c) {
2521cb0ef41Sopenharmony_ci      // Don't enqueue immediately after start. We want the stream to be empty when we call .read() on it.
2531cb0ef41Sopenharmony_ci      if (pullCount > 0) {
2541cb0ef41Sopenharmony_ci        c.enqueue(pullCount);
2551cb0ef41Sopenharmony_ci      }
2561cb0ef41Sopenharmony_ci      ++pullCount;
2571cb0ef41Sopenharmony_ci    }
2581cb0ef41Sopenharmony_ci  });
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
2611cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should be called once start finishes');
2621cb0ef41Sopenharmony_ci  }).then(() => {
2631cb0ef41Sopenharmony_ci    const reader = rs.getReader();
2641cb0ef41Sopenharmony_ci    const read = reader.read();
2651cb0ef41Sopenharmony_ci    assert_equals(pullCount, 2, 'pull should be called when read is called');
2661cb0ef41Sopenharmony_ci    return read;
2671cb0ef41Sopenharmony_ci  }).then(result => {
2681cb0ef41Sopenharmony_ci    assert_equals(pullCount, 3, 'pull should be called again in reaction to calling read');
2691cb0ef41Sopenharmony_ci    assert_object_equals(result, { value: 1, done: false }, 'the result read should be the one enqueued');
2701cb0ef41Sopenharmony_ci  });
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci}, 'ReadableStream: should call pull when trying to read from a started, empty stream');
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_cipromise_test(() => {
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  let pullCount = 0;
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
2791cb0ef41Sopenharmony_ci    start(c) {
2801cb0ef41Sopenharmony_ci      c.enqueue('a');
2811cb0ef41Sopenharmony_ci    },
2821cb0ef41Sopenharmony_ci    pull() {
2831cb0ef41Sopenharmony_ci      pullCount++;
2841cb0ef41Sopenharmony_ci    }
2851cb0ef41Sopenharmony_ci  });
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  const read = rs.getReader().read();
2881cb0ef41Sopenharmony_ci  assert_equals(pullCount, 0, 'calling read() should not cause pull to be called yet');
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
2911cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should be called once start finishes');
2921cb0ef41Sopenharmony_ci    return read;
2931cb0ef41Sopenharmony_ci  }).then(r => {
2941cb0ef41Sopenharmony_ci    assert_object_equals(r, { value: 'a', done: false }, 'first read() should return first chunk');
2951cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should not have been called again');
2961cb0ef41Sopenharmony_ci    return delay(10);
2971cb0ef41Sopenharmony_ci  }).then(() => {
2981cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should be called exactly once');
2991cb0ef41Sopenharmony_ci  });
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci}, 'ReadableStream: should only call pull once on a non-empty stream read from before start fulfills');
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_cipromise_test(() => {
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci  let pullCount = 0;
3061cb0ef41Sopenharmony_ci  const startPromise = Promise.resolve();
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
3091cb0ef41Sopenharmony_ci    start(c) {
3101cb0ef41Sopenharmony_ci      c.enqueue('a');
3111cb0ef41Sopenharmony_ci    },
3121cb0ef41Sopenharmony_ci    pull() {
3131cb0ef41Sopenharmony_ci      pullCount++;
3141cb0ef41Sopenharmony_ci    }
3151cb0ef41Sopenharmony_ci  });
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
3181cb0ef41Sopenharmony_ci    assert_equals(pullCount, 0, 'pull should not be called once start finishes, since the queue is full');
3191cb0ef41Sopenharmony_ci
3201cb0ef41Sopenharmony_ci    const read = rs.getReader().read();
3211cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'calling read() should cause pull to be called immediately');
3221cb0ef41Sopenharmony_ci    return read;
3231cb0ef41Sopenharmony_ci  }).then(r => {
3241cb0ef41Sopenharmony_ci    assert_object_equals(r, { value: 'a', done: false }, 'first read() should return first chunk');
3251cb0ef41Sopenharmony_ci    return delay(10);
3261cb0ef41Sopenharmony_ci  }).then(() => {
3271cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should be called exactly once');
3281cb0ef41Sopenharmony_ci  });
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci}, 'ReadableStream: should only call pull once on a non-empty stream read from after start fulfills');
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_cipromise_test(() => {
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci  let pullCount = 0;
3351cb0ef41Sopenharmony_ci  let controller;
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
3381cb0ef41Sopenharmony_ci    start(c) {
3391cb0ef41Sopenharmony_ci      controller = c;
3401cb0ef41Sopenharmony_ci    },
3411cb0ef41Sopenharmony_ci    pull() {
3421cb0ef41Sopenharmony_ci      ++pullCount;
3431cb0ef41Sopenharmony_ci    }
3441cb0ef41Sopenharmony_ci  });
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci  const reader = rs.getReader();
3471cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
3481cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should have been called once by the time the stream starts');
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ci    controller.enqueue('a');
3511cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should not have been called again after enqueue');
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci    return reader.read();
3541cb0ef41Sopenharmony_ci  }).then(() => {
3551cb0ef41Sopenharmony_ci    assert_equals(pullCount, 2, 'pull should have been called again after read');
3561cb0ef41Sopenharmony_ci
3571cb0ef41Sopenharmony_ci    return delay(10);
3581cb0ef41Sopenharmony_ci  }).then(() => {
3591cb0ef41Sopenharmony_ci    assert_equals(pullCount, 2, 'pull should be called exactly twice');
3601cb0ef41Sopenharmony_ci  });
3611cb0ef41Sopenharmony_ci}, 'ReadableStream: should call pull in reaction to read()ing the last chunk, if not draining');
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_cipromise_test(() => {
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci  let pullCount = 0;
3661cb0ef41Sopenharmony_ci  let controller;
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
3691cb0ef41Sopenharmony_ci    start(c) {
3701cb0ef41Sopenharmony_ci      controller = c;
3711cb0ef41Sopenharmony_ci    },
3721cb0ef41Sopenharmony_ci    pull() {
3731cb0ef41Sopenharmony_ci      ++pullCount;
3741cb0ef41Sopenharmony_ci    }
3751cb0ef41Sopenharmony_ci  });
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci  const reader = rs.getReader();
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
3801cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should have been called once by the time the stream starts');
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci    controller.enqueue('a');
3831cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should not have been called again after enqueue');
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci    controller.close();
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci    return reader.read();
3881cb0ef41Sopenharmony_ci  }).then(() => {
3891cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should not have been called a second time after read');
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci    return delay(10);
3921cb0ef41Sopenharmony_ci  }).then(() => {
3931cb0ef41Sopenharmony_ci    assert_equals(pullCount, 1, 'pull should be called exactly once');
3941cb0ef41Sopenharmony_ci  });
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci}, 'ReadableStream: should not call pull() in reaction to read()ing the last chunk, if draining');
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_cipromise_test(() => {
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ci  let resolve;
4011cb0ef41Sopenharmony_ci  let returnedPromise;
4021cb0ef41Sopenharmony_ci  let timesCalled = 0;
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
4051cb0ef41Sopenharmony_ci    pull(c) {
4061cb0ef41Sopenharmony_ci      c.enqueue(++timesCalled);
4071cb0ef41Sopenharmony_ci      returnedPromise = new Promise(r => resolve = r);
4081cb0ef41Sopenharmony_ci      return returnedPromise;
4091cb0ef41Sopenharmony_ci    }
4101cb0ef41Sopenharmony_ci  });
4111cb0ef41Sopenharmony_ci  const reader = rs.getReader();
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_ci  return reader.read()
4141cb0ef41Sopenharmony_ci  .then(result1 => {
4151cb0ef41Sopenharmony_ci    assert_equals(timesCalled, 1,
4161cb0ef41Sopenharmony_ci      'pull should have been called once after start, but not yet have been called a second time');
4171cb0ef41Sopenharmony_ci    assert_object_equals(result1, { value: 1, done: false }, 'read() should fulfill with the enqueued value');
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci    return delay(10);
4201cb0ef41Sopenharmony_ci  }).then(() => {
4211cb0ef41Sopenharmony_ci    assert_equals(timesCalled, 1, 'after 10 ms, pull should still only have been called once');
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci    resolve();
4241cb0ef41Sopenharmony_ci    return returnedPromise;
4251cb0ef41Sopenharmony_ci  }).then(() => {
4261cb0ef41Sopenharmony_ci    assert_equals(timesCalled, 2,
4271cb0ef41Sopenharmony_ci      'after the promise returned by pull is fulfilled, pull should be called a second time');
4281cb0ef41Sopenharmony_ci  });
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci}, 'ReadableStream: should not call pull until the previous pull call\'s promise fulfills');
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_cipromise_test(() => {
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci  let timesCalled = 0;
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci  const rs = new ReadableStream(
4371cb0ef41Sopenharmony_ci    {
4381cb0ef41Sopenharmony_ci      start(c) {
4391cb0ef41Sopenharmony_ci        c.enqueue('a');
4401cb0ef41Sopenharmony_ci        c.enqueue('b');
4411cb0ef41Sopenharmony_ci        c.enqueue('c');
4421cb0ef41Sopenharmony_ci      },
4431cb0ef41Sopenharmony_ci      pull() {
4441cb0ef41Sopenharmony_ci        ++timesCalled;
4451cb0ef41Sopenharmony_ci      }
4461cb0ef41Sopenharmony_ci    },
4471cb0ef41Sopenharmony_ci    {
4481cb0ef41Sopenharmony_ci      size() {
4491cb0ef41Sopenharmony_ci        return 1;
4501cb0ef41Sopenharmony_ci      },
4511cb0ef41Sopenharmony_ci      highWaterMark: Infinity
4521cb0ef41Sopenharmony_ci    }
4531cb0ef41Sopenharmony_ci  );
4541cb0ef41Sopenharmony_ci  const reader = rs.getReader();
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
4571cb0ef41Sopenharmony_ci    return reader.read();
4581cb0ef41Sopenharmony_ci  }).then(result1 => {
4591cb0ef41Sopenharmony_ci    assert_object_equals(result1, { value: 'a', done: false }, 'first chunk should be as expected');
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci    return reader.read();
4621cb0ef41Sopenharmony_ci  }).then(result2 => {
4631cb0ef41Sopenharmony_ci    assert_object_equals(result2, { value: 'b', done: false }, 'second chunk should be as expected');
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci    return reader.read();
4661cb0ef41Sopenharmony_ci  }).then(result3 => {
4671cb0ef41Sopenharmony_ci    assert_object_equals(result3, { value: 'c', done: false }, 'third chunk should be as expected');
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ci    return delay(10);
4701cb0ef41Sopenharmony_ci  }).then(() => {
4711cb0ef41Sopenharmony_ci    // Once for after start, and once for every read.
4721cb0ef41Sopenharmony_ci    assert_equals(timesCalled, 4, 'pull() should be called exactly four times');
4731cb0ef41Sopenharmony_ci  });
4741cb0ef41Sopenharmony_ci
4751cb0ef41Sopenharmony_ci}, 'ReadableStream: should pull after start, and after every read');
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_cipromise_test(() => {
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci  let timesCalled = 0;
4801cb0ef41Sopenharmony_ci  const startPromise = Promise.resolve();
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
4831cb0ef41Sopenharmony_ci    start(c) {
4841cb0ef41Sopenharmony_ci      c.enqueue('a');
4851cb0ef41Sopenharmony_ci      c.close();
4861cb0ef41Sopenharmony_ci      return startPromise;
4871cb0ef41Sopenharmony_ci    },
4881cb0ef41Sopenharmony_ci    pull() {
4891cb0ef41Sopenharmony_ci      ++timesCalled;
4901cb0ef41Sopenharmony_ci    }
4911cb0ef41Sopenharmony_ci  });
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ci  const reader = rs.getReader();
4941cb0ef41Sopenharmony_ci  return startPromise.then(() => {
4951cb0ef41Sopenharmony_ci    assert_equals(timesCalled, 0, 'after start finishes, pull should not have been called');
4961cb0ef41Sopenharmony_ci
4971cb0ef41Sopenharmony_ci    return reader.read();
4981cb0ef41Sopenharmony_ci  }).then(() => {
4991cb0ef41Sopenharmony_ci    assert_equals(timesCalled, 0, 'reading should not have triggered a pull call');
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci    return reader.closed;
5021cb0ef41Sopenharmony_ci  }).then(() => {
5031cb0ef41Sopenharmony_ci    assert_equals(timesCalled, 0, 'stream should have closed with still no calls to pull');
5041cb0ef41Sopenharmony_ci  });
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci}, 'ReadableStream: should not call pull after start if the stream is now closed');
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_cipromise_test(() => {
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_ci  let timesCalled = 0;
5111cb0ef41Sopenharmony_ci  let resolve;
5121cb0ef41Sopenharmony_ci  const ready = new Promise(r => resolve = r);
5131cb0ef41Sopenharmony_ci
5141cb0ef41Sopenharmony_ci  new ReadableStream(
5151cb0ef41Sopenharmony_ci    {
5161cb0ef41Sopenharmony_ci      start() {},
5171cb0ef41Sopenharmony_ci      pull(c) {
5181cb0ef41Sopenharmony_ci        c.enqueue(++timesCalled);
5191cb0ef41Sopenharmony_ci
5201cb0ef41Sopenharmony_ci        if (timesCalled === 4) {
5211cb0ef41Sopenharmony_ci          resolve();
5221cb0ef41Sopenharmony_ci        }
5231cb0ef41Sopenharmony_ci      }
5241cb0ef41Sopenharmony_ci    },
5251cb0ef41Sopenharmony_ci    {
5261cb0ef41Sopenharmony_ci      size() {
5271cb0ef41Sopenharmony_ci        return 1;
5281cb0ef41Sopenharmony_ci      },
5291cb0ef41Sopenharmony_ci      highWaterMark: 4
5301cb0ef41Sopenharmony_ci    }
5311cb0ef41Sopenharmony_ci  );
5321cb0ef41Sopenharmony_ci
5331cb0ef41Sopenharmony_ci  return ready.then(() => {
5341cb0ef41Sopenharmony_ci    // after start: size = 0, pull()
5351cb0ef41Sopenharmony_ci    // after enqueue(1): size = 1, pull()
5361cb0ef41Sopenharmony_ci    // after enqueue(2): size = 2, pull()
5371cb0ef41Sopenharmony_ci    // after enqueue(3): size = 3, pull()
5381cb0ef41Sopenharmony_ci    // after enqueue(4): size = 4, do not pull
5391cb0ef41Sopenharmony_ci    assert_equals(timesCalled, 4, 'pull() should have been called four times');
5401cb0ef41Sopenharmony_ci  });
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci}, 'ReadableStream: should call pull after enqueueing from inside pull (with no read requests), if strategy allows');
5431cb0ef41Sopenharmony_ci
5441cb0ef41Sopenharmony_cipromise_test(() => {
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_ci  let pullCalled = false;
5471cb0ef41Sopenharmony_ci
5481cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
5491cb0ef41Sopenharmony_ci    pull(c) {
5501cb0ef41Sopenharmony_ci      pullCalled = true;
5511cb0ef41Sopenharmony_ci      c.close();
5521cb0ef41Sopenharmony_ci    }
5531cb0ef41Sopenharmony_ci  });
5541cb0ef41Sopenharmony_ci
5551cb0ef41Sopenharmony_ci  const reader = rs.getReader();
5561cb0ef41Sopenharmony_ci  return reader.closed.then(() => {
5571cb0ef41Sopenharmony_ci    assert_true(pullCalled);
5581cb0ef41Sopenharmony_ci  });
5591cb0ef41Sopenharmony_ci
5601cb0ef41Sopenharmony_ci}, 'ReadableStream pull should be able to close a stream.');
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_cipromise_test(t => {
5631cb0ef41Sopenharmony_ci
5641cb0ef41Sopenharmony_ci  const controllerError = { name: 'controller error' };
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
5671cb0ef41Sopenharmony_ci    pull(c) {
5681cb0ef41Sopenharmony_ci      c.error(controllerError);
5691cb0ef41Sopenharmony_ci    }
5701cb0ef41Sopenharmony_ci  });
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_ci  return promise_rejects_exactly(t, controllerError, rs.getReader().closed);
5731cb0ef41Sopenharmony_ci
5741cb0ef41Sopenharmony_ci}, 'ReadableStream pull should be able to error a stream.');
5751cb0ef41Sopenharmony_ci
5761cb0ef41Sopenharmony_cipromise_test(t => {
5771cb0ef41Sopenharmony_ci
5781cb0ef41Sopenharmony_ci  const controllerError = { name: 'controller error' };
5791cb0ef41Sopenharmony_ci  const thrownError = { name: 'thrown error' };
5801cb0ef41Sopenharmony_ci
5811cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
5821cb0ef41Sopenharmony_ci    pull(c) {
5831cb0ef41Sopenharmony_ci      c.error(controllerError);
5841cb0ef41Sopenharmony_ci      throw thrownError;
5851cb0ef41Sopenharmony_ci    }
5861cb0ef41Sopenharmony_ci  });
5871cb0ef41Sopenharmony_ci
5881cb0ef41Sopenharmony_ci  return promise_rejects_exactly(t, controllerError, rs.getReader().closed);
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci}, 'ReadableStream pull should be able to error a stream and throw.');
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_citest(() => {
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ci  let startCalled = false;
5951cb0ef41Sopenharmony_ci
5961cb0ef41Sopenharmony_ci  new ReadableStream({
5971cb0ef41Sopenharmony_ci    start(c) {
5981cb0ef41Sopenharmony_ci      assert_equals(c.enqueue('a'), undefined, 'the first enqueue should return undefined');
5991cb0ef41Sopenharmony_ci      c.close();
6001cb0ef41Sopenharmony_ci
6011cb0ef41Sopenharmony_ci      assert_throws_js(TypeError, () => c.enqueue('b'), 'enqueue after close should throw a TypeError');
6021cb0ef41Sopenharmony_ci      startCalled = true;
6031cb0ef41Sopenharmony_ci    }
6041cb0ef41Sopenharmony_ci  });
6051cb0ef41Sopenharmony_ci
6061cb0ef41Sopenharmony_ci  assert_true(startCalled);
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_ci}, 'ReadableStream: enqueue should throw when the stream is readable but draining');
6091cb0ef41Sopenharmony_ci
6101cb0ef41Sopenharmony_citest(() => {
6111cb0ef41Sopenharmony_ci
6121cb0ef41Sopenharmony_ci  let startCalled = false;
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci  new ReadableStream({
6151cb0ef41Sopenharmony_ci    start(c) {
6161cb0ef41Sopenharmony_ci      c.close();
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_ci      assert_throws_js(TypeError, () => c.enqueue('a'), 'enqueue after close should throw a TypeError');
6191cb0ef41Sopenharmony_ci      startCalled = true;
6201cb0ef41Sopenharmony_ci    }
6211cb0ef41Sopenharmony_ci  });
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_ci  assert_true(startCalled);
6241cb0ef41Sopenharmony_ci
6251cb0ef41Sopenharmony_ci}, 'ReadableStream: enqueue should throw when the stream is closed');
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_cipromise_test(() => {
6281cb0ef41Sopenharmony_ci
6291cb0ef41Sopenharmony_ci  let startCalled = 0;
6301cb0ef41Sopenharmony_ci  let pullCalled = 0;
6311cb0ef41Sopenharmony_ci  let cancelCalled = 0;
6321cb0ef41Sopenharmony_ci
6331cb0ef41Sopenharmony_ci  /* eslint-disable no-use-before-define */
6341cb0ef41Sopenharmony_ci  class Source {
6351cb0ef41Sopenharmony_ci    start(c) {
6361cb0ef41Sopenharmony_ci      startCalled++;
6371cb0ef41Sopenharmony_ci      assert_equals(this, theSource, 'start() should be called with the correct this');
6381cb0ef41Sopenharmony_ci      c.enqueue('a');
6391cb0ef41Sopenharmony_ci    }
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ci    pull() {
6421cb0ef41Sopenharmony_ci      pullCalled++;
6431cb0ef41Sopenharmony_ci      assert_equals(this, theSource, 'pull() should be called with the correct this');
6441cb0ef41Sopenharmony_ci    }
6451cb0ef41Sopenharmony_ci
6461cb0ef41Sopenharmony_ci    cancel() {
6471cb0ef41Sopenharmony_ci      cancelCalled++;
6481cb0ef41Sopenharmony_ci      assert_equals(this, theSource, 'cancel() should be called with the correct this');
6491cb0ef41Sopenharmony_ci    }
6501cb0ef41Sopenharmony_ci  }
6511cb0ef41Sopenharmony_ci  /* eslint-enable no-use-before-define */
6521cb0ef41Sopenharmony_ci
6531cb0ef41Sopenharmony_ci  const theSource = new Source();
6541cb0ef41Sopenharmony_ci  theSource.debugName = 'the source object passed to the constructor'; // makes test failures easier to diagnose
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ci  const rs = new ReadableStream(theSource);
6571cb0ef41Sopenharmony_ci  const reader = rs.getReader();
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_ci  return reader.read().then(() => {
6601cb0ef41Sopenharmony_ci    reader.releaseLock();
6611cb0ef41Sopenharmony_ci    rs.cancel();
6621cb0ef41Sopenharmony_ci    assert_equals(startCalled, 1);
6631cb0ef41Sopenharmony_ci    assert_equals(pullCalled, 1);
6641cb0ef41Sopenharmony_ci    assert_equals(cancelCalled, 1);
6651cb0ef41Sopenharmony_ci    return rs.getReader().closed;
6661cb0ef41Sopenharmony_ci  });
6671cb0ef41Sopenharmony_ci
6681cb0ef41Sopenharmony_ci}, 'ReadableStream: should call underlying source methods as methods');
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_citest(() => {
6711cb0ef41Sopenharmony_ci  new ReadableStream({
6721cb0ef41Sopenharmony_ci    start(c) {
6731cb0ef41Sopenharmony_ci      assert_equals(c.desiredSize, 10, 'desiredSize must start at highWaterMark');
6741cb0ef41Sopenharmony_ci      c.close();
6751cb0ef41Sopenharmony_ci      assert_equals(c.desiredSize, 0, 'after closing, desiredSize must be 0');
6761cb0ef41Sopenharmony_ci    }
6771cb0ef41Sopenharmony_ci  }, {
6781cb0ef41Sopenharmony_ci    highWaterMark: 10
6791cb0ef41Sopenharmony_ci  });
6801cb0ef41Sopenharmony_ci}, 'ReadableStream: desiredSize when closed');
6811cb0ef41Sopenharmony_ci
6821cb0ef41Sopenharmony_citest(() => {
6831cb0ef41Sopenharmony_ci  new ReadableStream({
6841cb0ef41Sopenharmony_ci    start(c) {
6851cb0ef41Sopenharmony_ci      assert_equals(c.desiredSize, 10, 'desiredSize must start at highWaterMark');
6861cb0ef41Sopenharmony_ci      c.error();
6871cb0ef41Sopenharmony_ci      assert_equals(c.desiredSize, null, 'after erroring, desiredSize must be null');
6881cb0ef41Sopenharmony_ci    }
6891cb0ef41Sopenharmony_ci  }, {
6901cb0ef41Sopenharmony_ci    highWaterMark: 10
6911cb0ef41Sopenharmony_ci  });
6921cb0ef41Sopenharmony_ci}, 'ReadableStream: desiredSize when errored');
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_citest(() => {
6951cb0ef41Sopenharmony_ci  class Subclass extends ReadableStream {
6961cb0ef41Sopenharmony_ci    extraFunction() {
6971cb0ef41Sopenharmony_ci      return true;
6981cb0ef41Sopenharmony_ci    }
6991cb0ef41Sopenharmony_ci  }
7001cb0ef41Sopenharmony_ci  assert_equals(
7011cb0ef41Sopenharmony_ci      Object.getPrototypeOf(Subclass.prototype), ReadableStream.prototype,
7021cb0ef41Sopenharmony_ci      'Subclass.prototype\'s prototype should be ReadableStream.prototype');
7031cb0ef41Sopenharmony_ci  assert_equals(Object.getPrototypeOf(Subclass), ReadableStream,
7041cb0ef41Sopenharmony_ci                'Subclass\'s prototype should be ReadableStream');
7051cb0ef41Sopenharmony_ci  const sub = new Subclass();
7061cb0ef41Sopenharmony_ci  assert_true(sub instanceof ReadableStream,
7071cb0ef41Sopenharmony_ci              'Subclass object should be an instance of ReadableStream');
7081cb0ef41Sopenharmony_ci  assert_true(sub instanceof Subclass,
7091cb0ef41Sopenharmony_ci              'Subclass object should be an instance of Subclass');
7101cb0ef41Sopenharmony_ci  const lockedGetter = Object.getOwnPropertyDescriptor(
7111cb0ef41Sopenharmony_ci      ReadableStream.prototype, 'locked').get;
7121cb0ef41Sopenharmony_ci  assert_equals(lockedGetter.call(sub), sub.locked,
7131cb0ef41Sopenharmony_ci                'Subclass object should pass brand check');
7141cb0ef41Sopenharmony_ci  assert_true(sub.extraFunction(),
7151cb0ef41Sopenharmony_ci              'extraFunction() should be present on Subclass object');
7161cb0ef41Sopenharmony_ci}, 'Subclassing ReadableStream should work');
7171cb0ef41Sopenharmony_ci
7181cb0ef41Sopenharmony_citest(() => {
7191cb0ef41Sopenharmony_ci
7201cb0ef41Sopenharmony_ci  let startCalled = false;
7211cb0ef41Sopenharmony_ci  new ReadableStream({
7221cb0ef41Sopenharmony_ci    start(c) {
7231cb0ef41Sopenharmony_ci      assert_equals(c.desiredSize, 1);
7241cb0ef41Sopenharmony_ci      c.enqueue('a');
7251cb0ef41Sopenharmony_ci      assert_equals(c.desiredSize, 0);
7261cb0ef41Sopenharmony_ci      c.enqueue('b');
7271cb0ef41Sopenharmony_ci      assert_equals(c.desiredSize, -1);
7281cb0ef41Sopenharmony_ci      c.enqueue('c');
7291cb0ef41Sopenharmony_ci      assert_equals(c.desiredSize, -2);
7301cb0ef41Sopenharmony_ci      c.enqueue('d');
7311cb0ef41Sopenharmony_ci      assert_equals(c.desiredSize, -3);
7321cb0ef41Sopenharmony_ci      c.enqueue('e');
7331cb0ef41Sopenharmony_ci      startCalled = true;
7341cb0ef41Sopenharmony_ci    }
7351cb0ef41Sopenharmony_ci  });
7361cb0ef41Sopenharmony_ci
7371cb0ef41Sopenharmony_ci  assert_true(startCalled);
7381cb0ef41Sopenharmony_ci
7391cb0ef41Sopenharmony_ci}, 'ReadableStream strategies: the default strategy should give desiredSize of 1 to start, decreasing by 1 per enqueue');
7401cb0ef41Sopenharmony_ci
7411cb0ef41Sopenharmony_cipromise_test(() => {
7421cb0ef41Sopenharmony_ci
7431cb0ef41Sopenharmony_ci  let controller;
7441cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
7451cb0ef41Sopenharmony_ci    start(c) {
7461cb0ef41Sopenharmony_ci      controller = c;
7471cb0ef41Sopenharmony_ci    }
7481cb0ef41Sopenharmony_ci  });
7491cb0ef41Sopenharmony_ci  const reader = rs.getReader();
7501cb0ef41Sopenharmony_ci
7511cb0ef41Sopenharmony_ci  assert_equals(controller.desiredSize, 1, 'desiredSize should start at 1');
7521cb0ef41Sopenharmony_ci  controller.enqueue('a');
7531cb0ef41Sopenharmony_ci  assert_equals(controller.desiredSize, 0, 'desiredSize should decrease to 0 after first enqueue');
7541cb0ef41Sopenharmony_ci
7551cb0ef41Sopenharmony_ci  return reader.read().then(result1 => {
7561cb0ef41Sopenharmony_ci    assert_object_equals(result1, { value: 'a', done: false }, 'first chunk read should be correct');
7571cb0ef41Sopenharmony_ci
7581cb0ef41Sopenharmony_ci    assert_equals(controller.desiredSize, 1, 'desiredSize should go up to 1 after the first read');
7591cb0ef41Sopenharmony_ci    controller.enqueue('b');
7601cb0ef41Sopenharmony_ci    assert_equals(controller.desiredSize, 0, 'desiredSize should go down to 0 after the second enqueue');
7611cb0ef41Sopenharmony_ci
7621cb0ef41Sopenharmony_ci    return reader.read();
7631cb0ef41Sopenharmony_ci  }).then(result2 => {
7641cb0ef41Sopenharmony_ci    assert_object_equals(result2, { value: 'b', done: false }, 'second chunk read should be correct');
7651cb0ef41Sopenharmony_ci
7661cb0ef41Sopenharmony_ci    assert_equals(controller.desiredSize, 1, 'desiredSize should go up to 1 after the second read');
7671cb0ef41Sopenharmony_ci    controller.enqueue('c');
7681cb0ef41Sopenharmony_ci    assert_equals(controller.desiredSize, 0, 'desiredSize should go down to 0 after the third enqueue');
7691cb0ef41Sopenharmony_ci
7701cb0ef41Sopenharmony_ci    return reader.read();
7711cb0ef41Sopenharmony_ci  }).then(result3 => {
7721cb0ef41Sopenharmony_ci    assert_object_equals(result3, { value: 'c', done: false }, 'third chunk read should be correct');
7731cb0ef41Sopenharmony_ci
7741cb0ef41Sopenharmony_ci    assert_equals(controller.desiredSize, 1, 'desiredSize should go up to 1 after the third read');
7751cb0ef41Sopenharmony_ci    controller.enqueue('d');
7761cb0ef41Sopenharmony_ci    assert_equals(controller.desiredSize, 0, 'desiredSize should go down to 0 after the fourth enqueue');
7771cb0ef41Sopenharmony_ci  });
7781cb0ef41Sopenharmony_ci
7791cb0ef41Sopenharmony_ci}, 'ReadableStream strategies: the default strategy should continue giving desiredSize of 1 if the chunks are read immediately');
7801cb0ef41Sopenharmony_ci
7811cb0ef41Sopenharmony_cipromise_test(t => {
7821cb0ef41Sopenharmony_ci
7831cb0ef41Sopenharmony_ci  const randomSource = new RandomPushSource(8);
7841cb0ef41Sopenharmony_ci
7851cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
7861cb0ef41Sopenharmony_ci    start(c) {
7871cb0ef41Sopenharmony_ci      assert_equals(typeof c, 'object', 'c should be an object in start');
7881cb0ef41Sopenharmony_ci      assert_equals(typeof c.enqueue, 'function', 'enqueue should be a function in start');
7891cb0ef41Sopenharmony_ci      assert_equals(typeof c.close, 'function', 'close should be a function in start');
7901cb0ef41Sopenharmony_ci      assert_equals(typeof c.error, 'function', 'error should be a function in start');
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_ci      randomSource.ondata = t.step_func(chunk => {
7931cb0ef41Sopenharmony_ci        if (!c.enqueue(chunk) <= 0) {
7941cb0ef41Sopenharmony_ci          randomSource.readStop();
7951cb0ef41Sopenharmony_ci        }
7961cb0ef41Sopenharmony_ci      });
7971cb0ef41Sopenharmony_ci
7981cb0ef41Sopenharmony_ci      randomSource.onend = c.close.bind(c);
7991cb0ef41Sopenharmony_ci      randomSource.onerror = c.error.bind(c);
8001cb0ef41Sopenharmony_ci    },
8011cb0ef41Sopenharmony_ci
8021cb0ef41Sopenharmony_ci    pull(c) {
8031cb0ef41Sopenharmony_ci      assert_equals(typeof c, 'object', 'c should be an object in pull');
8041cb0ef41Sopenharmony_ci      assert_equals(typeof c.enqueue, 'function', 'enqueue should be a function in pull');
8051cb0ef41Sopenharmony_ci      assert_equals(typeof c.close, 'function', 'close should be a function in pull');
8061cb0ef41Sopenharmony_ci
8071cb0ef41Sopenharmony_ci      randomSource.readStart();
8081cb0ef41Sopenharmony_ci    }
8091cb0ef41Sopenharmony_ci  });
8101cb0ef41Sopenharmony_ci
8111cb0ef41Sopenharmony_ci  return readableStreamToArray(rs).then(chunks => {
8121cb0ef41Sopenharmony_ci    assert_equals(chunks.length, 8, '8 chunks should be read');
8131cb0ef41Sopenharmony_ci    for (const chunk of chunks) {
8141cb0ef41Sopenharmony_ci      assert_equals(chunk.length, 128, 'chunk should have 128 bytes');
8151cb0ef41Sopenharmony_ci    }
8161cb0ef41Sopenharmony_ci  });
8171cb0ef41Sopenharmony_ci
8181cb0ef41Sopenharmony_ci}, 'ReadableStream integration test: adapting a random push source');
8191cb0ef41Sopenharmony_ci
8201cb0ef41Sopenharmony_cipromise_test(() => {
8211cb0ef41Sopenharmony_ci
8221cb0ef41Sopenharmony_ci  const rs = sequentialReadableStream(10);
8231cb0ef41Sopenharmony_ci
8241cb0ef41Sopenharmony_ci  return readableStreamToArray(rs).then(chunks => {
8251cb0ef41Sopenharmony_ci    assert_true(rs.source.closed, 'source should be closed after all chunks are read');
8261cb0ef41Sopenharmony_ci    assert_array_equals(chunks, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'the expected 10 chunks should be read');
8271cb0ef41Sopenharmony_ci  });
8281cb0ef41Sopenharmony_ci
8291cb0ef41Sopenharmony_ci}, 'ReadableStream integration test: adapting a sync pull source');
8301cb0ef41Sopenharmony_ci
8311cb0ef41Sopenharmony_cipromise_test(() => {
8321cb0ef41Sopenharmony_ci
8331cb0ef41Sopenharmony_ci  const rs = sequentialReadableStream(10, { async: true });
8341cb0ef41Sopenharmony_ci
8351cb0ef41Sopenharmony_ci  return readableStreamToArray(rs).then(chunks => {
8361cb0ef41Sopenharmony_ci    assert_true(rs.source.closed, 'source should be closed after all chunks are read');
8371cb0ef41Sopenharmony_ci    assert_array_equals(chunks, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'the expected 10 chunks should be read');
8381cb0ef41Sopenharmony_ci  });
8391cb0ef41Sopenharmony_ci
8401cb0ef41Sopenharmony_ci}, 'ReadableStream integration test: adapting an async pull source');
841