• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// META: global=window,worker
2// META: script=../resources/test-utils.js
3// META: script=../resources/recording-streams.js
4'use strict';
5
6const error1 = { name: 'error1' };
7
8promise_test(() => {
9  let resolveStartPromise;
10  const ws = recordingWritableStream({
11    start() {
12      return new Promise(resolve => {
13        resolveStartPromise = resolve;
14      });
15    }
16  });
17
18  const writer = ws.getWriter();
19
20  assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
21  writer.write('a');
22  assert_equals(writer.desiredSize, 0, 'desiredSize should be 0 after writer.write()');
23
24  // Wait and verify that write isn't called.
25  return flushAsyncEvents()
26      .then(() => {
27        assert_array_equals(ws.events, [], 'write should not be called until start promise resolves');
28        resolveStartPromise();
29        return writer.ready;
30      })
31      .then(() => assert_array_equals(ws.events, ['write', 'a'],
32                                      'write should not be called until start promise resolves'));
33}, 'underlying sink\'s write should not be called until start finishes');
34
35promise_test(() => {
36  let resolveStartPromise;
37  const ws = recordingWritableStream({
38    start() {
39      return new Promise(resolve => {
40        resolveStartPromise = resolve;
41      });
42    }
43  });
44
45  const writer = ws.getWriter();
46
47  writer.close();
48  assert_equals(writer.desiredSize, 1, 'desiredSize should be 1');
49
50  // Wait and verify that write isn't called.
51  return flushAsyncEvents().then(() => {
52    assert_array_equals(ws.events, [], 'close should not be called until start promise resolves');
53    resolveStartPromise();
54    return writer.closed;
55  });
56}, 'underlying sink\'s close should not be called until start finishes');
57
58test(() => {
59  const passedError = new Error('horrible things');
60
61  let writeCalled = false;
62  let closeCalled = false;
63  assert_throws_exactly(passedError, () => {
64    // recordingWritableStream cannot be used here because the exception in the
65    // constructor prevents assigning the object to a variable.
66    new WritableStream({
67      start() {
68        throw passedError;
69      },
70      write() {
71        writeCalled = true;
72      },
73      close() {
74        closeCalled = true;
75      }
76    });
77  }, 'constructor should throw passedError');
78  assert_false(writeCalled, 'write should not be called');
79  assert_false(closeCalled, 'close should not be called');
80}, 'underlying sink\'s write or close should not be called if start throws');
81
82promise_test(() => {
83  const ws = recordingWritableStream({
84    start() {
85      return Promise.reject();
86    }
87  });
88
89  // Wait and verify that write or close aren't called.
90  return flushAsyncEvents()
91      .then(() => assert_array_equals(ws.events, [], 'write and close should not be called'));
92}, 'underlying sink\'s write or close should not be invoked if the promise returned by start is rejected');
93
94promise_test(t => {
95  const ws = new WritableStream({
96    start() {
97      return {
98        then(onFulfilled, onRejected) { onRejected(error1); }
99      };
100    }
101  });
102  return promise_rejects_exactly(t, error1, ws.getWriter().closed, 'closed promise should be rejected');
103}, 'returning a thenable from start() should work');
104
105promise_test(t => {
106  const ws = recordingWritableStream({
107    start(controller) {
108      controller.error(error1);
109    }
110  });
111  return promise_rejects_exactly(t, error1, ws.getWriter().write('a'), 'write() should reject with the error')
112      .then(() => {
113        assert_array_equals(ws.events, [], 'sink write() should not have been called');
114      });
115}, 'controller.error() during start should cause writes to fail');
116
117promise_test(t => {
118  let controller;
119  let resolveStart;
120  const ws = recordingWritableStream({
121    start(c) {
122      controller = c;
123      return new Promise(resolve => {
124        resolveStart = resolve;
125      });
126    }
127  });
128  const writer = ws.getWriter();
129  const writePromise = writer.write('a');
130  const closePromise = writer.close();
131  controller.error(error1);
132  resolveStart();
133  return Promise.all([
134    promise_rejects_exactly(t, error1, writePromise, 'write() should fail'),
135    promise_rejects_exactly(t, error1, closePromise, 'close() should fail')
136  ]).then(() => {
137    assert_array_equals(ws.events, [], 'sink write() and close() should not have been called');
138  });
139}, 'controller.error() during async start should cause existing writes to fail');
140
141promise_test(t => {
142  const events = [];
143  const promises = [];
144  function catchAndRecord(promise, name) {
145    promises.push(promise.then(t.unreached_func(`promise ${name} should not resolve`),
146                               () => {
147                                 events.push(name);
148                               }));
149  }
150  const ws = new WritableStream({
151    start() {
152      return Promise.reject();
153    }
154  }, { highWaterMark: 0 });
155  const writer = ws.getWriter();
156  catchAndRecord(writer.ready, 'ready');
157  catchAndRecord(writer.closed, 'closed');
158  catchAndRecord(writer.write(), 'write');
159  return Promise.all(promises)
160      .then(() => {
161        assert_array_equals(events, ['ready', 'write', 'closed'], 'promises should reject in standard order');
162      });
163}, 'when start() rejects, writer promises should reject in standard order');
164