summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/streams/transferable/writable-stream.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/streams/transferable/writable-stream.html')
-rw-r--r--testing/web-platform/tests/streams/transferable/writable-stream.html146
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>