OLD | NEW |
| (Empty) |
1 'use strict'; | |
2 | |
3 if (self.importScripts) { | |
4 self.importScripts('../resources/rs-utils.js'); | |
5 self.importScripts('/resources/testharness.js'); | |
6 } | |
7 | |
8 test(() => { | |
9 | |
10 const rs = new ReadableStream(); | |
11 const result = rs.tee(); | |
12 | |
13 assert_true(Array.isArray(result), 'return value should be an array'); | |
14 assert_equals(result.length, 2, 'array should have length 2'); | |
15 assert_equals(result[0].constructor, ReadableStream, '0th element should be a
ReadableStream'); | |
16 assert_equals(result[1].constructor, ReadableStream, '1st element should be a
ReadableStream'); | |
17 | |
18 }, 'ReadableStream teeing: rs.tee() returns an array of two ReadableStreams'); | |
19 | |
20 promise_test(t => { | |
21 | |
22 const rs = new ReadableStream({ | |
23 start(c) { | |
24 c.enqueue('a'); | |
25 c.enqueue('b'); | |
26 c.close(); | |
27 } | |
28 }); | |
29 | |
30 const branch = rs.tee(); | |
31 const branch1 = branch[0]; | |
32 const branch2 = branch[1]; | |
33 const reader1 = branch1.getReader(); | |
34 const reader2 = branch2.getReader(); | |
35 | |
36 reader2.closed.then(t.unreached_func('branch2 should not be closed')); | |
37 | |
38 return Promise.all([ | |
39 reader1.closed, | |
40 reader1.read().then(r => { | |
41 assert_object_equals(r, { value: 'a', done: false }, 'first chunk from bra
nch1 should be correct'); | |
42 }), | |
43 reader1.read().then(r => { | |
44 assert_object_equals(r, { value: 'b', done: false }, 'second chunk from br
anch1 should be correct'); | |
45 }), | |
46 reader1.read().then(r => { | |
47 assert_object_equals(r, { value: undefined, done: true }, 'third read() fr
om branch1 should be done'); | |
48 }), | |
49 reader2.read().then(r => { | |
50 assert_object_equals(r, { value: 'a', done: false }, 'first chunk from bra
nch2 should be correct'); | |
51 }) | |
52 ]); | |
53 | |
54 }, 'ReadableStream teeing: should be able to read one branch to the end without
affecting the other'); | |
55 | |
56 promise_test(() => { | |
57 | |
58 const theObject = { the: 'test object' }; | |
59 const rs = new ReadableStream({ | |
60 start(c) { | |
61 c.enqueue(theObject); | |
62 } | |
63 }); | |
64 | |
65 const branch = rs.tee(); | |
66 const branch1 = branch[0]; | |
67 const branch2 = branch[1]; | |
68 const reader1 = branch1.getReader(); | |
69 const reader2 = branch2.getReader(); | |
70 | |
71 return Promise.all([reader1.read(), reader2.read()]).then(values => { | |
72 assert_object_equals(values[0], values[1], 'the values should be equal'); | |
73 }); | |
74 | |
75 }, 'ReadableStream teeing: values should be equal across each branch'); | |
76 | |
77 promise_test(t => { | |
78 | |
79 const theError = { name: 'boo!' }; | |
80 const rs = new ReadableStream({ | |
81 start(c) { | |
82 c.enqueue('a'); | |
83 c.enqueue('b'); | |
84 }, | |
85 pull() { | |
86 throw theError; | |
87 } | |
88 }); | |
89 | |
90 const branches = rs.tee(); | |
91 const reader1 = branches[0].getReader(); | |
92 const reader2 = branches[1].getReader(); | |
93 | |
94 reader1.label = 'reader1'; | |
95 reader2.label = 'reader2'; | |
96 | |
97 return Promise.all([ | |
98 promise_rejects(t, theError, reader1.closed), | |
99 promise_rejects(t, theError, reader2.closed), | |
100 reader1.read().then(r => { | |
101 assert_object_equals(r, { value: 'a', done: false }, 'should be able to re
ad the first chunk in branch1'); | |
102 }), | |
103 reader1.read().then(r => { | |
104 assert_object_equals(r, { value: 'b', done: false }, 'should be able to re
ad the second chunk in branch1'); | |
105 | |
106 return promise_rejects(t, theError, reader2.read()); | |
107 }) | |
108 .then(() => promise_rejects(t, theError, reader1.read())) | |
109 ]); | |
110 | |
111 }, 'ReadableStream teeing: errors in the source should propagate to both branche
s'); | |
112 | |
113 promise_test(() => { | |
114 | |
115 const rs = new ReadableStream({ | |
116 start(c) { | |
117 c.enqueue('a'); | |
118 c.enqueue('b'); | |
119 c.close(); | |
120 } | |
121 }); | |
122 | |
123 const branches = rs.tee(); | |
124 const branch1 = branches[0]; | |
125 const branch2 = branches[1]; | |
126 branch1.cancel(); | |
127 | |
128 return Promise.all([ | |
129 readableStreamToArray(branch1).then(chunks => { | |
130 assert_array_equals(chunks, [], 'branch1 should have no chunks'); | |
131 }), | |
132 readableStreamToArray(branch2).then(chunks => { | |
133 assert_array_equals(chunks, ['a', 'b'], 'branch2 should have two chunks'); | |
134 }) | |
135 ]); | |
136 | |
137 }, 'ReadableStream teeing: canceling branch1 should not impact branch2'); | |
138 | |
139 promise_test(() => { | |
140 | |
141 const rs = new ReadableStream({ | |
142 start(c) { | |
143 c.enqueue('a'); | |
144 c.enqueue('b'); | |
145 c.close(); | |
146 } | |
147 }); | |
148 | |
149 const branches = rs.tee(); | |
150 const branch1 = branches[0]; | |
151 const branch2 = branches[1]; | |
152 branch2.cancel(); | |
153 | |
154 return Promise.all([ | |
155 readableStreamToArray(branch1).then(chunks => { | |
156 assert_array_equals(chunks, ['a', 'b'], 'branch1 should have two chunks'); | |
157 }), | |
158 readableStreamToArray(branch2).then(chunks => { | |
159 assert_array_equals(chunks, [], 'branch2 should have no chunks'); | |
160 }) | |
161 ]); | |
162 | |
163 }, 'ReadableStream teeing: canceling branch2 should not impact branch2'); | |
164 | |
165 promise_test(() => { | |
166 | |
167 const reason1 = new Error('We\'re wanted men.'); | |
168 const reason2 = new Error('I have the death sentence on twelve systems.'); | |
169 | |
170 let resolve; | |
171 const promise = new Promise(r => resolve = r); | |
172 const rs = new ReadableStream({ | |
173 cancel(reason) { | |
174 assert_array_equals(reason, [reason1, reason2], | |
175 'the cancel reason should be an array containing those
from the branches'); | |
176 resolve(); | |
177 } | |
178 }); | |
179 | |
180 const branch = rs.tee(); | |
181 const branch1 = branch[0]; | |
182 const branch2 = branch[1]; | |
183 branch1.cancel(reason1); | |
184 branch2.cancel(reason2); | |
185 | |
186 return promise; | |
187 | |
188 }, 'ReadableStream teeing: canceling both branches should aggregate the cancel r
easons into an array'); | |
189 | |
190 promise_test(t => { | |
191 | |
192 const theError = { name: 'I\'ll be careful.' }; | |
193 const rs = new ReadableStream({ | |
194 cancel() { | |
195 throw theError; | |
196 } | |
197 }); | |
198 | |
199 const branch = rs.tee(); | |
200 const branch1 = branch[0]; | |
201 const branch2 = branch[1]; | |
202 | |
203 return Promise.all([ | |
204 promise_rejects(t, theError, branch1.cancel()), | |
205 promise_rejects(t, theError, branch2.cancel()) | |
206 ]); | |
207 | |
208 }, 'ReadableStream teeing: failing to cancel the original stream should cause ca
ncel() to reject on branches'); | |
209 | |
210 promise_test(() => { | |
211 | |
212 let controller; | |
213 const rs = new ReadableStream({ | |
214 start(c) { | |
215 controller = c; | |
216 } | |
217 }); | |
218 | |
219 const branches = rs.tee(); | |
220 const reader1 = branches[0].getReader(); | |
221 const reader2 = branches[1].getReader(); | |
222 | |
223 const promise = Promise.all([reader1.closed, reader2.closed]); | |
224 | |
225 controller.close(); | |
226 return promise; | |
227 | |
228 }, 'ReadableStream teeing: closing the original should immediately close the bra
nches'); | |
229 | |
230 promise_test(t => { | |
231 | |
232 let controller; | |
233 const rs = new ReadableStream({ | |
234 start(c) { | |
235 controller = c; | |
236 } | |
237 }); | |
238 | |
239 const branches = rs.tee(); | |
240 const reader1 = branches[0].getReader(); | |
241 const reader2 = branches[1].getReader(); | |
242 | |
243 const theError = { name: 'boo!' }; | |
244 const promise = Promise.all([ | |
245 promise_rejects(t, theError, reader1.closed), | |
246 promise_rejects(t, theError, reader2.closed) | |
247 ]); | |
248 | |
249 controller.error(theError); | |
250 return promise; | |
251 | |
252 }, 'ReadableStream teeing: erroring the original should immediately error the br
anches'); | |
253 | |
254 done(); | |
OLD | NEW |