Plugin create can end up destroying its renderer.
[WebKit-https.git] / LayoutTests / streams / reference-implementation / readable-stream-tee.html
1 <!DOCTYPE html>
2 <script src='../../resources/testharness.js'></script>
3 <script src='../../resources/testharnessreport.js'></script>
4 <script src='resources/streams-utils.js'></script>
5 <script>
6 test(function() {
7     var rs = new ReadableStream();
8
9     var result = rs.tee();
10
11     assert_true(Array.isArray(result), 'return value should be an array');
12     assert_equals(result.length, 2, 'array should have length 2');
13     assert_equals(result[0].constructor, ReadableStream, '0th element should be a ReadableStream');
14     assert_equals(result[1].constructor, ReadableStream, '1st element should be a ReadableStream');
15 }, 'ReadableStream teeing: rs.tee() returns an array of two ReadableStreams');
16
17 var test1 = async_test('ReadableStream teeing: should be able to read one branch to the end without affecting the other');
18 test1.step(function() {
19     var closedCalled = false;
20     var readCalls = 0;
21     const rs = new ReadableStream({
22         start: function(c) {
23             c.enqueue('a');
24             c.enqueue('b');
25             c.close();
26         }
27     });
28
29     var branch = rs.tee();
30     var branch1 = branch[0];
31     var branch2 = branch[1];
32     var reader1 = branch1.getReader();
33     var reader2 = branch2.getReader();
34
35     reader1.closed.then(test1.step_func(function() {
36         closedCalled = true;
37     })).catch(test1.step_func(function(e) { assert_unreached(e); }));
38     reader2.closed.then(test1.step_func(function() { assert_unreached('branch2 should not be closed'); }));
39
40     reader1.read().then(test1.step_func(function(r) {
41         assert_object_equals(r, { value: 'a', done: false }, 'first chunk from branch1 should be correct');
42         ++readCalls;
43     }));
44     reader1.read().then(test1.step_func(function(r) {
45         assert_object_equals(r, { value: 'b', done: false }, 'second chunk from branch1 should be correct');
46         ++readCalls;
47     }));
48     reader1.read().then(test1.step_func(function(r) {
49         assert_object_equals(r, { value: undefined, done: true }, 'third read() from branch1 should be done');
50         assert_true(closedCalled);
51         assert_equals(++readCalls, 4);
52         test1.done();
53     }));
54
55     reader2.read().then(test1.step_func(function(r) {
56         assert_object_equals(r, { value: 'a', done: false }, 'first chunk from branch2 should be correct');
57         ++readCalls;
58     }));
59 });
60
61 var test2 = async_test('ReadableStream teeing: values should be equal across each branch');
62 test2.step(function() {
63     var theObject = { the: 'test object' };
64     var rs = new ReadableStream({
65         start: function(c) {
66             c.enqueue(theObject);
67         }
68     });
69
70     var branch = rs.tee();
71     var branch1 = branch[0];
72     var branch2 = branch[1];
73     var reader1 = branch1.getReader();
74     var reader2 = branch2.getReader();
75
76     Promise.all([reader1.read(), reader2.read()]).then(test2.step_func(function(values) {
77         assert_object_equals(values[0], values[1], 'the values should be equal');
78         test2.done();
79     }));
80 });
81
82 var test3 = async_test('ReadableStream teeing: errors in the source should propagate to both branches');
83 test3.step(function() {
84     var closedRejects = 0;
85     var readCalls = 0;
86     var readRejects = 0;
87     var theError = new Error('boo!');
88     var rs = new ReadableStream({
89         start: function(c) {
90             c.enqueue('a');
91             c.enqueue('b');
92         },
93         pull: function() {
94             throw theError;
95         }
96     });
97
98     var branch = rs.tee();
99     var branch1 = branch[0];
100     var branch2 = branch[1];
101     var reader1 = branch1.getReader();
102     var reader2 = branch2.getReader();
103
104     reader1.label = 'reader1';
105     reader2.label = 'reader2';
106
107     reader1.closed.catch(test3.step_func(function(e) {
108         ++closedRejects;
109         assert_equals(e, theError, 'branch1 closed promise should reject with the error');
110     }));
111     reader2.closed.catch(test3.step_func(function(e) {
112         ++closedRejects;
113         assert_equals(e, theError, 'branch2 closed promise should reject with the error');
114     }));
115
116     reader1.read().then(test3.step_func(function(r) {
117         ++readCalls;
118         assert_object_equals(r, { value: 'a', done: false }, 'should be able to read the first chunk in branch1');
119     }));
120
121     reader1.read().then(test3.step_func(function(r) {
122         ++readCalls;
123         assert_object_equals(r, { value: 'b', done: false }, 'should be able to read the second chunk in branch1');
124
125         return reader2.read().then(
126             test3.step_func(function() { assert_unreached('once the root stream has errored, you should not be able to read from branch2'); }),
127             test3.step_func(function(e) {
128                 ++readRejects;
129                 assert_equals(e, theError, 'branch2 read() promise should reject with the error');
130             }));
131     })).then(test3.step_func(function() {
132         return reader1.read().then(
133             test3.step_func(function() { assert_unreached('once the root stream has errored, you should not be able to read from branch1 either'); }),
134             test3.step_func(function(e) {
135                 assert_equals(closedRejects, 2);
136                 assert_equals(readCalls, 2);
137                 assert_equals(++readRejects, 2);
138                 assert_equals(e, theError, 'branch1 read() promise should reject with the error');
139                 test3.done();
140             })
141         );
142     })).catch(test3.step_func(function(e) { assert_unreached(e); }));
143 });
144
145 var test4 = async_test('ReadableStream teeing: canceling branch1 should not impact branch2');
146 test4.step(function() {
147     var branch1Read = false;
148     var rs = new ReadableStream({
149         start: function(c) {
150             c.enqueue('a');
151             c.enqueue('b');
152             c.close();
153         }
154     });
155
156     var branch = rs.tee();
157     var branch1 = branch[0];
158     var branch2 = branch[1];
159     branch1.cancel();
160
161     readableStreamToArray(branch1).then(test4.step_func(function(chunks) {
162         assert_array_equals(chunks, [], 'branch1 should have no chunks');
163         branch1Read = true;
164     }));
165                                                        
166     readableStreamToArray(branch2).then(test4.step_func(function(chunks) {
167         assert_array_equals(chunks, ['a', 'b'], 'branch2 should have two chunks');
168         assert_true(branch1Read);
169         test4.done();
170     }));
171 });
172
173 var test5 = async_test('ReadableStream teeing: canceling branch2 should not impact branch1');
174 test5.step(function() {
175     var branch2Read = false;
176     var rs = new ReadableStream({
177         start: function(c) {
178             c.enqueue('a');
179             c.enqueue('b');
180             c.close();
181         }
182     });
183
184     var branch = rs.tee();
185     var branch1 = branch[0];
186     var branch2 = branch[1];
187     branch2.cancel();
188
189     readableStreamToArray(branch1).then(test5.step_func(function(chunks) {
190         assert_array_equals(chunks, ['a', 'b'], 'branch1 should have two chunks');
191         assert_true(branch2Read);
192         test5.done();
193     }));
194     readableStreamToArray(branch2).then(test5.step_func(function(chunks) {
195         assert_array_equals(chunks, [], 'branch2 should have no chunks');
196         branch2Read = true;
197     }));
198 });
199
200 var test6 = async_test('ReadableStream teeing: canceling both branches should aggregate the cancel reasons into an array');
201 test6.step(function() {
202     var reason1 = new Error('We\'re wanted men.');
203     var reason2 = new Error('I have the death sentence on twelve systems.');
204
205     var rs = new ReadableStream({
206         cancel: function(reason) {
207             assert_array_equals(reason, [reason1, reason2], 'the cancel reason should be an array containing those from the branches');
208             test6.done();
209         }
210     });
211
212     var branch = rs.tee();
213     var branch1 = branch[0];
214     var branch2 = branch[1];
215     branch1.cancel(reason1);
216     branch2.cancel(reason2);
217 });
218
219 var test7 = async_test('ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches');
220 test7.step(function() {
221     var cancel1Rejected = false;
222     var theError = new Error('I\'ll be careful.');
223     var rs = new ReadableStream({
224         cancel: function() {
225             throw theError;
226         }
227     });
228
229     var branch = rs.tee();
230     var branch1 = branch[0];
231     var branch2 = branch[1];
232     branch1.cancel().catch(test7.step_func(function(e) {
233         assert_equals(e, theError, 'branch1.cancel() should reject with the error');
234         cancel1Rejected = true;
235     }));
236     branch2.cancel().catch(test7.step_func(function(e) {
237         assert_equals(e, theError, 'branch2.cancel() should reject with the error');
238         assert_true(cancel1Rejected);
239         test7.done();
240     }));
241 });
242
243 var test8 = async_test('ReadableStream teeing: closing the original should immediately close the branches');
244 test8.step(function() {
245     var reader1Closed = false;
246     var controller;
247     var rs = new ReadableStream({
248         start: function(c) {
249             controller = c;
250         }
251     });
252
253     var branch = rs.tee();
254     var branch1 = branch[0];
255     var branch2 = branch[1];
256     var reader1 = branch1.getReader();
257     var reader2 = branch2.getReader();
258
259     reader1.closed.then(test8.step_func(function() {
260         reader1Closed = true; //branch1 should be closed
261     })).catch(test8.step_func(function(e) { assert_unreached(e); }));
262     reader2.closed.then(test8.step_func(function() {
263         assert_true(reader1Closed);
264         test8.done('branch2 should be closed');
265     })).catch(test8.step_func(function(e) { assert_unreached(e); }));
266
267     controller.close();
268 });
269
270 var test9 = async_test('ReadableStream teeing: erroring the original should immediately error the branches');
271 test9.step(function() {
272     var reader1Rejected = false;
273     var controller;
274     var rs = new ReadableStream({
275         start(c) {
276             controller = c;
277         }
278     });
279
280     var branch = rs.tee();
281     var branch1 = branch[0];
282     var branch2 = branch[1];
283     var reader1 = branch1.getReader();
284     var reader2 = branch2.getReader();
285
286     var theError = new Error('boo!');
287
288     reader1.closed.then(
289         test9.step_func(function() { assert_unreached('branch1 should not be closed'); }),
290         test9.step_func(function(e) {
291             assert_equals(e, theError, 'branch1 should be errored with the error');
292             reader1Rejected = true;
293         })
294     );
295     reader2.closed.then(
296         test9.step_func(function() { assert_unreached('branch2 should not be closed'); }),
297         test9.step_func(function(e) {
298             assert_equals(e, theError, 'branch2 should be errored with the error');
299             assert_true(reader1Rejected);
300             test9.done();
301         })
302     );
303
304     controller.error(theError);
305 });
306 </script>