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 |