11cb0ef41Sopenharmony_ci// META: global=window,worker
21cb0ef41Sopenharmony_ci'use strict';
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_citest(() => {
51cb0ef41Sopenharmony_ci  const ws = new WritableStream({});
61cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
71cb0ef41Sopenharmony_ci  writer.releaseLock();
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => writer.desiredSize, 'desiredSize should throw a TypeError');
101cb0ef41Sopenharmony_ci}, 'desiredSize on a released writer');
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_citest(() => {
131cb0ef41Sopenharmony_ci  const ws = new WritableStream({});
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci  assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
181cb0ef41Sopenharmony_ci}, 'desiredSize initial value');
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_cipromise_test(() => {
211cb0ef41Sopenharmony_ci  const ws = new WritableStream({});
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  writer.close();
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci  return writer.closed.then(() => {
281cb0ef41Sopenharmony_ci    assert_equals(writer.desiredSize, 0, 'desiredSize should be 0');
291cb0ef41Sopenharmony_ci  });
301cb0ef41Sopenharmony_ci}, 'desiredSize on a writer for a closed stream');
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_citest(() => {
331cb0ef41Sopenharmony_ci  const ws = new WritableStream({
341cb0ef41Sopenharmony_ci    start(c) {
351cb0ef41Sopenharmony_ci      c.error();
361cb0ef41Sopenharmony_ci    }
371cb0ef41Sopenharmony_ci  });
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
401cb0ef41Sopenharmony_ci  assert_equals(writer.desiredSize, null, 'desiredSize should be null');
411cb0ef41Sopenharmony_ci}, 'desiredSize on a writer for an errored stream');
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_citest(() => {
441cb0ef41Sopenharmony_ci  const ws = new WritableStream({});
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
471cb0ef41Sopenharmony_ci  writer.close();
481cb0ef41Sopenharmony_ci  writer.releaseLock();
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  ws.getWriter();
511cb0ef41Sopenharmony_ci}, 'ws.getWriter() on a closing WritableStream');
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_cipromise_test(() => {
541cb0ef41Sopenharmony_ci  const ws = new WritableStream({});
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
571cb0ef41Sopenharmony_ci  return writer.close().then(() => {
581cb0ef41Sopenharmony_ci    writer.releaseLock();
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci    ws.getWriter();
611cb0ef41Sopenharmony_ci  });
621cb0ef41Sopenharmony_ci}, 'ws.getWriter() on a closed WritableStream');
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_citest(() => {
651cb0ef41Sopenharmony_ci  const ws = new WritableStream({});
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
681cb0ef41Sopenharmony_ci  writer.abort();
691cb0ef41Sopenharmony_ci  writer.releaseLock();
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  ws.getWriter();
721cb0ef41Sopenharmony_ci}, 'ws.getWriter() on an aborted WritableStream');
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_cipromise_test(() => {
751cb0ef41Sopenharmony_ci  const ws = new WritableStream({
761cb0ef41Sopenharmony_ci    start(c) {
771cb0ef41Sopenharmony_ci      c.error();
781cb0ef41Sopenharmony_ci    }
791cb0ef41Sopenharmony_ci  });
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
821cb0ef41Sopenharmony_ci  return writer.closed.then(
831cb0ef41Sopenharmony_ci    v => assert_unreached('writer.closed fulfilled unexpectedly with: ' + v),
841cb0ef41Sopenharmony_ci    () => {
851cb0ef41Sopenharmony_ci      writer.releaseLock();
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci      ws.getWriter();
881cb0ef41Sopenharmony_ci    }
891cb0ef41Sopenharmony_ci  );
901cb0ef41Sopenharmony_ci}, 'ws.getWriter() on an errored WritableStream');
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_cipromise_test(() => {
931cb0ef41Sopenharmony_ci  const ws = new WritableStream({});
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
961cb0ef41Sopenharmony_ci  writer.releaseLock();
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  return writer.closed.then(
991cb0ef41Sopenharmony_ci    v => assert_unreached('writer.closed fulfilled unexpectedly with: ' + v),
1001cb0ef41Sopenharmony_ci    closedRejection => {
1011cb0ef41Sopenharmony_ci      assert_equals(closedRejection.name, 'TypeError', 'closed promise should reject with a TypeError');
1021cb0ef41Sopenharmony_ci      return writer.ready.then(
1031cb0ef41Sopenharmony_ci        v => assert_unreached('writer.ready fulfilled unexpectedly with: ' + v),
1041cb0ef41Sopenharmony_ci        readyRejection => assert_equals(readyRejection, closedRejection,
1051cb0ef41Sopenharmony_ci          'ready promise should reject with the same error')
1061cb0ef41Sopenharmony_ci      );
1071cb0ef41Sopenharmony_ci    }
1081cb0ef41Sopenharmony_ci  );
1091cb0ef41Sopenharmony_ci}, 'closed and ready on a released writer');
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_cipromise_test(t => {
1121cb0ef41Sopenharmony_ci  let thisObject = null;
1131cb0ef41Sopenharmony_ci  // Calls to Sink methods after the first are implicitly ignored. Only the first value that is passed to the resolver
1141cb0ef41Sopenharmony_ci  // is used.
1151cb0ef41Sopenharmony_ci  class Sink {
1161cb0ef41Sopenharmony_ci    start() {
1171cb0ef41Sopenharmony_ci      // Called twice
1181cb0ef41Sopenharmony_ci      t.step(() => {
1191cb0ef41Sopenharmony_ci        assert_equals(this, thisObject, 'start should be called as a method');
1201cb0ef41Sopenharmony_ci      });
1211cb0ef41Sopenharmony_ci    }
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci    write() {
1241cb0ef41Sopenharmony_ci      t.step(() => {
1251cb0ef41Sopenharmony_ci        assert_equals(this, thisObject, 'write should be called as a method');
1261cb0ef41Sopenharmony_ci      });
1271cb0ef41Sopenharmony_ci    }
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci    close() {
1301cb0ef41Sopenharmony_ci      t.step(() => {
1311cb0ef41Sopenharmony_ci        assert_equals(this, thisObject, 'close should be called as a method');
1321cb0ef41Sopenharmony_ci      });
1331cb0ef41Sopenharmony_ci    }
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci    abort() {
1361cb0ef41Sopenharmony_ci      t.step(() => {
1371cb0ef41Sopenharmony_ci        assert_equals(this, thisObject, 'abort should be called as a method');
1381cb0ef41Sopenharmony_ci      });
1391cb0ef41Sopenharmony_ci    }
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  const theSink = new Sink();
1431cb0ef41Sopenharmony_ci  thisObject = theSink;
1441cb0ef41Sopenharmony_ci  const ws = new WritableStream(theSink);
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  writer.write('a');
1491cb0ef41Sopenharmony_ci  const closePromise = writer.close();
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  const ws2 = new WritableStream(theSink);
1521cb0ef41Sopenharmony_ci  const writer2 = ws2.getWriter();
1531cb0ef41Sopenharmony_ci  const abortPromise = writer2.abort();
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  return Promise.all([
1561cb0ef41Sopenharmony_ci    closePromise,
1571cb0ef41Sopenharmony_ci    abortPromise
1581cb0ef41Sopenharmony_ci  ]);
1591cb0ef41Sopenharmony_ci}, 'WritableStream should call underlying sink methods as methods');
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_cipromise_test(t => {
1621cb0ef41Sopenharmony_ci  function functionWithOverloads() {}
1631cb0ef41Sopenharmony_ci  functionWithOverloads.apply = t.unreached_func('apply() should not be called');
1641cb0ef41Sopenharmony_ci  functionWithOverloads.call = t.unreached_func('call() should not be called');
1651cb0ef41Sopenharmony_ci  const underlyingSink = {
1661cb0ef41Sopenharmony_ci    start: functionWithOverloads,
1671cb0ef41Sopenharmony_ci    write: functionWithOverloads,
1681cb0ef41Sopenharmony_ci    close: functionWithOverloads,
1691cb0ef41Sopenharmony_ci    abort: functionWithOverloads
1701cb0ef41Sopenharmony_ci  };
1711cb0ef41Sopenharmony_ci  // Test start(), write(), close().
1721cb0ef41Sopenharmony_ci  const ws1 = new WritableStream(underlyingSink);
1731cb0ef41Sopenharmony_ci  const writer1 = ws1.getWriter();
1741cb0ef41Sopenharmony_ci  writer1.write('a');
1751cb0ef41Sopenharmony_ci  writer1.close();
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  // Test abort().
1781cb0ef41Sopenharmony_ci  const abortError = new Error();
1791cb0ef41Sopenharmony_ci  abortError.name = 'abort error';
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  const ws2 = new WritableStream(underlyingSink);
1821cb0ef41Sopenharmony_ci  const writer2 = ws2.getWriter();
1831cb0ef41Sopenharmony_ci  writer2.abort(abortError);
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci  // Test abort() with a close underlying sink method present. (Historical; see
1861cb0ef41Sopenharmony_ci  // https://github.com/whatwg/streams/issues/620#issuecomment-263483953 for what used to be
1871cb0ef41Sopenharmony_ci  // tested here. But more coverage can't hurt.)
1881cb0ef41Sopenharmony_ci  const ws3 = new WritableStream({
1891cb0ef41Sopenharmony_ci    start: functionWithOverloads,
1901cb0ef41Sopenharmony_ci    write: functionWithOverloads,
1911cb0ef41Sopenharmony_ci    close: functionWithOverloads
1921cb0ef41Sopenharmony_ci  });
1931cb0ef41Sopenharmony_ci  const writer3 = ws3.getWriter();
1941cb0ef41Sopenharmony_ci  writer3.abort(abortError);
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  return writer1.closed
1971cb0ef41Sopenharmony_ci      .then(() => promise_rejects_exactly(t, abortError, writer2.closed, 'writer2.closed should be rejected'))
1981cb0ef41Sopenharmony_ci      .then(() => promise_rejects_exactly(t, abortError, writer3.closed, 'writer3.closed should be rejected'));
1991cb0ef41Sopenharmony_ci}, 'methods should not not have .apply() or .call() called');
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_cipromise_test(() => {
2021cb0ef41Sopenharmony_ci  const strategy = {
2031cb0ef41Sopenharmony_ci    size() {
2041cb0ef41Sopenharmony_ci      if (this !== undefined) {
2051cb0ef41Sopenharmony_ci        throw new Error('size called as a method');
2061cb0ef41Sopenharmony_ci      }
2071cb0ef41Sopenharmony_ci      return 1;
2081cb0ef41Sopenharmony_ci    }
2091cb0ef41Sopenharmony_ci  };
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci  const ws = new WritableStream({}, strategy);
2121cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
2131cb0ef41Sopenharmony_ci  return writer.write('a');
2141cb0ef41Sopenharmony_ci}, 'WritableStream\'s strategy.size should not be called as a method');
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_cipromise_test(() => {
2171cb0ef41Sopenharmony_ci  const ws = new WritableStream();
2181cb0ef41Sopenharmony_ci  const writer1 = ws.getWriter();
2191cb0ef41Sopenharmony_ci  assert_equals(undefined, writer1.releaseLock(), 'releaseLock() should return undefined');
2201cb0ef41Sopenharmony_ci  const writer2 = ws.getWriter();
2211cb0ef41Sopenharmony_ci  assert_equals(undefined, writer1.releaseLock(), 'no-op releaseLock() should return undefined');
2221cb0ef41Sopenharmony_ci  // Calling releaseLock() on writer1 should not interfere with writer2. If it did, then the ready promise would be
2231cb0ef41Sopenharmony_ci  // rejected.
2241cb0ef41Sopenharmony_ci  return writer2.ready;
2251cb0ef41Sopenharmony_ci}, 'redundant releaseLock() is no-op');
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_cipromise_test(() => {
2281cb0ef41Sopenharmony_ci  const events = [];
2291cb0ef41Sopenharmony_ci  const ws = new WritableStream();
2301cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
2311cb0ef41Sopenharmony_ci  return writer.ready.then(() => {
2321cb0ef41Sopenharmony_ci    // Force the ready promise back to a pending state.
2331cb0ef41Sopenharmony_ci    const writerPromise = writer.write('dummy');
2341cb0ef41Sopenharmony_ci    const readyPromise = writer.ready.catch(() => events.push('ready'));
2351cb0ef41Sopenharmony_ci    const closedPromise = writer.closed.catch(() => events.push('closed'));
2361cb0ef41Sopenharmony_ci    writer.releaseLock();
2371cb0ef41Sopenharmony_ci    return Promise.all([readyPromise, closedPromise]).then(() => {
2381cb0ef41Sopenharmony_ci      assert_array_equals(events, ['ready', 'closed'], 'ready promise should fire before closed promise');
2391cb0ef41Sopenharmony_ci      // Stop the writer promise hanging around after the test has finished.
2401cb0ef41Sopenharmony_ci      return Promise.all([
2411cb0ef41Sopenharmony_ci        writerPromise,
2421cb0ef41Sopenharmony_ci        ws.abort()
2431cb0ef41Sopenharmony_ci      ]);
2441cb0ef41Sopenharmony_ci    });
2451cb0ef41Sopenharmony_ci  });
2461cb0ef41Sopenharmony_ci}, 'ready promise should fire before closed on releaseLock');
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_citest(() => {
2491cb0ef41Sopenharmony_ci  class Subclass extends WritableStream {
2501cb0ef41Sopenharmony_ci    extraFunction() {
2511cb0ef41Sopenharmony_ci      return true;
2521cb0ef41Sopenharmony_ci    }
2531cb0ef41Sopenharmony_ci  }
2541cb0ef41Sopenharmony_ci  assert_equals(
2551cb0ef41Sopenharmony_ci      Object.getPrototypeOf(Subclass.prototype), WritableStream.prototype,
2561cb0ef41Sopenharmony_ci      'Subclass.prototype\'s prototype should be WritableStream.prototype');
2571cb0ef41Sopenharmony_ci  assert_equals(Object.getPrototypeOf(Subclass), WritableStream,
2581cb0ef41Sopenharmony_ci                'Subclass\'s prototype should be WritableStream');
2591cb0ef41Sopenharmony_ci  const sub = new Subclass();
2601cb0ef41Sopenharmony_ci  assert_true(sub instanceof WritableStream,
2611cb0ef41Sopenharmony_ci              'Subclass object should be an instance of WritableStream');
2621cb0ef41Sopenharmony_ci  assert_true(sub instanceof Subclass,
2631cb0ef41Sopenharmony_ci              'Subclass object should be an instance of Subclass');
2641cb0ef41Sopenharmony_ci  const lockedGetter = Object.getOwnPropertyDescriptor(
2651cb0ef41Sopenharmony_ci      WritableStream.prototype, 'locked').get;
2661cb0ef41Sopenharmony_ci  assert_equals(lockedGetter.call(sub), sub.locked,
2671cb0ef41Sopenharmony_ci                'Subclass object should pass brand check');
2681cb0ef41Sopenharmony_ci  assert_true(sub.extraFunction(),
2691cb0ef41Sopenharmony_ci              'extraFunction() should be present on Subclass object');
2701cb0ef41Sopenharmony_ci}, 'Subclassing WritableStream should work');
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_citest(() => {
2731cb0ef41Sopenharmony_ci  const ws = new WritableStream();
2741cb0ef41Sopenharmony_ci  assert_false(ws.locked, 'stream should not be locked');
2751cb0ef41Sopenharmony_ci  ws.getWriter();
2761cb0ef41Sopenharmony_ci  assert_true(ws.locked, 'stream should be locked');
2771cb0ef41Sopenharmony_ci}, 'the locked getter should return true if the stream has a writer');
278