11cb0ef41Sopenharmony_ci<!DOCTYPE html>
21cb0ef41Sopenharmony_ci<meta charset="utf-8">
31cb0ef41Sopenharmony_ci<script src="/resources/testharness.js"></script>
41cb0ef41Sopenharmony_ci<script src="/resources/testharnessreport.js"></script>
51cb0ef41Sopenharmony_ci<script src="resources/helpers.js"></script>
61cb0ef41Sopenharmony_ci<script src="../resources/test-utils.js"></script>
71cb0ef41Sopenharmony_ci<script src="../resources/recording-streams.js"></script>
81cb0ef41Sopenharmony_ci<script>
91cb0ef41Sopenharmony_ci'use strict';
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_cipromise_test(t => {
121cb0ef41Sopenharmony_ci  const orig = new WritableStream();
131cb0ef41Sopenharmony_ci  const promise = new Promise(resolve => {
141cb0ef41Sopenharmony_ci    addEventListener('message', t.step_func(evt => {
151cb0ef41Sopenharmony_ci      const transferred = evt.data;
161cb0ef41Sopenharmony_ci      assert_equals(transferred.constructor, WritableStream,
171cb0ef41Sopenharmony_ci                    'transferred should be a WritableStream in this realm');
181cb0ef41Sopenharmony_ci      assert_true(transferred instanceof WritableStream,
191cb0ef41Sopenharmony_ci                  'instanceof check should pass');
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci      // Perform a brand-check on |transferred|.
221cb0ef41Sopenharmony_ci      const writer = WritableStream.prototype.getWriter.call(transferred);
231cb0ef41Sopenharmony_ci      resolve();
241cb0ef41Sopenharmony_ci    }), {once: true});
251cb0ef41Sopenharmony_ci  });
261cb0ef41Sopenharmony_ci  postMessage(orig, '*', [orig]);
271cb0ef41Sopenharmony_ci  assert_true(orig.locked, 'the original stream should be locked');
281cb0ef41Sopenharmony_ci  return promise;
291cb0ef41Sopenharmony_ci}, 'window.postMessage should be able to transfer a WritableStream');
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_citest(() => {
321cb0ef41Sopenharmony_ci  const ws = new WritableStream();
331cb0ef41Sopenharmony_ci  const writer = ws.getWriter();
341cb0ef41Sopenharmony_ci  assert_throws_dom('DataCloneError', () => postMessage(ws, '*', [ws]),
351cb0ef41Sopenharmony_ci                    'postMessage should throw');
361cb0ef41Sopenharmony_ci}, 'a locked WritableStream should not be transferable');
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cipromise_test(t => {
391cb0ef41Sopenharmony_ci  const {writable, readable} = new TransformStream();
401cb0ef41Sopenharmony_ci  const promise = new Promise(resolve => {
411cb0ef41Sopenharmony_ci    addEventListener('message', t.step_func(async evt => {
421cb0ef41Sopenharmony_ci      const {writable, readable} = evt.data;
431cb0ef41Sopenharmony_ci      const reader = readable.getReader();
441cb0ef41Sopenharmony_ci      const writer = writable.getWriter();
451cb0ef41Sopenharmony_ci      const writerPromises = Promise.all([
461cb0ef41Sopenharmony_ci        writer.write('hi'),
471cb0ef41Sopenharmony_ci        writer.close(),
481cb0ef41Sopenharmony_ci      ]);
491cb0ef41Sopenharmony_ci      const {value, done} = await reader.read();
501cb0ef41Sopenharmony_ci      assert_false(done, 'we should not be done');
511cb0ef41Sopenharmony_ci      assert_equals(value, 'hi', 'chunk should have been delivered');
521cb0ef41Sopenharmony_ci      const readResult = await reader.read();
531cb0ef41Sopenharmony_ci      assert_true(readResult.done, 'readable should be closed');
541cb0ef41Sopenharmony_ci      await writerPromises;
551cb0ef41Sopenharmony_ci      resolve();
561cb0ef41Sopenharmony_ci    }), {once: true});
571cb0ef41Sopenharmony_ci  });
581cb0ef41Sopenharmony_ci  postMessage({writable, readable}, '*', [writable, readable]);
591cb0ef41Sopenharmony_ci  return promise;
601cb0ef41Sopenharmony_ci}, 'window.postMessage should be able to transfer a {readable, writable} pair');
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_cifunction transfer(stream) {
631cb0ef41Sopenharmony_ci  return new Promise(resolve => {
641cb0ef41Sopenharmony_ci    addEventListener('message', evt => resolve(evt.data), { once: true });
651cb0ef41Sopenharmony_ci    postMessage(stream, '*', [stream]);
661cb0ef41Sopenharmony_ci  });
671cb0ef41Sopenharmony_ci}
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_cipromise_test(async () => {
701cb0ef41Sopenharmony_ci  const orig = new WritableStream(
711cb0ef41Sopenharmony_ci    {}, new ByteLengthQueuingStrategy({ highWaterMark: 65536 }));
721cb0ef41Sopenharmony_ci  const transferred = await transfer(orig);
731cb0ef41Sopenharmony_ci  const writer = transferred.getWriter();
741cb0ef41Sopenharmony_ci  assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
751cb0ef41Sopenharmony_ci}, 'desiredSize for a newly-transferred stream should be 1');
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_cipromise_test(async () => {
781cb0ef41Sopenharmony_ci  const orig = new WritableStream({
791cb0ef41Sopenharmony_ci    write() {
801cb0ef41Sopenharmony_ci      return new Promise(() => {});
811cb0ef41Sopenharmony_ci    }
821cb0ef41Sopenharmony_ci  });
831cb0ef41Sopenharmony_ci  const transferred = await transfer(orig);
841cb0ef41Sopenharmony_ci  const writer = transferred.getWriter();
851cb0ef41Sopenharmony_ci  await writer.write('a');
861cb0ef41Sopenharmony_ci  assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
871cb0ef41Sopenharmony_ci}, 'effective queue size of a transferred writable should be 2');
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_cipromise_test(async () => {
901cb0ef41Sopenharmony_ci  const [writeCalled, resolveWriteCalled] = makePromiseAndResolveFunc();
911cb0ef41Sopenharmony_ci  let resolveWrite;
921cb0ef41Sopenharmony_ci  const orig = new WritableStream({
931cb0ef41Sopenharmony_ci    write() {
941cb0ef41Sopenharmony_ci      resolveWriteCalled();
951cb0ef41Sopenharmony_ci      return new Promise(resolve => {
961cb0ef41Sopenharmony_ci        resolveWrite = resolve;
971cb0ef41Sopenharmony_ci      });
981cb0ef41Sopenharmony_ci    }
991cb0ef41Sopenharmony_ci  });
1001cb0ef41Sopenharmony_ci  const transferred = await transfer(orig);
1011cb0ef41Sopenharmony_ci  const writer = transferred.getWriter();
1021cb0ef41Sopenharmony_ci  await writer.write('a');
1031cb0ef41Sopenharmony_ci  let writeDone = false;
1041cb0ef41Sopenharmony_ci  const writePromise = writer.write('b').then(() => {
1051cb0ef41Sopenharmony_ci    writeDone = true;
1061cb0ef41Sopenharmony_ci  });
1071cb0ef41Sopenharmony_ci  await writeCalled;
1081cb0ef41Sopenharmony_ci  assert_false(writeDone, 'second write should not have resolved yet');
1091cb0ef41Sopenharmony_ci  resolveWrite();
1101cb0ef41Sopenharmony_ci  await writePromise; // (makes sure this resolves)
1111cb0ef41Sopenharmony_ci}, 'second write should wait for first underlying write to complete');
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ciasync function transferredWritableStreamWithAbortPromise() {
1141cb0ef41Sopenharmony_ci  const [abortCalled, resolveAbortCalled] = makePromiseAndResolveFunc();
1151cb0ef41Sopenharmony_ci  const orig = recordingWritableStream({
1161cb0ef41Sopenharmony_ci    abort() {
1171cb0ef41Sopenharmony_ci      resolveAbortCalled();
1181cb0ef41Sopenharmony_ci    }
1191cb0ef41Sopenharmony_ci  });
1201cb0ef41Sopenharmony_ci  const transferred = await transfer(orig);
1211cb0ef41Sopenharmony_ci  return { orig, transferred, abortCalled };
1221cb0ef41Sopenharmony_ci}
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_cipromise_test(async t => {
1251cb0ef41Sopenharmony_ci  const { orig, transferred, abortCalled } = await transferredWritableStreamWithAbortPromise();
1261cb0ef41Sopenharmony_ci  transferred.abort('p');
1271cb0ef41Sopenharmony_ci  await abortCalled;
1281cb0ef41Sopenharmony_ci  assert_array_equals(orig.events, ['abort', 'p'],
1291cb0ef41Sopenharmony_ci                      'abort() should have been called');
1301cb0ef41Sopenharmony_ci}, 'abort() should work');
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_cipromise_test(async t => {
1331cb0ef41Sopenharmony_ci  const { orig, transferred, abortCalled } = await transferredWritableStreamWithAbortPromise();
1341cb0ef41Sopenharmony_ci  const writer = transferred.getWriter();
1351cb0ef41Sopenharmony_ci  // A WritableStream object cannot be cloned.
1361cb0ef41Sopenharmony_ci  await promise_rejects_dom(t, 'DataCloneError', writer.write(new WritableStream()),
1371cb0ef41Sopenharmony_ci                            'the write should reject');
1381cb0ef41Sopenharmony_ci  await promise_rejects_dom(t, 'DataCloneError', writer.closed,
1391cb0ef41Sopenharmony_ci                            'the stream should be errored');
1401cb0ef41Sopenharmony_ci  await abortCalled;
1411cb0ef41Sopenharmony_ci  assert_equals(orig.events.length, 2, 'abort should have been called');
1421cb0ef41Sopenharmony_ci  assert_equals(orig.events[0], 'abort', 'first event should be abort');
1431cb0ef41Sopenharmony_ci  assert_equals(orig.events[1].name, 'DataCloneError',
1441cb0ef41Sopenharmony_ci                'reason should be a DataCloneError');
1451cb0ef41Sopenharmony_ci}, 'writing a unclonable object should error the stream');
1461cb0ef41Sopenharmony_ci</script>
147