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_ciconst error1 = new Error('error1');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cifunction assert_iter_result(iterResult, value, done, message) {
101cb0ef41Sopenharmony_ci  const prefix = message === undefined ? '' : `${message} `;
111cb0ef41Sopenharmony_ci  assert_equals(typeof iterResult, 'object', `${prefix}type is object`);
121cb0ef41Sopenharmony_ci  assert_equals(Object.getPrototypeOf(iterResult), Object.prototype, `${prefix}[[Prototype]]`);
131cb0ef41Sopenharmony_ci  assert_array_equals(Object.getOwnPropertyNames(iterResult).sort(), ['done', 'value'], `${prefix}property names`);
141cb0ef41Sopenharmony_ci  assert_equals(iterResult.value, value, `${prefix}value`);
151cb0ef41Sopenharmony_ci  assert_equals(iterResult.done, done, `${prefix}done`);
161cb0ef41Sopenharmony_ci}
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_citest(() => {
191cb0ef41Sopenharmony_ci  const s = new ReadableStream();
201cb0ef41Sopenharmony_ci  const it = s.values();
211cb0ef41Sopenharmony_ci  const proto = Object.getPrototypeOf(it);
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(async function* () {}).prototype);
241cb0ef41Sopenharmony_ci  assert_equals(Object.getPrototypeOf(proto), AsyncIteratorPrototype, 'prototype should extend AsyncIteratorPrototype');
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci  const methods = ['next', 'return'].sort();
271cb0ef41Sopenharmony_ci  assert_array_equals(Object.getOwnPropertyNames(proto).sort(), methods, 'should have all the correct methods');
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  for (const m of methods) {
301cb0ef41Sopenharmony_ci    const propDesc = Object.getOwnPropertyDescriptor(proto, m);
311cb0ef41Sopenharmony_ci    assert_true(propDesc.enumerable, 'method should be enumerable');
321cb0ef41Sopenharmony_ci    assert_true(propDesc.configurable, 'method should be configurable');
331cb0ef41Sopenharmony_ci    assert_true(propDesc.writable, 'method should be writable');
341cb0ef41Sopenharmony_ci    assert_equals(typeof it[m], 'function', 'method should be a function');
351cb0ef41Sopenharmony_ci    assert_equals(it[m].name, m, 'method should have the correct name');
361cb0ef41Sopenharmony_ci  }
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  assert_equals(it.next.length, 0, 'next should have no parameters');
391cb0ef41Sopenharmony_ci  assert_equals(it.return.length, 1, 'return should have 1 parameter');
401cb0ef41Sopenharmony_ci  assert_equals(typeof it.throw, 'undefined', 'throw should not exist');
411cb0ef41Sopenharmony_ci}, 'Async iterator instances should have the correct list of properties');
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_cipromise_test(async () => {
441cb0ef41Sopenharmony_ci  const s = new ReadableStream({
451cb0ef41Sopenharmony_ci    start(c) {
461cb0ef41Sopenharmony_ci      c.enqueue(1);
471cb0ef41Sopenharmony_ci      c.enqueue(2);
481cb0ef41Sopenharmony_ci      c.enqueue(3);
491cb0ef41Sopenharmony_ci      c.close();
501cb0ef41Sopenharmony_ci    }
511cb0ef41Sopenharmony_ci  });
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  const chunks = [];
541cb0ef41Sopenharmony_ci  for await (const chunk of s) {
551cb0ef41Sopenharmony_ci    chunks.push(chunk);
561cb0ef41Sopenharmony_ci  }
571cb0ef41Sopenharmony_ci  assert_array_equals(chunks, [1, 2, 3]);
581cb0ef41Sopenharmony_ci}, 'Async-iterating a push source');
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_cipromise_test(async () => {
611cb0ef41Sopenharmony_ci  let i = 1;
621cb0ef41Sopenharmony_ci  const s = new ReadableStream({
631cb0ef41Sopenharmony_ci    pull(c) {
641cb0ef41Sopenharmony_ci      c.enqueue(i);
651cb0ef41Sopenharmony_ci      if (i >= 3) {
661cb0ef41Sopenharmony_ci        c.close();
671cb0ef41Sopenharmony_ci      }
681cb0ef41Sopenharmony_ci      i += 1;
691cb0ef41Sopenharmony_ci    }
701cb0ef41Sopenharmony_ci  });
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  const chunks = [];
731cb0ef41Sopenharmony_ci  for await (const chunk of s) {
741cb0ef41Sopenharmony_ci    chunks.push(chunk);
751cb0ef41Sopenharmony_ci  }
761cb0ef41Sopenharmony_ci  assert_array_equals(chunks, [1, 2, 3]);
771cb0ef41Sopenharmony_ci}, 'Async-iterating a pull source');
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_cipromise_test(async () => {
801cb0ef41Sopenharmony_ci  const s = new ReadableStream({
811cb0ef41Sopenharmony_ci    start(c) {
821cb0ef41Sopenharmony_ci      c.enqueue(undefined);
831cb0ef41Sopenharmony_ci      c.enqueue(undefined);
841cb0ef41Sopenharmony_ci      c.enqueue(undefined);
851cb0ef41Sopenharmony_ci      c.close();
861cb0ef41Sopenharmony_ci    }
871cb0ef41Sopenharmony_ci  });
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  const chunks = [];
901cb0ef41Sopenharmony_ci  for await (const chunk of s) {
911cb0ef41Sopenharmony_ci    chunks.push(chunk);
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci  assert_array_equals(chunks, [undefined, undefined, undefined]);
941cb0ef41Sopenharmony_ci}, 'Async-iterating a push source with undefined values');
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_cipromise_test(async () => {
971cb0ef41Sopenharmony_ci  let i = 1;
981cb0ef41Sopenharmony_ci  const s = new ReadableStream({
991cb0ef41Sopenharmony_ci    pull(c) {
1001cb0ef41Sopenharmony_ci      c.enqueue(undefined);
1011cb0ef41Sopenharmony_ci      if (i >= 3) {
1021cb0ef41Sopenharmony_ci        c.close();
1031cb0ef41Sopenharmony_ci      }
1041cb0ef41Sopenharmony_ci      i += 1;
1051cb0ef41Sopenharmony_ci    }
1061cb0ef41Sopenharmony_ci  });
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  const chunks = [];
1091cb0ef41Sopenharmony_ci  for await (const chunk of s) {
1101cb0ef41Sopenharmony_ci    chunks.push(chunk);
1111cb0ef41Sopenharmony_ci  }
1121cb0ef41Sopenharmony_ci  assert_array_equals(chunks, [undefined, undefined, undefined]);
1131cb0ef41Sopenharmony_ci}, 'Async-iterating a pull source with undefined values');
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_cipromise_test(async () => {
1161cb0ef41Sopenharmony_ci  let i = 1;
1171cb0ef41Sopenharmony_ci  const s = recordingReadableStream({
1181cb0ef41Sopenharmony_ci    pull(c) {
1191cb0ef41Sopenharmony_ci      c.enqueue(i);
1201cb0ef41Sopenharmony_ci      if (i >= 3) {
1211cb0ef41Sopenharmony_ci        c.close();
1221cb0ef41Sopenharmony_ci      }
1231cb0ef41Sopenharmony_ci      i += 1;
1241cb0ef41Sopenharmony_ci    },
1251cb0ef41Sopenharmony_ci  }, new CountQueuingStrategy({ highWaterMark: 0 }));
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  const it = s.values();
1281cb0ef41Sopenharmony_ci  assert_array_equals(s.events, []);
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci  const read1 = await it.next();
1311cb0ef41Sopenharmony_ci  assert_iter_result(read1, 1, false);
1321cb0ef41Sopenharmony_ci  assert_array_equals(s.events, ['pull']);
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci  const read2 = await it.next();
1351cb0ef41Sopenharmony_ci  assert_iter_result(read2, 2, false);
1361cb0ef41Sopenharmony_ci  assert_array_equals(s.events, ['pull', 'pull']);
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  const read3 = await it.next();
1391cb0ef41Sopenharmony_ci  assert_iter_result(read3, 3, false);
1401cb0ef41Sopenharmony_ci  assert_array_equals(s.events, ['pull', 'pull', 'pull']);
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  const read4 = await it.next();
1431cb0ef41Sopenharmony_ci  assert_iter_result(read4, undefined, true);
1441cb0ef41Sopenharmony_ci  assert_array_equals(s.events, ['pull', 'pull', 'pull']);
1451cb0ef41Sopenharmony_ci}, 'Async-iterating a pull source manually');
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_cipromise_test(async () => {
1481cb0ef41Sopenharmony_ci  const s = new ReadableStream({
1491cb0ef41Sopenharmony_ci    start(c) {
1501cb0ef41Sopenharmony_ci      c.error('e');
1511cb0ef41Sopenharmony_ci    },
1521cb0ef41Sopenharmony_ci  });
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  try {
1551cb0ef41Sopenharmony_ci    for await (const chunk of s) {}
1561cb0ef41Sopenharmony_ci    assert_unreached();
1571cb0ef41Sopenharmony_ci  } catch (e) {
1581cb0ef41Sopenharmony_ci    assert_equals(e, 'e');
1591cb0ef41Sopenharmony_ci  }
1601cb0ef41Sopenharmony_ci}, 'Async-iterating an errored stream throws');
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_cipromise_test(async () => {
1631cb0ef41Sopenharmony_ci  const s = new ReadableStream({
1641cb0ef41Sopenharmony_ci    start(c) {
1651cb0ef41Sopenharmony_ci      c.close();
1661cb0ef41Sopenharmony_ci    }
1671cb0ef41Sopenharmony_ci  });
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  for await (const chunk of s) {
1701cb0ef41Sopenharmony_ci    assert_unreached();
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci}, 'Async-iterating a closed stream never executes the loop body, but works fine');
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_cipromise_test(async () => {
1751cb0ef41Sopenharmony_ci  const s = new ReadableStream();
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  const loop = async () => {
1781cb0ef41Sopenharmony_ci    for await (const chunk of s) {
1791cb0ef41Sopenharmony_ci      assert_unreached();
1801cb0ef41Sopenharmony_ci    }
1811cb0ef41Sopenharmony_ci    assert_unreached();
1821cb0ef41Sopenharmony_ci  };
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  await Promise.race([
1851cb0ef41Sopenharmony_ci    loop(),
1861cb0ef41Sopenharmony_ci    flushAsyncEvents()
1871cb0ef41Sopenharmony_ci  ]);
1881cb0ef41Sopenharmony_ci}, 'Async-iterating an empty but not closed/errored stream never executes the loop body and stalls the async function');
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_cipromise_test(async () => {
1911cb0ef41Sopenharmony_ci  const s = new ReadableStream({
1921cb0ef41Sopenharmony_ci    start(c) {
1931cb0ef41Sopenharmony_ci      c.enqueue(1);
1941cb0ef41Sopenharmony_ci      c.enqueue(2);
1951cb0ef41Sopenharmony_ci      c.enqueue(3);
1961cb0ef41Sopenharmony_ci      c.close();
1971cb0ef41Sopenharmony_ci    },
1981cb0ef41Sopenharmony_ci  });
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  const reader = s.getReader();
2011cb0ef41Sopenharmony_ci  const readResult = await reader.read();
2021cb0ef41Sopenharmony_ci  assert_iter_result(readResult, 1, false);
2031cb0ef41Sopenharmony_ci  reader.releaseLock();
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  const chunks = [];
2061cb0ef41Sopenharmony_ci  for await (const chunk of s) {
2071cb0ef41Sopenharmony_ci    chunks.push(chunk);
2081cb0ef41Sopenharmony_ci  }
2091cb0ef41Sopenharmony_ci  assert_array_equals(chunks, [2, 3]);
2101cb0ef41Sopenharmony_ci}, 'Async-iterating a partially consumed stream');
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_cifor (const type of ['throw', 'break', 'return']) {
2131cb0ef41Sopenharmony_ci  for (const preventCancel of [false, true]) {
2141cb0ef41Sopenharmony_ci    promise_test(async () => {
2151cb0ef41Sopenharmony_ci      const s = recordingReadableStream({
2161cb0ef41Sopenharmony_ci        start(c) {
2171cb0ef41Sopenharmony_ci          c.enqueue(0);
2181cb0ef41Sopenharmony_ci        }
2191cb0ef41Sopenharmony_ci      });
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci      // use a separate function for the loop body so return does not stop the test
2221cb0ef41Sopenharmony_ci      const loop = async () => {
2231cb0ef41Sopenharmony_ci        for await (const c of s.values({ preventCancel })) {
2241cb0ef41Sopenharmony_ci          if (type === 'throw') {
2251cb0ef41Sopenharmony_ci            throw new Error();
2261cb0ef41Sopenharmony_ci          } else if (type === 'break') {
2271cb0ef41Sopenharmony_ci            break;
2281cb0ef41Sopenharmony_ci          } else if (type === 'return') {
2291cb0ef41Sopenharmony_ci            return;
2301cb0ef41Sopenharmony_ci          }
2311cb0ef41Sopenharmony_ci        }
2321cb0ef41Sopenharmony_ci      };
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci      try {
2351cb0ef41Sopenharmony_ci        await loop();
2361cb0ef41Sopenharmony_ci      } catch (e) {}
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci      if (preventCancel) {
2391cb0ef41Sopenharmony_ci        assert_array_equals(s.events, ['pull'], `cancel() should not be called`);
2401cb0ef41Sopenharmony_ci      } else {
2411cb0ef41Sopenharmony_ci        assert_array_equals(s.events, ['pull', 'cancel', undefined], `cancel() should be called`);
2421cb0ef41Sopenharmony_ci      }
2431cb0ef41Sopenharmony_ci    }, `Cancellation behavior when ${type}ing inside loop body; preventCancel = ${preventCancel}`);
2441cb0ef41Sopenharmony_ci  }
2451cb0ef41Sopenharmony_ci}
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_cifor (const preventCancel of [false, true]) {
2481cb0ef41Sopenharmony_ci  promise_test(async () => {
2491cb0ef41Sopenharmony_ci    const s = recordingReadableStream({
2501cb0ef41Sopenharmony_ci      start(c) {
2511cb0ef41Sopenharmony_ci        c.enqueue(0);
2521cb0ef41Sopenharmony_ci      }
2531cb0ef41Sopenharmony_ci    });
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci    const it = s.values({ preventCancel });
2561cb0ef41Sopenharmony_ci    await it.return();
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci    if (preventCancel) {
2591cb0ef41Sopenharmony_ci      assert_array_equals(s.events, [], `cancel() should not be called`);
2601cb0ef41Sopenharmony_ci    } else {
2611cb0ef41Sopenharmony_ci      assert_array_equals(s.events, ['cancel', undefined], `cancel() should be called`);
2621cb0ef41Sopenharmony_ci    }
2631cb0ef41Sopenharmony_ci  }, `Cancellation behavior when manually calling return(); preventCancel = ${preventCancel}`);
2641cb0ef41Sopenharmony_ci}
2651cb0ef41Sopenharmony_ci
2661cb0ef41Sopenharmony_cipromise_test(async t => {
2671cb0ef41Sopenharmony_ci  let timesPulled = 0;
2681cb0ef41Sopenharmony_ci  const s = new ReadableStream({
2691cb0ef41Sopenharmony_ci    pull(c) {
2701cb0ef41Sopenharmony_ci      if (timesPulled === 0) {
2711cb0ef41Sopenharmony_ci        c.enqueue(0);
2721cb0ef41Sopenharmony_ci        ++timesPulled;
2731cb0ef41Sopenharmony_ci      } else {
2741cb0ef41Sopenharmony_ci        c.error(error1);
2751cb0ef41Sopenharmony_ci      }
2761cb0ef41Sopenharmony_ci    }
2771cb0ef41Sopenharmony_ci  });
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci  const it = s[Symbol.asyncIterator]();
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci  const iterResult1 = await it.next();
2821cb0ef41Sopenharmony_ci  assert_iter_result(iterResult1, 0, false, '1st next()');
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci  await promise_rejects_exactly(t, error1, it.next(), '2nd next()');
2851cb0ef41Sopenharmony_ci}, 'next() rejects if the stream errors');
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_cipromise_test(async () => {
2881cb0ef41Sopenharmony_ci  let timesPulled = 0;
2891cb0ef41Sopenharmony_ci  const s = new ReadableStream({
2901cb0ef41Sopenharmony_ci    pull(c) {
2911cb0ef41Sopenharmony_ci      if (timesPulled === 0) {
2921cb0ef41Sopenharmony_ci        c.enqueue(0);
2931cb0ef41Sopenharmony_ci        ++timesPulled;
2941cb0ef41Sopenharmony_ci      } else {
2951cb0ef41Sopenharmony_ci        c.error(error1);
2961cb0ef41Sopenharmony_ci      }
2971cb0ef41Sopenharmony_ci    }
2981cb0ef41Sopenharmony_ci  });
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci  const it = s[Symbol.asyncIterator]();
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci  const iterResult = await it.return('return value');
3031cb0ef41Sopenharmony_ci  assert_iter_result(iterResult, 'return value', true);
3041cb0ef41Sopenharmony_ci}, 'return() does not rejects if the stream has not errored yet');
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_cipromise_test(async t => {
3071cb0ef41Sopenharmony_ci  let timesPulled = 0;
3081cb0ef41Sopenharmony_ci  const s = new ReadableStream({
3091cb0ef41Sopenharmony_ci    pull(c) {
3101cb0ef41Sopenharmony_ci      // Do not error in start() because doing so would prevent acquiring a reader/async iterator.
3111cb0ef41Sopenharmony_ci      c.error(error1);
3121cb0ef41Sopenharmony_ci    }
3131cb0ef41Sopenharmony_ci  });
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci  const it = s[Symbol.asyncIterator]();
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci  await flushAsyncEvents();
3181cb0ef41Sopenharmony_ci  await promise_rejects_exactly(t, error1, it.return('return value'));
3191cb0ef41Sopenharmony_ci}, 'return() rejects if the stream has errored');
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_cipromise_test(async t => {
3221cb0ef41Sopenharmony_ci  let timesPulled = 0;
3231cb0ef41Sopenharmony_ci  const s = new ReadableStream({
3241cb0ef41Sopenharmony_ci    pull(c) {
3251cb0ef41Sopenharmony_ci      if (timesPulled === 0) {
3261cb0ef41Sopenharmony_ci        c.enqueue(0);
3271cb0ef41Sopenharmony_ci        ++timesPulled;
3281cb0ef41Sopenharmony_ci      } else {
3291cb0ef41Sopenharmony_ci        c.error(error1);
3301cb0ef41Sopenharmony_ci      }
3311cb0ef41Sopenharmony_ci    }
3321cb0ef41Sopenharmony_ci  });
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci  const it = s[Symbol.asyncIterator]();
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_ci  const iterResult1 = await it.next();
3371cb0ef41Sopenharmony_ci  assert_iter_result(iterResult1, 0, false, '1st next()');
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ci  await promise_rejects_exactly(t, error1, it.next(), '2nd next()');
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  const iterResult3 = await it.next();
3421cb0ef41Sopenharmony_ci  assert_iter_result(iterResult3, undefined, true, '3rd next()');
3431cb0ef41Sopenharmony_ci}, 'next() that succeeds; next() that reports an error; next()');
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_cipromise_test(async () => {
3461cb0ef41Sopenharmony_ci  let timesPulled = 0;
3471cb0ef41Sopenharmony_ci  const s = new ReadableStream({
3481cb0ef41Sopenharmony_ci    pull(c) {
3491cb0ef41Sopenharmony_ci      if (timesPulled === 0) {
3501cb0ef41Sopenharmony_ci        c.enqueue(0);
3511cb0ef41Sopenharmony_ci        ++timesPulled;
3521cb0ef41Sopenharmony_ci      } else {
3531cb0ef41Sopenharmony_ci        c.error(error1);
3541cb0ef41Sopenharmony_ci      }
3551cb0ef41Sopenharmony_ci    }
3561cb0ef41Sopenharmony_ci  });
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci  const it = s[Symbol.asyncIterator]();
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  const iterResults = await Promise.allSettled([it.next(), it.next(), it.next()]);
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci  assert_equals(iterResults[0].status, 'fulfilled', '1st next() promise status');
3631cb0ef41Sopenharmony_ci  assert_iter_result(iterResults[0].value, 0, false, '1st next()');
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci  assert_equals(iterResults[1].status, 'rejected', '2nd next() promise status');
3661cb0ef41Sopenharmony_ci  assert_equals(iterResults[1].reason, error1, '2nd next() rejection reason');
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_ci  assert_equals(iterResults[2].status, 'fulfilled', '3rd next() promise status');
3691cb0ef41Sopenharmony_ci  assert_iter_result(iterResults[2].value, undefined, true, '3rd next()');
3701cb0ef41Sopenharmony_ci}, 'next() that succeeds; next() that reports an error(); next() [no awaiting]');
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_cipromise_test(async t => {
3731cb0ef41Sopenharmony_ci  let timesPulled = 0;
3741cb0ef41Sopenharmony_ci  const s = new ReadableStream({
3751cb0ef41Sopenharmony_ci    pull(c) {
3761cb0ef41Sopenharmony_ci      if (timesPulled === 0) {
3771cb0ef41Sopenharmony_ci        c.enqueue(0);
3781cb0ef41Sopenharmony_ci        ++timesPulled;
3791cb0ef41Sopenharmony_ci      } else {
3801cb0ef41Sopenharmony_ci        c.error(error1);
3811cb0ef41Sopenharmony_ci      }
3821cb0ef41Sopenharmony_ci    }
3831cb0ef41Sopenharmony_ci  });
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci  const it = s[Symbol.asyncIterator]();
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci  const iterResult1 = await it.next();
3881cb0ef41Sopenharmony_ci  assert_iter_result(iterResult1, 0, false, '1st next()');
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ci  await promise_rejects_exactly(t, error1, it.next(), '2nd next()');
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci  const iterResult3 = await it.return('return value');
3931cb0ef41Sopenharmony_ci  assert_iter_result(iterResult3, 'return value', true, 'return()');
3941cb0ef41Sopenharmony_ci}, 'next() that succeeds; next() that reports an error(); return()');
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_cipromise_test(async () => {
3971cb0ef41Sopenharmony_ci  let timesPulled = 0;
3981cb0ef41Sopenharmony_ci  const s = new ReadableStream({
3991cb0ef41Sopenharmony_ci    pull(c) {
4001cb0ef41Sopenharmony_ci      if (timesPulled === 0) {
4011cb0ef41Sopenharmony_ci        c.enqueue(0);
4021cb0ef41Sopenharmony_ci        ++timesPulled;
4031cb0ef41Sopenharmony_ci      } else {
4041cb0ef41Sopenharmony_ci        c.error(error1);
4051cb0ef41Sopenharmony_ci      }
4061cb0ef41Sopenharmony_ci    }
4071cb0ef41Sopenharmony_ci  });
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci  const it = s[Symbol.asyncIterator]();
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ci  const iterResults = await Promise.allSettled([it.next(), it.next(), it.return('return value')]);
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_ci  assert_equals(iterResults[0].status, 'fulfilled', '1st next() promise status');
4141cb0ef41Sopenharmony_ci  assert_iter_result(iterResults[0].value, 0, false, '1st next()');
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci  assert_equals(iterResults[1].status, 'rejected', '2nd next() promise status');
4171cb0ef41Sopenharmony_ci  assert_equals(iterResults[1].reason, error1, '2nd next() rejection reason');
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci  assert_equals(iterResults[2].status, 'fulfilled', 'return() promise status');
4201cb0ef41Sopenharmony_ci  assert_iter_result(iterResults[2].value, 'return value', true, 'return()');
4211cb0ef41Sopenharmony_ci}, 'next() that succeeds; next() that reports an error(); return() [no awaiting]');
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_cipromise_test(async () => {
4241cb0ef41Sopenharmony_ci  let timesPulled = 0;
4251cb0ef41Sopenharmony_ci  const s = new ReadableStream({
4261cb0ef41Sopenharmony_ci    pull(c) {
4271cb0ef41Sopenharmony_ci      c.enqueue(timesPulled);
4281cb0ef41Sopenharmony_ci      ++timesPulled;
4291cb0ef41Sopenharmony_ci    }
4301cb0ef41Sopenharmony_ci  });
4311cb0ef41Sopenharmony_ci  const it = s[Symbol.asyncIterator]();
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ci  const iterResult1 = await it.next();
4341cb0ef41Sopenharmony_ci  assert_iter_result(iterResult1, 0, false, 'next()');
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci  const iterResult2 = await it.return('return value');
4371cb0ef41Sopenharmony_ci  assert_iter_result(iterResult2, 'return value', true, 'return()');
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_ci  assert_equals(timesPulled, 2);
4401cb0ef41Sopenharmony_ci}, 'next() that succeeds; return()');
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_cipromise_test(async () => {
4431cb0ef41Sopenharmony_ci  let timesPulled = 0;
4441cb0ef41Sopenharmony_ci  const s = new ReadableStream({
4451cb0ef41Sopenharmony_ci    pull(c) {
4461cb0ef41Sopenharmony_ci      c.enqueue(timesPulled);
4471cb0ef41Sopenharmony_ci      ++timesPulled;
4481cb0ef41Sopenharmony_ci    }
4491cb0ef41Sopenharmony_ci  });
4501cb0ef41Sopenharmony_ci  const it = s[Symbol.asyncIterator]();
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_ci  const iterResults = await Promise.allSettled([it.next(), it.return('return value')]);
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ci  assert_equals(iterResults[0].status, 'fulfilled', 'next() promise status');
4551cb0ef41Sopenharmony_ci  assert_iter_result(iterResults[0].value, 0, false, 'next()');
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci  assert_equals(iterResults[1].status, 'fulfilled', 'return() promise status');
4581cb0ef41Sopenharmony_ci  assert_iter_result(iterResults[1].value, 'return value', true, 'return()');
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_ci  assert_equals(timesPulled, 2);
4611cb0ef41Sopenharmony_ci}, 'next() that succeeds; return() [no awaiting]');
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_cipromise_test(async () => {
4641cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
4651cb0ef41Sopenharmony_ci  const it = rs.values();
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci  const iterResult1 = await it.return('return value');
4681cb0ef41Sopenharmony_ci  assert_iter_result(iterResult1, 'return value', true, 'return()');
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ci  const iterResult2 = await it.next();
4711cb0ef41Sopenharmony_ci  assert_iter_result(iterResult2, undefined, true, 'next()');
4721cb0ef41Sopenharmony_ci}, 'return(); next()');
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_cipromise_test(async () => {
4751cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
4761cb0ef41Sopenharmony_ci  const it = rs.values();
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci  const iterResults = await Promise.allSettled([it.return('return value'), it.next()]);
4791cb0ef41Sopenharmony_ci
4801cb0ef41Sopenharmony_ci  assert_equals(iterResults[0].status, 'fulfilled', 'return() promise status');
4811cb0ef41Sopenharmony_ci  assert_iter_result(iterResults[0].value, 'return value', true, 'return()');
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_ci  assert_equals(iterResults[1].status, 'fulfilled', 'next() promise status');
4841cb0ef41Sopenharmony_ci  assert_iter_result(iterResults[1].value, undefined, true, 'next()');
4851cb0ef41Sopenharmony_ci}, 'return(); next() [no awaiting]');
4861cb0ef41Sopenharmony_ci
4871cb0ef41Sopenharmony_cipromise_test(async () => {
4881cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
4891cb0ef41Sopenharmony_ci  const it = rs.values();
4901cb0ef41Sopenharmony_ci
4911cb0ef41Sopenharmony_ci  const iterResult1 = await it.return('return value 1');
4921cb0ef41Sopenharmony_ci  assert_iter_result(iterResult1, 'return value 1', true, '1st return()');
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci  const iterResult2 = await it.return('return value 2');
4951cb0ef41Sopenharmony_ci  assert_iter_result(iterResult2, 'return value 2', true, '1st return()');
4961cb0ef41Sopenharmony_ci}, 'return(); return()');
4971cb0ef41Sopenharmony_ci
4981cb0ef41Sopenharmony_cipromise_test(async () => {
4991cb0ef41Sopenharmony_ci  const rs = new ReadableStream();
5001cb0ef41Sopenharmony_ci  const it = rs.values();
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ci  const iterResults = await Promise.allSettled([it.return('return value 1'), it.return('return value 2')]);
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_ci  assert_equals(iterResults[0].status, 'fulfilled', '1st return() promise status');
5051cb0ef41Sopenharmony_ci  assert_iter_result(iterResults[0].value, 'return value 1', true, '1st return()');
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ci  assert_equals(iterResults[1].status, 'fulfilled', '2nd return() promise status');
5081cb0ef41Sopenharmony_ci  assert_iter_result(iterResults[1].value, 'return value 2', true, '1st return()');
5091cb0ef41Sopenharmony_ci}, 'return(); return() [no awaiting]');
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_citest(() => {
5121cb0ef41Sopenharmony_ci  const s = new ReadableStream({
5131cb0ef41Sopenharmony_ci    start(c) {
5141cb0ef41Sopenharmony_ci      c.enqueue(0);
5151cb0ef41Sopenharmony_ci      c.close();
5161cb0ef41Sopenharmony_ci    },
5171cb0ef41Sopenharmony_ci  });
5181cb0ef41Sopenharmony_ci  s.values();
5191cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => s.values(), 'values() should throw');
5201cb0ef41Sopenharmony_ci}, 'values() throws if there\'s already a lock');
5211cb0ef41Sopenharmony_ci
5221cb0ef41Sopenharmony_cipromise_test(async () => {
5231cb0ef41Sopenharmony_ci  const s = new ReadableStream({
5241cb0ef41Sopenharmony_ci    start(c) {
5251cb0ef41Sopenharmony_ci      c.enqueue(1);
5261cb0ef41Sopenharmony_ci      c.enqueue(2);
5271cb0ef41Sopenharmony_ci      c.enqueue(3);
5281cb0ef41Sopenharmony_ci      c.close();
5291cb0ef41Sopenharmony_ci    }
5301cb0ef41Sopenharmony_ci  });
5311cb0ef41Sopenharmony_ci
5321cb0ef41Sopenharmony_ci  const chunks = [];
5331cb0ef41Sopenharmony_ci  for await (const chunk of s) {
5341cb0ef41Sopenharmony_ci    chunks.push(chunk);
5351cb0ef41Sopenharmony_ci  }
5361cb0ef41Sopenharmony_ci  assert_array_equals(chunks, [1, 2, 3]);
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ci  const reader = s.getReader();
5391cb0ef41Sopenharmony_ci  await reader.closed;
5401cb0ef41Sopenharmony_ci}, 'Acquiring a reader after exhaustively async-iterating a stream');
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_cipromise_test(async t => {
5431cb0ef41Sopenharmony_ci  let timesPulled = 0;
5441cb0ef41Sopenharmony_ci  const s = new ReadableStream({
5451cb0ef41Sopenharmony_ci    pull(c) {
5461cb0ef41Sopenharmony_ci      if (timesPulled === 0) {
5471cb0ef41Sopenharmony_ci        c.enqueue(0);
5481cb0ef41Sopenharmony_ci        ++timesPulled;
5491cb0ef41Sopenharmony_ci      } else {
5501cb0ef41Sopenharmony_ci        c.error(error1);
5511cb0ef41Sopenharmony_ci      }
5521cb0ef41Sopenharmony_ci    }
5531cb0ef41Sopenharmony_ci  });
5541cb0ef41Sopenharmony_ci
5551cb0ef41Sopenharmony_ci  const it = s[Symbol.asyncIterator]({ preventCancel: true });
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_ci  const iterResult1 = await it.next();
5581cb0ef41Sopenharmony_ci  assert_iter_result(iterResult1, 0, false, '1st next()');
5591cb0ef41Sopenharmony_ci
5601cb0ef41Sopenharmony_ci  await promise_rejects_exactly(t, error1, it.next(), '2nd next()');
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_ci  const iterResult2 = await it.return('return value');
5631cb0ef41Sopenharmony_ci  assert_iter_result(iterResult2, 'return value', true, 'return()');
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci  // i.e. it should not reject with a generic "this stream is locked" TypeError.
5661cb0ef41Sopenharmony_ci  const reader = s.getReader();
5671cb0ef41Sopenharmony_ci  await promise_rejects_exactly(t, error1, reader.closed, 'closed on the new reader should reject with the error');
5681cb0ef41Sopenharmony_ci}, 'Acquiring a reader after return()ing from a stream that errors');
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_cipromise_test(async () => {
5711cb0ef41Sopenharmony_ci  const s = new ReadableStream({
5721cb0ef41Sopenharmony_ci    start(c) {
5731cb0ef41Sopenharmony_ci      c.enqueue(1);
5741cb0ef41Sopenharmony_ci      c.enqueue(2);
5751cb0ef41Sopenharmony_ci      c.enqueue(3);
5761cb0ef41Sopenharmony_ci      c.close();
5771cb0ef41Sopenharmony_ci    },
5781cb0ef41Sopenharmony_ci  });
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci  // read the first two chunks, then cancel
5811cb0ef41Sopenharmony_ci  const chunks = [];
5821cb0ef41Sopenharmony_ci  for await (const chunk of s) {
5831cb0ef41Sopenharmony_ci    chunks.push(chunk);
5841cb0ef41Sopenharmony_ci    if (chunk >= 2) {
5851cb0ef41Sopenharmony_ci      break;
5861cb0ef41Sopenharmony_ci    }
5871cb0ef41Sopenharmony_ci  }
5881cb0ef41Sopenharmony_ci  assert_array_equals(chunks, [1, 2]);
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci  const reader = s.getReader();
5911cb0ef41Sopenharmony_ci  await reader.closed;
5921cb0ef41Sopenharmony_ci}, 'Acquiring a reader after partially async-iterating a stream');
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_cipromise_test(async () => {
5951cb0ef41Sopenharmony_ci  const s = new ReadableStream({
5961cb0ef41Sopenharmony_ci    start(c) {
5971cb0ef41Sopenharmony_ci      c.enqueue(1);
5981cb0ef41Sopenharmony_ci      c.enqueue(2);
5991cb0ef41Sopenharmony_ci      c.enqueue(3);
6001cb0ef41Sopenharmony_ci      c.close();
6011cb0ef41Sopenharmony_ci    },
6021cb0ef41Sopenharmony_ci  });
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ci  // read the first two chunks, then release lock
6051cb0ef41Sopenharmony_ci  const chunks = [];
6061cb0ef41Sopenharmony_ci  for await (const chunk of s.values({preventCancel: true})) {
6071cb0ef41Sopenharmony_ci    chunks.push(chunk);
6081cb0ef41Sopenharmony_ci    if (chunk >= 2) {
6091cb0ef41Sopenharmony_ci      break;
6101cb0ef41Sopenharmony_ci    }
6111cb0ef41Sopenharmony_ci  }
6121cb0ef41Sopenharmony_ci  assert_array_equals(chunks, [1, 2]);
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci  const reader = s.getReader();
6151cb0ef41Sopenharmony_ci  const readResult = await reader.read();
6161cb0ef41Sopenharmony_ci  assert_iter_result(readResult, 3, false);
6171cb0ef41Sopenharmony_ci  await reader.closed;
6181cb0ef41Sopenharmony_ci}, 'Acquiring a reader and reading the remaining chunks after partially async-iterating a stream with preventCancel = true');
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_cifor (const preventCancel of [false, true]) {
6211cb0ef41Sopenharmony_ci  test(() => {
6221cb0ef41Sopenharmony_ci    const rs = new ReadableStream();
6231cb0ef41Sopenharmony_ci    rs.values({ preventCancel }).return();
6241cb0ef41Sopenharmony_ci    // The test passes if this line doesn't throw.
6251cb0ef41Sopenharmony_ci    rs.getReader();
6261cb0ef41Sopenharmony_ci  }, `return() should unlock the stream synchronously when preventCancel = ${preventCancel}`);
6271cb0ef41Sopenharmony_ci}
6281cb0ef41Sopenharmony_ci
6291cb0ef41Sopenharmony_cipromise_test(async () => {
6301cb0ef41Sopenharmony_ci  const rs = new ReadableStream({
6311cb0ef41Sopenharmony_ci    async start(c) {
6321cb0ef41Sopenharmony_ci      c.enqueue('a');
6331cb0ef41Sopenharmony_ci      c.enqueue('b');
6341cb0ef41Sopenharmony_ci      c.enqueue('c');
6351cb0ef41Sopenharmony_ci      await flushAsyncEvents();
6361cb0ef41Sopenharmony_ci      // At this point, the async iterator has a read request in the stream's queue for its pending next() promise.
6371cb0ef41Sopenharmony_ci      // Closing the stream now causes two things to happen *synchronously*:
6381cb0ef41Sopenharmony_ci      //  1. ReadableStreamClose resolves reader.[[closedPromise]] with undefined.
6391cb0ef41Sopenharmony_ci      //  2. ReadableStreamClose calls the read request's close steps, which calls ReadableStreamReaderGenericRelease,
6401cb0ef41Sopenharmony_ci      //     which replaces reader.[[closedPromise]] with a rejected promise.
6411cb0ef41Sopenharmony_ci      c.close();
6421cb0ef41Sopenharmony_ci    }
6431cb0ef41Sopenharmony_ci  });
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_ci  const chunks = [];
6461cb0ef41Sopenharmony_ci  for await (const chunk of rs) {
6471cb0ef41Sopenharmony_ci    chunks.push(chunk);
6481cb0ef41Sopenharmony_ci  }
6491cb0ef41Sopenharmony_ci  assert_array_equals(chunks, ['a', 'b', 'c']);
6501cb0ef41Sopenharmony_ci}, 'close() while next() is pending');
651