diff options
Diffstat (limited to 'testing/web-platform/tests/streams/transferable/writable-stream.html')
-rw-r--r-- | testing/web-platform/tests/streams/transferable/writable-stream.html | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/testing/web-platform/tests/streams/transferable/writable-stream.html b/testing/web-platform/tests/streams/transferable/writable-stream.html new file mode 100644 index 0000000000..7e25dad94d --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/writable-stream.html @@ -0,0 +1,146 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/helpers.js"></script> +<script src="../resources/test-utils.js"></script> +<script src="../resources/recording-streams.js"></script> +<script> +'use strict'; + +promise_test(t => { + const orig = new WritableStream(); + const promise = new Promise(resolve => { + addEventListener('message', t.step_func(evt => { + const transferred = evt.data; + assert_equals(transferred.constructor, WritableStream, + 'transferred should be a WritableStream in this realm'); + assert_true(transferred instanceof WritableStream, + 'instanceof check should pass'); + + // Perform a brand-check on |transferred|. + const writer = WritableStream.prototype.getWriter.call(transferred); + resolve(); + }), {once: true}); + }); + postMessage(orig, '*', [orig]); + assert_true(orig.locked, 'the original stream should be locked'); + return promise; +}, 'window.postMessage should be able to transfer a WritableStream'); + +test(() => { + const ws = new WritableStream(); + const writer = ws.getWriter(); + assert_throws_dom('DataCloneError', () => postMessage(ws, '*', [ws]), + 'postMessage should throw'); +}, 'a locked WritableStream should not be transferable'); + +promise_test(t => { + const {writable, readable} = new TransformStream(); + const promise = new Promise(resolve => { + addEventListener('message', t.step_func(async evt => { + const {writable, readable} = evt.data; + const reader = readable.getReader(); + const writer = writable.getWriter(); + const writerPromises = Promise.all([ + writer.write('hi'), + writer.close(), + ]); + const {value, done} = await reader.read(); + assert_false(done, 'we should not be done'); + assert_equals(value, 'hi', 'chunk should have been delivered'); + const readResult = await reader.read(); + assert_true(readResult.done, 'readable should be closed'); + await writerPromises; + resolve(); + }), {once: true}); + }); + postMessage({writable, readable}, '*', [writable, readable]); + return promise; +}, 'window.postMessage should be able to transfer a {readable, writable} pair'); + +function transfer(stream) { + return new Promise(resolve => { + addEventListener('message', evt => resolve(evt.data), { once: true }); + postMessage(stream, '*', [stream]); + }); +} + +promise_test(async () => { + const orig = new WritableStream( + {}, new ByteLengthQueuingStrategy({ highWaterMark: 65536 })); + const transferred = await transfer(orig); + const writer = transferred.getWriter(); + assert_equals(writer.desiredSize, 1, 'desiredSize should be 1'); +}, 'desiredSize for a newly-transferred stream should be 1'); + +promise_test(async () => { + const orig = new WritableStream({ + write() { + return new Promise(() => {}); + } + }); + const transferred = await transfer(orig); + const writer = transferred.getWriter(); + await writer.write('a'); + assert_equals(writer.desiredSize, 1, 'desiredSize should be 1'); +}, 'effective queue size of a transferred writable should be 2'); + +promise_test(async () => { + const [writeCalled, resolveWriteCalled] = makePromiseAndResolveFunc(); + let resolveWrite; + const orig = new WritableStream({ + write() { + resolveWriteCalled(); + return new Promise(resolve => { + resolveWrite = resolve; + }); + } + }); + const transferred = await transfer(orig); + const writer = transferred.getWriter(); + await writer.write('a'); + let writeDone = false; + const writePromise = writer.write('b').then(() => { + writeDone = true; + }); + await writeCalled; + assert_false(writeDone, 'second write should not have resolved yet'); + resolveWrite(); + await writePromise; // (makes sure this resolves) +}, 'second write should wait for first underlying write to complete'); + +async function transferredWritableStreamWithAbortPromise() { + const [abortCalled, resolveAbortCalled] = makePromiseAndResolveFunc(); + const orig = recordingWritableStream({ + abort() { + resolveAbortCalled(); + } + }); + const transferred = await transfer(orig); + return { orig, transferred, abortCalled }; +} + +promise_test(async t => { + const { orig, transferred, abortCalled } = await transferredWritableStreamWithAbortPromise(); + transferred.abort('p'); + await abortCalled; + assert_array_equals(orig.events, ['abort', 'p'], + 'abort() should have been called'); +}, 'abort() should work'); + +promise_test(async t => { + const { orig, transferred, abortCalled } = await transferredWritableStreamWithAbortPromise(); + const writer = transferred.getWriter(); + // A WritableStream object cannot be cloned. + await promise_rejects_dom(t, 'DataCloneError', writer.write(new WritableStream()), + 'the write should reject'); + await promise_rejects_dom(t, 'DataCloneError', writer.closed, + 'the stream should be errored'); + await abortCalled; + assert_equals(orig.events.length, 2, 'abort should have been called'); + assert_equals(orig.events[0], 'abort', 'first event should be abort'); + assert_equals(orig.events[1].name, 'DataCloneError', + 'reason should be a DataCloneError'); +}, 'writing a unclonable object should error the stream'); +</script> |