• 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
6// These tests exercise the pathological case of calling WritableStream* methods from within the strategy.size()
7// callback. This is not something any real code should ever do. Failures here indicate subtle deviations from the
8// standard that may affect real, non-pathological code.
9
10const error1 = { name: 'error1' };
11
12promise_test(() => {
13  let writer;
14  const strategy = {
15    size(chunk) {
16      if (chunk > 0) {
17        writer.write(chunk - 1);
18      }
19      return chunk;
20    }
21  };
22
23  const ws = recordingWritableStream({}, strategy);
24  writer = ws.getWriter();
25  return writer.write(2)
26      .then(() => {
27        assert_array_equals(ws.events, ['write', 0, 'write', 1, 'write', 2], 'writes should appear in order');
28      });
29}, 'writes should be written in the standard order');
30
31promise_test(() => {
32  let writer;
33  const events = [];
34  const strategy = {
35    size(chunk) {
36      events.push('size', chunk);
37      if (chunk > 0) {
38        writer.write(chunk - 1)
39            .then(() => events.push('writer.write done', chunk - 1));
40      }
41      return chunk;
42    }
43  };
44  const ws = new WritableStream({
45    write(chunk) {
46      events.push('sink.write', chunk);
47    }
48  }, strategy);
49  writer = ws.getWriter();
50  return writer.write(2)
51      .then(() => events.push('writer.write done', 2))
52      .then(() => flushAsyncEvents())
53      .then(() => {
54        assert_array_equals(events, ['size', 2, 'size', 1, 'size', 0,
55                                     'sink.write', 0, 'sink.write', 1, 'writer.write done', 0,
56                                     'sink.write', 2, 'writer.write done', 1,
57                                     'writer.write done', 2],
58                            'events should happen in standard order');
59      });
60}, 'writer.write() promises should resolve in the standard order');
61
62promise_test(t => {
63  let controller;
64  const strategy = {
65    size() {
66      controller.error(error1);
67      return 1;
68    }
69  };
70  const ws = recordingWritableStream({
71    start(c) {
72      controller = c;
73    }
74  }, strategy);
75  const resolved = [];
76  const writer = ws.getWriter();
77  const readyPromise1 = writer.ready.then(() => resolved.push('ready1'));
78  const writePromise = promise_rejects_exactly(t, error1, writer.write(),
79                                               'write() should reject with the error')
80                                                   .then(() => resolved.push('write'));
81  const readyPromise2 = promise_rejects_exactly(t, error1, writer.ready, 'ready should reject with error1')
82      .then(() => resolved.push('ready2'));
83  const closedPromise = promise_rejects_exactly(t, error1, writer.closed, 'closed should reject with error1')
84      .then(() => resolved.push('closed'));
85  return Promise.all([readyPromise1, writePromise, readyPromise2, closedPromise])
86      .then(() => {
87        assert_array_equals(resolved, ['ready1', 'write', 'ready2', 'closed'],
88                            'promises should resolve in standard order');
89        assert_array_equals(ws.events, [], 'underlying sink write should not be called');
90      });
91}, 'controller.error() should work when called from within strategy.size()');
92
93promise_test(t => {
94  let writer;
95  const strategy = {
96    size() {
97      writer.close();
98      return 1;
99    }
100  };
101
102  const ws = recordingWritableStream({}, strategy);
103  writer = ws.getWriter();
104  return promise_rejects_js(t, TypeError, writer.write('a'), 'write() promise should reject')
105      .then(() => {
106        assert_array_equals(ws.events, ['close'], 'sink.write() should not be called');
107      });
108}, 'close() should work when called from within strategy.size()');
109
110promise_test(t => {
111  let writer;
112  const strategy = {
113    size() {
114      writer.abort(error1);
115      return 1;
116    }
117  };
118
119  const ws = recordingWritableStream({}, strategy);
120  writer = ws.getWriter();
121  return promise_rejects_exactly(t, error1, writer.write('a'), 'write() promise should reject')
122      .then(() => {
123        assert_array_equals(ws.events, ['abort', error1], 'sink.write() should not be called');
124      });
125}, 'abort() should work when called from within strategy.size()');
126
127promise_test(t => {
128  let writer;
129  const strategy = {
130    size() {
131      writer.releaseLock();
132      return 1;
133    }
134  };
135
136  const ws = recordingWritableStream({}, strategy);
137  writer = ws.getWriter();
138  const writePromise = promise_rejects_js(t, TypeError, writer.write('a'), 'write() promise should reject');
139  const readyPromise = promise_rejects_js(t, TypeError, writer.ready, 'ready promise should reject');
140  const closedPromise = promise_rejects_js(t, TypeError, writer.closed, 'closed promise should reject');
141  return Promise.all([writePromise, readyPromise, closedPromise])
142      .then(() => {
143        assert_array_equals(ws.events, [], 'sink.write() should not be called');
144      });
145}, 'releaseLock() should abort the write() when called within strategy.size()');
146
147promise_test(t => {
148  let writer1;
149  let ws;
150  let writePromise2;
151  let closePromise;
152  let closedPromise2;
153  const strategy = {
154    size(chunk) {
155      if (chunk > 0) {
156        writer1.releaseLock();
157        const writer2 = ws.getWriter();
158        writePromise2 = writer2.write(0);
159        closePromise = writer2.close();
160        closedPromise2 = writer2.closed;
161      }
162      return 1;
163    }
164  };
165  ws = recordingWritableStream({}, strategy);
166  writer1 = ws.getWriter();
167  const writePromise1 = promise_rejects_js(t, TypeError, writer1.write(1), 'write() promise should reject');
168  const readyPromise = promise_rejects_js(t, TypeError, writer1.ready, 'ready promise should reject');
169  const closedPromise1 = promise_rejects_js(t, TypeError, writer1.closed, 'closed promise should reject');
170  return Promise.all([writePromise1, readyPromise, closedPromise1, writePromise2, closePromise, closedPromise2])
171      .then(() => {
172        assert_array_equals(ws.events, ['write', 0, 'close'], 'sink.write() should only be called once');
173      });
174}, 'original reader should error when new reader is created within strategy.size()');
175