| // META: script=../../constants.sub.js |
| // META: script=resources/url-constants.js |
| // META: script=/common/gc.js |
| // META: global=window,worker |
| // META: variant=?default |
| // META: variant=?wss |
| // META: variant=?wpt_flags=h2 |
| |
| 'use strict'; |
| |
| const GOODBYE_MESSAGE = 'Goodbye'; // Must match echo_exit_wsh.py |
| |
| // This message needs to be large enough that writing it cannot complete |
| // synchronously, and to fill up the TCP send buffer and any user agent internal |
| // send buffers so that the user agent has to receive the "Close" frame from the |
| // server before it can complete sending this message. |
| const BIG_MESSAGE_SIZE = 8 * 1024 * 1024; |
| |
| // Common setup used by two tests. Sends a "Goodbye" message to tell the server |
| // to close the WebSocket, and immediately afterwards a big message that cannot |
| // be completely sent before the connection closes. Waits for the "Goodbye" |
| // message to be sent and the connection to be closed before returning. `t` is |
| // the test object provided by promse_test. |
| async function sendGoodbyeThenBigMessage(t) { |
| const wss = new WebSocketStream(BASEURL + '/echo_exit'); |
| const { writable } = await wss.opened; |
| const writer = writable.getWriter(); |
| const bigMessage = new Uint8Array(BIG_MESSAGE_SIZE); |
| const goodbyePromise = writer.write(GOODBYE_MESSAGE); |
| const bigMessagePromise = writer.write(bigMessage); |
| await goodbyePromise; |
| // testharness.js doesn't know about WebSocketError yet. |
| await wss.closed.then( |
| t.unreached_func('closed promise should reject'), |
| e => assert_equals( |
| e.constructor, WebSocketError, |
| 'a WebSocketError should be thrown')); |
| return { writer, bigMessagePromise }; |
| } |
| |
| promise_test(async t => { |
| const { writer, bigMessagePromise } = await sendGoodbyeThenBigMessage(t); |
| await promise_rejects_dom( |
| t, 'InvalidStateError', bigMessagePromise, |
| 'write() should reject with an InvalidStateError'); |
| const invalidStateError = await bigMessagePromise.then( |
| t.unreached_func('write() promise should reject'), e => e); |
| await promise_rejects_exactly( |
| t, invalidStateError, writer.write('word'), |
| 'stream should be errored with same object'); |
| }, 'a write that was incomplete at close time should reject'); |
| |
| promise_test(async t => { |
| const { bigMessagePromise } = await sendGoodbyeThenBigMessage(t); |
| // For some reason 5 is the magic number that causes garbage collection to |
| // really really collect garbage. |
| for (let i = 0; i < 5; ++i) { |
| await garbageCollect(); |
| } |
| await promise_rejects_dom( |
| t, 'InvalidStateError', bigMessagePromise, |
| 'write() should reject with an InvalidStateError'); |
| }, 'garbage collection after close with a pending write promise should not ' + |
| 'crash'); |
| |
| promise_test(async t => { |
| const wss = new WebSocketStream(ECHOURL); |
| const { writable } = await wss.opened; |
| const writer = writable.getWriter(); |
| const cannotStringify = { toString() { return this; } }; |
| await promise_rejects_js( |
| t, TypeError, writer.write(cannotStringify), 'write() should reject'); |
| }, 'writing a value that cannot be stringified should cause a rejection'); |
| |
| promise_test(async t => { |
| const wss = new WebSocketStream(ECHOURL); |
| const { writable } = await wss.opened; |
| const writer = writable.getWriter(); |
| const buffer = new ArrayBuffer(1024, { maxByteLength: 65536 }); |
| await promise_rejects_js( |
| t, TypeError, writer.write(buffer), 'write() should reject'); |
| }, 'writing a resizable ArrayBuffer should be rejected'); |
| |
| promise_test(async t => { |
| const wss = new WebSocketStream(ECHOURL); |
| const { writable } = await wss.opened; |
| const writer = writable.getWriter(); |
| const memory = new WebAssembly.Memory({ |
| initial: 4096, |
| maximum: 65536, |
| shared: true, |
| }); |
| const view = new Uint8Array(memory.buffer); |
| await promise_rejects_js( |
| t, TypeError, writer.write(view), 'write() should reject'); |
| }, 'writing a view on a shared buffer should be rejected'); |