tor-browser

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

write.any.js (4411B)


      1 // META: script=../../constants.sub.js
      2 // META: script=resources/url-constants.js
      3 // META: script=/common/gc.js
      4 // META: global=window,worker
      5 // META: variant=?default
      6 // META: variant=?wss
      7 // META: variant=?wpt_flags=h2
      8 
      9 'use strict';
     10 
     11 const GOODBYE_MESSAGE = 'Goodbye';  // Must match echo_exit_wsh.py
     12 
     13 // This message needs to be large enough that writing it cannot complete
     14 // synchronously, and to fill up the TCP send buffer and any user agent internal
     15 // send buffers so that the user agent has to receive the "Close" frame from the
     16 // server before it can complete sending this message.
     17 const BIG_MESSAGE_SIZE = 8 * 1024 * 1024;
     18 
     19 // Common setup used by two tests. Sends a "Goodbye" message to tell the server
     20 // to close the WebSocket, and immediately afterwards a big message that cannot
     21 // be completely sent before the connection closes. Waits for the "Goodbye"
     22 // message to be sent and the connection to be closed before returning. `t` is
     23 // the test object provided by promse_test.
     24 async function sendGoodbyeThenBigMessage(t) {
     25  const wss = new WebSocketStream(BASEURL + '/echo_exit');
     26  const { writable } = await wss.opened;
     27  const writer = writable.getWriter();
     28  const bigMessage = new Uint8Array(BIG_MESSAGE_SIZE);
     29  const goodbyePromise = writer.write(GOODBYE_MESSAGE);
     30  const bigMessagePromise = writer.write(bigMessage);
     31  await goodbyePromise;
     32  // testharness.js doesn't know about WebSocketError yet.
     33  await wss.closed.then(
     34      t.unreached_func('closed promise should reject'),
     35      e => assert_equals(
     36          e.constructor, WebSocketError,
     37          'a WebSocketError should be thrown'));
     38  return { writer, bigMessagePromise };
     39 }
     40 
     41 promise_test(async t => {
     42  const { writer, bigMessagePromise } = await sendGoodbyeThenBigMessage(t);
     43  await promise_rejects_dom(
     44      t, 'InvalidStateError', bigMessagePromise,
     45      'write() should reject with an InvalidStateError');
     46  const invalidStateError = await bigMessagePromise.then(
     47      t.unreached_func('write() promise should reject'), e => e);
     48  await promise_rejects_exactly(
     49      t, invalidStateError, writer.write('word'),
     50      'stream should be errored with same object');
     51 }, 'a write that was incomplete at close time should reject');
     52 
     53 promise_test(async t => {
     54  const { bigMessagePromise } = await sendGoodbyeThenBigMessage(t);
     55  // For some reason 5 is the magic number that causes garbage collection to
     56  // really really collect garbage.
     57  for (let i = 0; i < 5; ++i) {
     58    await garbageCollect();
     59  }
     60  await promise_rejects_dom(
     61      t, 'InvalidStateError', bigMessagePromise,
     62      'write() should reject with an InvalidStateError');
     63 }, 'garbage collection after close with a pending write promise should not ' +
     64       'crash');
     65 
     66 promise_test(async t => {
     67  const wss = new WebSocketStream(ECHOURL);
     68  const { writable } = await wss.opened;
     69  const writer = writable.getWriter();
     70  const cannotStringify = { toString() { return this; } };
     71  await promise_rejects_js(
     72      t, TypeError, writer.write(cannotStringify), 'write() should reject');
     73 }, 'writing a value that cannot be stringified should cause a rejection');
     74 
     75 promise_test(async t => {
     76  const wss = new WebSocketStream(ECHOURL);
     77  const { writable } = await wss.opened;
     78  const writer = writable.getWriter();
     79  const buffer = new ArrayBuffer(1024, { maxByteLength: 65536 });
     80  await promise_rejects_js(
     81      t, TypeError, writer.write(buffer), 'write() should reject');
     82 }, 'writing a resizable ArrayBuffer should be rejected');
     83 
     84 promise_test(async t => {
     85  const wss = new WebSocketStream(ECHOURL);
     86  const { writable } = await wss.opened;
     87  const writer = writable.getWriter();
     88  const memory = new WebAssembly.Memory({
     89    initial: 4096,
     90    maximum: 65536,
     91    shared: true,
     92  });
     93  const view = new Uint8Array(memory.buffer);
     94  await promise_rejects_js(
     95      t, TypeError, writer.write(view), 'write() should reject');
     96 }, 'writing a view on a shared buffer should be rejected');
     97 
     98 promise_test(async () => {
     99  let wss = new WebSocketStream(ECHOURL);
    100  let { writable } = await wss.opened;
    101  let writer = writable.getWriter();
    102  wss = writable = null;
    103  const promises = [];
    104  for (let i = 0; i < 20; ++i) {
    105    promises.push(writer.write(new Uint8Array(100000)));
    106  }
    107  writer = null;
    108  for (let i = 0; i < 5; ++i) {
    109    await garbageCollect();
    110  }
    111 }, 'Garbage collecting a WebSocket stream doesn\'t crash while write promise is pending');