tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

writable-stream.html (5408B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <script src="resources/helpers.js"></script>
      6 <script src="../resources/test-utils.js"></script>
      7 <script src="../resources/recording-streams.js"></script>
      8 <script>
      9 'use strict';
     10 
     11 promise_test(t => {
     12  const orig = new WritableStream();
     13  const promise = new Promise(resolve => {
     14    addEventListener('message', t.step_func(evt => {
     15      const transferred = evt.data;
     16      assert_equals(transferred.constructor, WritableStream,
     17                    'transferred should be a WritableStream in this realm');
     18      assert_true(transferred instanceof WritableStream,
     19                  'instanceof check should pass');
     20 
     21      // Perform a brand-check on |transferred|.
     22      const writer = WritableStream.prototype.getWriter.call(transferred);
     23      resolve();
     24    }), {once: true});
     25  });
     26  postMessage(orig, '*', [orig]);
     27  assert_true(orig.locked, 'the original stream should be locked');
     28  return promise;
     29 }, 'window.postMessage should be able to transfer a WritableStream');
     30 
     31 test(() => {
     32  const ws = new WritableStream();
     33  const writer = ws.getWriter();
     34  assert_throws_dom('DataCloneError', () => postMessage(ws, '*', [ws]),
     35                    'postMessage should throw');
     36 }, 'a locked WritableStream should not be transferable');
     37 
     38 promise_test(t => {
     39  const {writable, readable} = new TransformStream();
     40  const promise = new Promise(resolve => {
     41    addEventListener('message', t.step_func(async evt => {
     42      const {writable, readable} = evt.data;
     43      const reader = readable.getReader();
     44      const writer = writable.getWriter();
     45      const writerPromises = Promise.all([
     46        writer.write('hi'),
     47        writer.close(),
     48      ]);
     49      const {value, done} = await reader.read();
     50      assert_false(done, 'we should not be done');
     51      assert_equals(value, 'hi', 'chunk should have been delivered');
     52      const readResult = await reader.read();
     53      assert_true(readResult.done, 'readable should be closed');
     54      await writerPromises;
     55      resolve();
     56    }), {once: true});
     57  });
     58  postMessage({writable, readable}, '*', [writable, readable]);
     59  return promise;
     60 }, 'window.postMessage should be able to transfer a {readable, writable} pair');
     61 
     62 function transfer(stream) {
     63  return new Promise(resolve => {
     64    addEventListener('message', evt => resolve(evt.data), { once: true });
     65    postMessage(stream, '*', [stream]);
     66  });
     67 }
     68 
     69 promise_test(async () => {
     70  const orig = new WritableStream(
     71    {}, new ByteLengthQueuingStrategy({ highWaterMark: 65536 }));
     72  const transferred = await transfer(orig);
     73  const writer = transferred.getWriter();
     74  assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
     75 }, 'desiredSize for a newly-transferred stream should be 1');
     76 
     77 promise_test(async () => {
     78  const orig = new WritableStream({
     79    write() {
     80      return new Promise(() => {});
     81    }
     82  });
     83  const transferred = await transfer(orig);
     84  const writer = transferred.getWriter();
     85  await writer.write('a');
     86  assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
     87 }, 'effective queue size of a transferred writable should be 2');
     88 
     89 promise_test(async () => {
     90  const [writeCalled, resolveWriteCalled] = makePromiseAndResolveFunc();
     91  let resolveWrite;
     92  const orig = new WritableStream({
     93    write() {
     94      resolveWriteCalled();
     95      return new Promise(resolve => {
     96        resolveWrite = resolve;
     97      });
     98    }
     99  });
    100  const transferred = await transfer(orig);
    101  const writer = transferred.getWriter();
    102  await writer.write('a');
    103  let writeDone = false;
    104  const writePromise = writer.write('b').then(() => {
    105    writeDone = true;
    106  });
    107  await writeCalled;
    108  assert_false(writeDone, 'second write should not have resolved yet');
    109  resolveWrite();
    110  await writePromise; // (makes sure this resolves)
    111 }, 'second write should wait for first underlying write to complete');
    112 
    113 async function transferredWritableStreamWithAbortPromise() {
    114  const [abortCalled, resolveAbortCalled] = makePromiseAndResolveFunc();
    115  const orig = recordingWritableStream({
    116    abort() {
    117      resolveAbortCalled();
    118    }
    119  });
    120  const transferred = await transfer(orig);
    121  return { orig, transferred, abortCalled };
    122 }
    123 
    124 promise_test(async t => {
    125  const { orig, transferred, abortCalled } = await transferredWritableStreamWithAbortPromise();
    126  transferred.abort('p');
    127  await abortCalled;
    128  assert_array_equals(orig.events, ['abort', 'p'],
    129                      'abort() should have been called');
    130 }, 'abort() should work');
    131 
    132 promise_test(async t => {
    133  const { orig, transferred, abortCalled } = await transferredWritableStreamWithAbortPromise();
    134  const writer = transferred.getWriter();
    135  // A WritableStream object cannot be cloned.
    136  await promise_rejects_dom(t, 'DataCloneError', writer.write(new WritableStream()),
    137                            'the write should reject');
    138  await promise_rejects_dom(t, 'DataCloneError', writer.closed,
    139                            'the stream should be errored');
    140  await abortCalled;
    141  assert_equals(orig.events.length, 2, 'abort should have been called');
    142  assert_equals(orig.events[0], 'abort', 'first event should be abort');
    143  assert_equals(orig.events[1].name, 'DataCloneError',
    144                'reason should be a DataCloneError');
    145 }, 'writing a unclonable object should error the stream');
    146 </script>