| <!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 () => { |
| let resolveWrite; |
| const orig = new WritableStream({ |
| write() { |
| return new Promise(resolve => { |
| resolveWrite = resolve; |
| }); |
| } |
| }); |
| const transferred = await transfer(orig); |
| const writer = transferred.getWriter(); |
| await writer.write('a'); |
| let writeDone = false; |
| writer.write('b').then(() => { |
| writeDone = true; |
| }); |
| await flushAsyncEvents(); |
| assert_false(writeDone, 'second write should not have resolved yet'); |
| resolveWrite(); |
| await delay(0); |
| assert_true(writeDone, 'second write should have resolved'); |
| }, 'second write should wait for first underlying write to complete'); |
| |
| promise_test(async t => { |
| const orig = recordingWritableStream(); |
| const transferred = await transfer(orig); |
| transferred.abort('p'); |
| await delay(0); |
| assert_array_equals(orig.events, ['abort', 'p'], |
| 'abort() should have been called'); |
| }, 'abort() should work'); |
| |
| promise_test(async t => { |
| const orig = recordingWritableStream(); |
| const transferred = await transfer(orig); |
| 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 delay(0); |
| 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> |