| // META: global=worker,jsshell |
| // META: script=../resources/test-utils.js |
| // META: script=../resources/recording-streams.js |
| 'use strict'; |
| |
| const error1 = { name: 'error1' }; |
| |
| promise_test(() => { |
| let resolveStartPromise; |
| const ws = recordingWritableStream({ |
| start() { |
| return new Promise(resolve => { |
| resolveStartPromise = resolve; |
| }); |
| } |
| }); |
| |
| const writer = ws.getWriter(); |
| |
| assert_equals(writer.desiredSize, 1, 'desiredSize should be 1'); |
| writer.write('a'); |
| assert_equals(writer.desiredSize, 0, 'desiredSize should be 0 after writer.write()'); |
| |
| // Wait and verify that write isn't called. |
| return flushAsyncEvents() |
| .then(() => { |
| assert_array_equals(ws.events, [], 'write should not be called until start promise resolves'); |
| resolveStartPromise(); |
| return writer.ready; |
| }) |
| .then(() => assert_array_equals(ws.events, ['write', 'a'], |
| 'write should not be called until start promise resolves')); |
| }, 'underlying sink\'s write should not be called until start finishes'); |
| |
| promise_test(() => { |
| let resolveStartPromise; |
| const ws = recordingWritableStream({ |
| start() { |
| return new Promise(resolve => { |
| resolveStartPromise = resolve; |
| }); |
| } |
| }); |
| |
| const writer = ws.getWriter(); |
| |
| writer.close(); |
| assert_equals(writer.desiredSize, 1, 'desiredSize should be 1'); |
| |
| // Wait and verify that write isn't called. |
| return flushAsyncEvents().then(() => { |
| assert_array_equals(ws.events, [], 'close should not be called until start promise resolves'); |
| resolveStartPromise(); |
| return writer.closed; |
| }); |
| }, 'underlying sink\'s close should not be called until start finishes'); |
| |
| test(() => { |
| const passedError = new Error('horrible things'); |
| |
| let writeCalled = false; |
| let closeCalled = false; |
| assert_throws(passedError, () => { |
| // recordingWritableStream cannot be used here because the exception in the |
| // constructor prevents assigning the object to a variable. |
| new WritableStream({ |
| start() { |
| throw passedError; |
| }, |
| write() { |
| writeCalled = true; |
| }, |
| close() { |
| closeCalled = true; |
| } |
| }); |
| }, 'constructor should throw passedError'); |
| assert_false(writeCalled, 'write should not be called'); |
| assert_false(closeCalled, 'close should not be called'); |
| }, 'underlying sink\'s write or close should not be called if start throws'); |
| |
| promise_test(() => { |
| const ws = recordingWritableStream({ |
| start() { |
| return Promise.reject(); |
| } |
| }); |
| |
| // Wait and verify that write or close aren't called. |
| return flushAsyncEvents() |
| .then(() => assert_array_equals(ws.events, [], 'write and close should not be called')); |
| }, 'underlying sink\'s write or close should not be invoked if the promise returned by start is rejected'); |
| |
| promise_test(t => { |
| const ws = new WritableStream({ |
| start() { |
| return { |
| then(onFulfilled, onRejected) { onRejected(error1); } |
| }; |
| } |
| }); |
| return promise_rejects(t, error1, ws.getWriter().closed, 'closed promise should be rejected'); |
| }, 'returning a thenable from start() should work'); |
| |
| promise_test(t => { |
| const ws = recordingWritableStream({ |
| start(controller) { |
| controller.error(error1); |
| } |
| }); |
| return promise_rejects(t, error1, ws.getWriter().write('a'), 'write() should reject with the error') |
| .then(() => { |
| assert_array_equals(ws.events, [], 'sink write() should not have been called'); |
| }); |
| }, 'controller.error() during start should cause writes to fail'); |
| |
| promise_test(t => { |
| let controller; |
| let resolveStart; |
| const ws = recordingWritableStream({ |
| start(c) { |
| controller = c; |
| return new Promise(resolve => { |
| resolveStart = resolve; |
| }); |
| } |
| }); |
| const writer = ws.getWriter(); |
| const writePromise = writer.write('a'); |
| const closePromise = writer.close(); |
| controller.error(error1); |
| resolveStart(); |
| return Promise.all([ |
| promise_rejects(t, error1, writePromise, 'write() should fail'), |
| promise_rejects(t, error1, closePromise, 'close() should fail') |
| ]).then(() => { |
| assert_array_equals(ws.events, [], 'sink write() and close() should not have been called'); |
| }); |
| }, 'controller.error() during async start should cause existing writes to fail'); |
| |
| promise_test(t => { |
| const events = []; |
| const promises = []; |
| function catchAndRecord(promise, name) { |
| promises.push(promise.then(t.unreached_func(`promise ${name} should not resolve`), |
| () => { |
| events.push(name); |
| })); |
| } |
| const ws = new WritableStream({ |
| start() { |
| return Promise.reject(); |
| } |
| }, { highWaterMark: 0 }); |
| const writer = ws.getWriter(); |
| catchAndRecord(writer.ready, 'ready'); |
| catchAndRecord(writer.closed, 'closed'); |
| catchAndRecord(writer.write(), 'write'); |
| return Promise.all(promises) |
| .then(() => { |
| assert_array_equals(events, ['ready', 'write', 'closed'], 'promises should reject in standard order'); |
| }); |
| }, 'when start() rejects, writer promises should reject in standard order'); |