11cb0ef41Sopenharmony_ci// META: global=window,worker
21cb0ef41Sopenharmony_ci// META: script=../resources/test-utils.js
31cb0ef41Sopenharmony_ci// META: script=../resources/recording-streams.js
41cb0ef41Sopenharmony_ci'use strict';
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciconst error1 = new Error('error1');
71cb0ef41Sopenharmony_cierror1.name = 'error1';
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciconst error2 = new Error('error2');
101cb0ef41Sopenharmony_cierror2.name = 'error2';
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cipromise_test(() => {
131cb0ef41Sopenharmony_ci  const ws = new WritableStream({
141cb0ef41Sopenharmony_ci    close() {
151cb0ef41Sopenharmony_ci      return 'Hello';
161cb0ef41Sopenharmony_ci    }
171cb0ef41Sopenharmony_ci  });
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  const closePromise = writer.close();
221cb0ef41Sopenharmony_ci  return closePromise.then(value => assert_equals(value, undefined, 'fulfillment value must be undefined'));
231cb0ef41Sopenharmony_ci}, 'fulfillment value of writer.close() call must be undefined even if the underlying sink returns a non-undefined ' +
241cb0ef41Sopenharmony_ci    'value');
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_cipromise_test(() => {
271cb0ef41Sopenharmony_ci  let controller;
281cb0ef41Sopenharmony_ci  let resolveClose;
291cb0ef41Sopenharmony_ci  const ws = new WritableStream({
301cb0ef41Sopenharmony_ci    start(c) {
311cb0ef41Sopenharmony_ci      controller = c;
321cb0ef41Sopenharmony_ci    },
331cb0ef41Sopenharmony_ci    close() {
341cb0ef41Sopenharmony_ci      return new Promise(resolve => {
351cb0ef41Sopenharmony_ci        resolveClose = resolve;
361cb0ef41Sopenharmony_ci      });
371cb0ef41Sopenharmony_ci    }
381cb0ef41Sopenharmony_ci  });
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  const closePromise = writer.close();
431cb0ef41Sopenharmony_ci  return flushAsyncEvents().then(() => {
441cb0ef41Sopenharmony_ci    controller.error(error1);
451cb0ef41Sopenharmony_ci    return flushAsyncEvents();
461cb0ef41Sopenharmony_ci  }).then(() => {
471cb0ef41Sopenharmony_ci    resolveClose();
481cb0ef41Sopenharmony_ci    return Promise.all([
491cb0ef41Sopenharmony_ci      closePromise,
501cb0ef41Sopenharmony_ci      writer.closed,
511cb0ef41Sopenharmony_ci      flushAsyncEvents().then(() => writer.closed)]);
521cb0ef41Sopenharmony_ci  });
531cb0ef41Sopenharmony_ci}, 'when sink calls error asynchronously while sink close is in-flight, the stream should not become errored');
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_cipromise_test(() => {
561cb0ef41Sopenharmony_ci  let controller;
571cb0ef41Sopenharmony_ci  const passedError = new Error('error me');
581cb0ef41Sopenharmony_ci  const ws = new WritableStream({
591cb0ef41Sopenharmony_ci    start(c) {
601cb0ef41Sopenharmony_ci      controller = c;
611cb0ef41Sopenharmony_ci    },
621cb0ef41Sopenharmony_ci    close() {
631cb0ef41Sopenharmony_ci      controller.error(passedError);
641cb0ef41Sopenharmony_ci    }
651cb0ef41Sopenharmony_ci  });
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  return writer.close().then(() => writer.closed);
701cb0ef41Sopenharmony_ci}, 'when sink calls error synchronously while closing, the stream should not become errored');
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_cipromise_test(t => {
731cb0ef41Sopenharmony_ci  const ws = new WritableStream({
741cb0ef41Sopenharmony_ci    close() {
751cb0ef41Sopenharmony_ci      throw error1;
761cb0ef41Sopenharmony_ci    }
771cb0ef41Sopenharmony_ci  });
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  return Promise.all([
821cb0ef41Sopenharmony_ci    writer.write('y'),
831cb0ef41Sopenharmony_ci    promise_rejects_exactly(t, error1, writer.close(), 'close() must reject with the error'),
841cb0ef41Sopenharmony_ci    promise_rejects_exactly(t, error1, writer.closed, 'closed must reject with the error')
851cb0ef41Sopenharmony_ci  ]);
861cb0ef41Sopenharmony_ci}, 'when the sink throws during close, and the close is requested while a write is still in-flight, the stream should ' +
871cb0ef41Sopenharmony_ci   'become errored during the close');
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_cipromise_test(() => {
901cb0ef41Sopenharmony_ci  const ws = new WritableStream({
911cb0ef41Sopenharmony_ci    write(chunk, controller) {
921cb0ef41Sopenharmony_ci      controller.error(error1);
931cb0ef41Sopenharmony_ci      return new Promise(() => {});
941cb0ef41Sopenharmony_ci    }
951cb0ef41Sopenharmony_ci  });
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
981cb0ef41Sopenharmony_ci  writer.write('a');
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  return delay(0).then(() => {
1011cb0ef41Sopenharmony_ci    writer.releaseLock();
1021cb0ef41Sopenharmony_ci  });
1031cb0ef41Sopenharmony_ci}, 'releaseLock on a stream with a pending write in which the stream has been errored');
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_cipromise_test(() => {
1061cb0ef41Sopenharmony_ci  let controller;
1071cb0ef41Sopenharmony_ci  const ws = new WritableStream({
1081cb0ef41Sopenharmony_ci    start(c) {
1091cb0ef41Sopenharmony_ci      controller = c;
1101cb0ef41Sopenharmony_ci    },
1111cb0ef41Sopenharmony_ci    close() {
1121cb0ef41Sopenharmony_ci      controller.error(error1);
1131cb0ef41Sopenharmony_ci      return new Promise(() => {});
1141cb0ef41Sopenharmony_ci    }
1151cb0ef41Sopenharmony_ci  });
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
1181cb0ef41Sopenharmony_ci  writer.close();
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  return delay(0).then(() => {
1211cb0ef41Sopenharmony_ci    writer.releaseLock();
1221cb0ef41Sopenharmony_ci  });
1231cb0ef41Sopenharmony_ci}, 'releaseLock on a stream with a pending close in which controller.error() was called');
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_cipromise_test(() => {
1261cb0ef41Sopenharmony_ci  const ws = recordingWritableStream();
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci  return writer.ready.then(() => {
1311cb0ef41Sopenharmony_ci    assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci    writer.close();
1341cb0ef41Sopenharmony_ci    assert_equals(writer.desiredSize, 1, 'desiredSize should be still 1');
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci    return writer.ready.then(v => {
1371cb0ef41Sopenharmony_ci      assert_equals(v, undefined, 'ready promise should be fulfilled with undefined');
1381cb0ef41Sopenharmony_ci      assert_array_equals(ws.events, ['close'], 'write and abort should not be called');
1391cb0ef41Sopenharmony_ci    });
1401cb0ef41Sopenharmony_ci  });
1411cb0ef41Sopenharmony_ci}, 'when close is called on a WritableStream in writable state, ready should return a fulfilled promise');
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_cipromise_test(() => {
1441cb0ef41Sopenharmony_ci  const ws = recordingWritableStream({
1451cb0ef41Sopenharmony_ci    write() {
1461cb0ef41Sopenharmony_ci      return new Promise(() => {});
1471cb0ef41Sopenharmony_ci    }
1481cb0ef41Sopenharmony_ci  });
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  return writer.ready.then(() => {
1531cb0ef41Sopenharmony_ci    writer.write('a');
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci    assert_equals(writer.desiredSize, 0, 'desiredSize should be 0');
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci    let calledClose = false;
1581cb0ef41Sopenharmony_ci    return Promise.all([
1591cb0ef41Sopenharmony_ci      writer.ready.then(v => {
1601cb0ef41Sopenharmony_ci        assert_equals(v, undefined, 'ready promise should be fulfilled with undefined');
1611cb0ef41Sopenharmony_ci        assert_true(calledClose, 'ready should not be fulfilled before writer.close() is called');
1621cb0ef41Sopenharmony_ci        assert_array_equals(ws.events, ['write', 'a'], 'sink abort() should not be called');
1631cb0ef41Sopenharmony_ci      }),
1641cb0ef41Sopenharmony_ci      flushAsyncEvents().then(() => {
1651cb0ef41Sopenharmony_ci        writer.close();
1661cb0ef41Sopenharmony_ci        calledClose = true;
1671cb0ef41Sopenharmony_ci      })
1681cb0ef41Sopenharmony_ci    ]);
1691cb0ef41Sopenharmony_ci  });
1701cb0ef41Sopenharmony_ci}, 'when close is called on a WritableStream in waiting state, ready promise should be fulfilled');
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_cipromise_test(() => {
1731cb0ef41Sopenharmony_ci  let asyncCloseFinished = false;
1741cb0ef41Sopenharmony_ci  const ws = recordingWritableStream({
1751cb0ef41Sopenharmony_ci    close() {
1761cb0ef41Sopenharmony_ci      return flushAsyncEvents().then(() => {
1771cb0ef41Sopenharmony_ci        asyncCloseFinished = true;
1781cb0ef41Sopenharmony_ci      });
1791cb0ef41Sopenharmony_ci    }
1801cb0ef41Sopenharmony_ci  });
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
1831cb0ef41Sopenharmony_ci  return writer.ready.then(() => {
1841cb0ef41Sopenharmony_ci    writer.write('a');
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci    writer.close();
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci    return writer.ready.then(v => {
1891cb0ef41Sopenharmony_ci      assert_false(asyncCloseFinished, 'ready promise should be fulfilled before async close completes');
1901cb0ef41Sopenharmony_ci      assert_equals(v, undefined, 'ready promise should be fulfilled with undefined');
1911cb0ef41Sopenharmony_ci      assert_array_equals(ws.events, ['write', 'a', 'close'], 'sink abort() should not be called');
1921cb0ef41Sopenharmony_ci    });
1931cb0ef41Sopenharmony_ci  });
1941cb0ef41Sopenharmony_ci}, 'when close is called on a WritableStream in waiting state, ready should be fulfilled immediately even if close ' +
1951cb0ef41Sopenharmony_ci    'takes a long time');
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_cipromise_test(t => {
1981cb0ef41Sopenharmony_ci  const rejection = { name: 'letter' };
1991cb0ef41Sopenharmony_ci  const ws = new WritableStream({
2001cb0ef41Sopenharmony_ci    close() {
2011cb0ef41Sopenharmony_ci      return {
2021cb0ef41Sopenharmony_ci        then(onFulfilled, onRejected) { onRejected(rejection); }
2031cb0ef41Sopenharmony_ci      };
2041cb0ef41Sopenharmony_ci    }
2051cb0ef41Sopenharmony_ci  });
2061cb0ef41Sopenharmony_ci  return promise_rejects_exactly(t, rejection, ws.getWriter().close(), 'close() should return a rejection');
2071cb0ef41Sopenharmony_ci}, 'returning a thenable from close() should work');
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_cipromise_test(t => {
2101cb0ef41Sopenharmony_ci  const ws = new WritableStream();
2111cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
2121cb0ef41Sopenharmony_ci  return writer.ready.then(() => {
2131cb0ef41Sopenharmony_ci    const closePromise = writer.close();
2141cb0ef41Sopenharmony_ci    const closedPromise = writer.closed;
2151cb0ef41Sopenharmony_ci    writer.releaseLock();
2161cb0ef41Sopenharmony_ci    return Promise.all([
2171cb0ef41Sopenharmony_ci      closePromise,
2181cb0ef41Sopenharmony_ci      promise_rejects_js(t, TypeError, closedPromise, '.closed promise should be rejected')
2191cb0ef41Sopenharmony_ci    ]);
2201cb0ef41Sopenharmony_ci  });
2211cb0ef41Sopenharmony_ci}, 'releaseLock() should not change the result of sync close()');
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_cipromise_test(t => {
2241cb0ef41Sopenharmony_ci  const ws = new WritableStream({
2251cb0ef41Sopenharmony_ci    close() {
2261cb0ef41Sopenharmony_ci      return flushAsyncEvents();
2271cb0ef41Sopenharmony_ci    }
2281cb0ef41Sopenharmony_ci  });
2291cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
2301cb0ef41Sopenharmony_ci  return writer.ready.then(() => {
2311cb0ef41Sopenharmony_ci    const closePromise = writer.close();
2321cb0ef41Sopenharmony_ci    const closedPromise = writer.closed;
2331cb0ef41Sopenharmony_ci    writer.releaseLock();
2341cb0ef41Sopenharmony_ci    return Promise.all([
2351cb0ef41Sopenharmony_ci      closePromise,
2361cb0ef41Sopenharmony_ci      promise_rejects_js(t, TypeError, closedPromise, '.closed promise should be rejected')
2371cb0ef41Sopenharmony_ci    ]);
2381cb0ef41Sopenharmony_ci  });
2391cb0ef41Sopenharmony_ci}, 'releaseLock() should not change the result of async close()');
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_cipromise_test(() => {
2421cb0ef41Sopenharmony_ci  let resolveClose;
2431cb0ef41Sopenharmony_ci  const ws = new WritableStream({
2441cb0ef41Sopenharmony_ci    close() {
2451cb0ef41Sopenharmony_ci      const promise = new Promise(resolve => {
2461cb0ef41Sopenharmony_ci        resolveClose = resolve;
2471cb0ef41Sopenharmony_ci      });
2481cb0ef41Sopenharmony_ci      return promise;
2491cb0ef41Sopenharmony_ci    }
2501cb0ef41Sopenharmony_ci  });
2511cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
2521cb0ef41Sopenharmony_ci  const closePromise = writer.close();
2531cb0ef41Sopenharmony_ci  writer.releaseLock();
2541cb0ef41Sopenharmony_ci  return delay(0).then(() => {
2551cb0ef41Sopenharmony_ci    resolveClose();
2561cb0ef41Sopenharmony_ci    return closePromise.then(() => {
2571cb0ef41Sopenharmony_ci      assert_equals(ws.getWriter().desiredSize, 0, 'desiredSize should be 0');
2581cb0ef41Sopenharmony_ci    });
2591cb0ef41Sopenharmony_ci  });
2601cb0ef41Sopenharmony_ci}, 'close() should set state to CLOSED even if writer has detached');
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_cipromise_test(() => {
2631cb0ef41Sopenharmony_ci  let resolveClose;
2641cb0ef41Sopenharmony_ci  const ws = new WritableStream({
2651cb0ef41Sopenharmony_ci    close() {
2661cb0ef41Sopenharmony_ci      const promise = new Promise(resolve => {
2671cb0ef41Sopenharmony_ci        resolveClose = resolve;
2681cb0ef41Sopenharmony_ci      });
2691cb0ef41Sopenharmony_ci      return promise;
2701cb0ef41Sopenharmony_ci    }
2711cb0ef41Sopenharmony_ci  });
2721cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
2731cb0ef41Sopenharmony_ci  writer.close();
2741cb0ef41Sopenharmony_ci  writer.releaseLock();
2751cb0ef41Sopenharmony_ci  return delay(0).then(() => {
2761cb0ef41Sopenharmony_ci    const abortingWriter = ws.getWriter();
2771cb0ef41Sopenharmony_ci    const abortPromise = abortingWriter.abort();
2781cb0ef41Sopenharmony_ci    abortingWriter.releaseLock();
2791cb0ef41Sopenharmony_ci    resolveClose();
2801cb0ef41Sopenharmony_ci    return abortPromise;
2811cb0ef41Sopenharmony_ci  });
2821cb0ef41Sopenharmony_ci}, 'the promise returned by async abort during close should resolve');
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci// Though the order in which the promises are fulfilled or rejected is arbitrary, we're checking it for
2851cb0ef41Sopenharmony_ci// interoperability. We can change the order as long as we file bugs on all implementers to update to the latest tests
2861cb0ef41Sopenharmony_ci// to keep them interoperable.
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_cipromise_test(() => {
2891cb0ef41Sopenharmony_ci  const ws = new WritableStream({});
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci  const closePromise = writer.close();
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci  const events = [];
2961cb0ef41Sopenharmony_ci  return Promise.all([
2971cb0ef41Sopenharmony_ci    closePromise.then(() => {
2981cb0ef41Sopenharmony_ci      events.push('closePromise');
2991cb0ef41Sopenharmony_ci    }),
3001cb0ef41Sopenharmony_ci    writer.closed.then(() => {
3011cb0ef41Sopenharmony_ci      events.push('closed');
3021cb0ef41Sopenharmony_ci    })
3031cb0ef41Sopenharmony_ci  ]).then(() => {
3041cb0ef41Sopenharmony_ci    assert_array_equals(events, ['closePromise', 'closed'],
3051cb0ef41Sopenharmony_ci                        'promises must fulfill/reject in the expected order');
3061cb0ef41Sopenharmony_ci  });
3071cb0ef41Sopenharmony_ci}, 'promises must fulfill/reject in the expected order on closure');
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_cipromise_test(() => {
3101cb0ef41Sopenharmony_ci  const ws = new WritableStream({});
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci  // Wait until the WritableStream starts so that the close() call gets processed. Otherwise, abort() will be
3131cb0ef41Sopenharmony_ci  // processed without waiting for completion of the close().
3141cb0ef41Sopenharmony_ci  return delay(0).then(() => {
3151cb0ef41Sopenharmony_ci    const writer = ws.getWriter();
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci    const closePromise = writer.close();
3181cb0ef41Sopenharmony_ci    const abortPromise = writer.abort(error1);
3191cb0ef41Sopenharmony_ci
3201cb0ef41Sopenharmony_ci    const events = [];
3211cb0ef41Sopenharmony_ci    return Promise.all([
3221cb0ef41Sopenharmony_ci      closePromise.then(() => {
3231cb0ef41Sopenharmony_ci        events.push('closePromise');
3241cb0ef41Sopenharmony_ci      }),
3251cb0ef41Sopenharmony_ci      abortPromise.then(() => {
3261cb0ef41Sopenharmony_ci        events.push('abortPromise');
3271cb0ef41Sopenharmony_ci      }),
3281cb0ef41Sopenharmony_ci      writer.closed.then(() => {
3291cb0ef41Sopenharmony_ci        events.push('closed');
3301cb0ef41Sopenharmony_ci      })
3311cb0ef41Sopenharmony_ci    ]).then(() => {
3321cb0ef41Sopenharmony_ci      assert_array_equals(events, ['closePromise', 'abortPromise', 'closed'],
3331cb0ef41Sopenharmony_ci                          'promises must fulfill/reject in the expected order');
3341cb0ef41Sopenharmony_ci    });
3351cb0ef41Sopenharmony_ci  });
3361cb0ef41Sopenharmony_ci}, 'promises must fulfill/reject in the expected order on aborted closure');
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_cipromise_test(t => {
3391cb0ef41Sopenharmony_ci  const ws = new WritableStream({
3401cb0ef41Sopenharmony_ci    close() {
3411cb0ef41Sopenharmony_ci      return Promise.reject(error1);
3421cb0ef41Sopenharmony_ci    }
3431cb0ef41Sopenharmony_ci  });
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_ci  // Wait until the WritableStream starts so that the close() call gets processed.
3461cb0ef41Sopenharmony_ci  return delay(0).then(() => {
3471cb0ef41Sopenharmony_ci    const writer = ws.getWriter();
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci    const closePromise = writer.close();
3501cb0ef41Sopenharmony_ci    const abortPromise = writer.abort(error2);
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci    const events = [];
3531cb0ef41Sopenharmony_ci    closePromise.catch(() => events.push('closePromise'));
3541cb0ef41Sopenharmony_ci    abortPromise.catch(() => events.push('abortPromise'));
3551cb0ef41Sopenharmony_ci    writer.closed.catch(() => events.push('closed'));
3561cb0ef41Sopenharmony_ci    return Promise.all([
3571cb0ef41Sopenharmony_ci      promise_rejects_exactly(t, error1, closePromise,
3581cb0ef41Sopenharmony_ci                             'closePromise must reject with the error returned from the sink\'s close method'),
3591cb0ef41Sopenharmony_ci      promise_rejects_exactly(t, error1, abortPromise,
3601cb0ef41Sopenharmony_ci                             'abortPromise must reject with the error returned from the sink\'s close method'),
3611cb0ef41Sopenharmony_ci      promise_rejects_exactly(t, error2, writer.closed,
3621cb0ef41Sopenharmony_ci                              'writer.closed must reject with error2')
3631cb0ef41Sopenharmony_ci    ]).then(() => {
3641cb0ef41Sopenharmony_ci      assert_array_equals(events, ['closePromise', 'abortPromise', 'closed'],
3651cb0ef41Sopenharmony_ci                          'promises must fulfill/reject in the expected order');
3661cb0ef41Sopenharmony_ci    });
3671cb0ef41Sopenharmony_ci  });
3681cb0ef41Sopenharmony_ci}, 'promises must fulfill/reject in the expected order on aborted and errored closure');
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_cipromise_test(t => {
3711cb0ef41Sopenharmony_ci  let resolveWrite;
3721cb0ef41Sopenharmony_ci  let controller;
3731cb0ef41Sopenharmony_ci  const ws = new WritableStream({
3741cb0ef41Sopenharmony_ci    write(chunk, c) {
3751cb0ef41Sopenharmony_ci      controller = c;
3761cb0ef41Sopenharmony_ci      return new Promise(resolve => {
3771cb0ef41Sopenharmony_ci        resolveWrite = resolve;
3781cb0ef41Sopenharmony_ci      });
3791cb0ef41Sopenharmony_ci    }
3801cb0ef41Sopenharmony_ci  });
3811cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
3821cb0ef41Sopenharmony_ci  return writer.ready.then(() => {
3831cb0ef41Sopenharmony_ci    const writePromise = writer.write('c');
3841cb0ef41Sopenharmony_ci    controller.error(error1);
3851cb0ef41Sopenharmony_ci    const closePromise = writer.close();
3861cb0ef41Sopenharmony_ci    let closeRejected = false;
3871cb0ef41Sopenharmony_ci    closePromise.catch(() => {
3881cb0ef41Sopenharmony_ci      closeRejected = true;
3891cb0ef41Sopenharmony_ci    });
3901cb0ef41Sopenharmony_ci    return flushAsyncEvents().then(() => {
3911cb0ef41Sopenharmony_ci      assert_false(closeRejected);
3921cb0ef41Sopenharmony_ci      resolveWrite();
3931cb0ef41Sopenharmony_ci      return Promise.all([
3941cb0ef41Sopenharmony_ci        writePromise,
3951cb0ef41Sopenharmony_ci        promise_rejects_exactly(t, error1, closePromise, 'close() should reject')
3961cb0ef41Sopenharmony_ci      ]).then(() => {
3971cb0ef41Sopenharmony_ci        assert_true(closeRejected);
3981cb0ef41Sopenharmony_ci      });
3991cb0ef41Sopenharmony_ci    });
4001cb0ef41Sopenharmony_ci  });
4011cb0ef41Sopenharmony_ci}, 'close() should not reject until no sink methods are in flight');
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_cipromise_test(() => {
4041cb0ef41Sopenharmony_ci  const ws = new WritableStream();
4051cb0ef41Sopenharmony_ci  const writer1 = ws.getWriter();
4061cb0ef41Sopenharmony_ci  return writer1.close().then(() => {
4071cb0ef41Sopenharmony_ci    writer1.releaseLock();
4081cb0ef41Sopenharmony_ci    const writer2 = ws.getWriter();
4091cb0ef41Sopenharmony_ci    const ready = writer2.ready;
4101cb0ef41Sopenharmony_ci    assert_equals(ready.constructor, Promise);
4111cb0ef41Sopenharmony_ci    return ready;
4121cb0ef41Sopenharmony_ci  });
4131cb0ef41Sopenharmony_ci}, 'ready promise should be initialised as fulfilled for a writer on a closed stream');
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_cipromise_test(() => {
4161cb0ef41Sopenharmony_ci  const ws = new WritableStream();
4171cb0ef41Sopenharmony_ci  ws.close();
4181cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
4191cb0ef41Sopenharmony_ci  return writer.closed;
4201cb0ef41Sopenharmony_ci}, 'close() on a writable stream should work');
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_cipromise_test(t => {
4231cb0ef41Sopenharmony_ci  const ws = new WritableStream();
4241cb0ef41Sopenharmony_ci  ws.getWriter();
4251cb0ef41Sopenharmony_ci  return promise_rejects_js(t, TypeError, ws.close(), 'close should reject');
4261cb0ef41Sopenharmony_ci}, 'close() on a locked stream should reject');
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_cipromise_test(t => {
4291cb0ef41Sopenharmony_ci  const ws = new WritableStream({
4301cb0ef41Sopenharmony_ci    start(controller) {
4311cb0ef41Sopenharmony_ci      controller.error(error1);
4321cb0ef41Sopenharmony_ci    }
4331cb0ef41Sopenharmony_ci  });
4341cb0ef41Sopenharmony_ci  return promise_rejects_exactly(t, error1, ws.close(), 'close should reject with error1');
4351cb0ef41Sopenharmony_ci}, 'close() on an erroring stream should reject');
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_cipromise_test(t => {
4381cb0ef41Sopenharmony_ci  const ws = new WritableStream({
4391cb0ef41Sopenharmony_ci    start(controller) {
4401cb0ef41Sopenharmony_ci      controller.error(error1);
4411cb0ef41Sopenharmony_ci    }
4421cb0ef41Sopenharmony_ci  });
4431cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
4441cb0ef41Sopenharmony_ci  return promise_rejects_exactly(t, error1, writer.closed, 'closed should reject with the error').then(() => {
4451cb0ef41Sopenharmony_ci    writer.releaseLock();
4461cb0ef41Sopenharmony_ci    return promise_rejects_js(t, TypeError, ws.close(), 'close should reject');
4471cb0ef41Sopenharmony_ci  });
4481cb0ef41Sopenharmony_ci}, 'close() on an errored stream should reject');
4491cb0ef41Sopenharmony_ci
4501cb0ef41Sopenharmony_cipromise_test(t => {
4511cb0ef41Sopenharmony_ci  const ws = new WritableStream();
4521cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
4531cb0ef41Sopenharmony_ci  return writer.close().then(() => {
4541cb0ef41Sopenharmony_ci    return promise_rejects_js(t, TypeError, ws.close(), 'close should reject');
4551cb0ef41Sopenharmony_ci  });
4561cb0ef41Sopenharmony_ci}, 'close() on an closed stream should reject');
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_cipromise_test(t => {
4591cb0ef41Sopenharmony_ci  const ws = new WritableStream({
4601cb0ef41Sopenharmony_ci    close() {
4611cb0ef41Sopenharmony_ci      return new Promise(() => {});
4621cb0ef41Sopenharmony_ci    }
4631cb0ef41Sopenharmony_ci  });
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
4661cb0ef41Sopenharmony_ci  writer.close();
4671cb0ef41Sopenharmony_ci  writer.releaseLock();
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ci  return promise_rejects_js(t, TypeError, ws.close(), 'close should reject');
4701cb0ef41Sopenharmony_ci}, 'close() on a stream with a pending close should reject');
471