OLD | NEW |
(Empty) | |
| 1 'use strict'; |
| 2 |
| 3 if (self.importScripts) { |
| 4 self.importScripts('../resources/test-utils.js'); |
| 5 self.importScripts('../resources/rs-utils.js'); |
| 6 self.importScripts('/resources/testharness.js'); |
| 7 } |
| 8 |
| 9 promise_test(() => { |
| 10 |
| 11 const randomSource = new RandomPushSource(); |
| 12 |
| 13 let cancellationFinished = false; |
| 14 const rs = new ReadableStream({ |
| 15 start(c) { |
| 16 randomSource.ondata = c.enqueue.bind(c); |
| 17 randomSource.onend = c.close.bind(c); |
| 18 randomSource.onerror = c.error.bind(c); |
| 19 }, |
| 20 |
| 21 pull() { |
| 22 randomSource.readStart(); |
| 23 }, |
| 24 |
| 25 cancel() { |
| 26 randomSource.readStop(); |
| 27 randomSource.onend(); |
| 28 |
| 29 return new Promise(resolve => { |
| 30 setTimeout(() => { |
| 31 cancellationFinished = true; |
| 32 resolve(); |
| 33 }, 1); |
| 34 }); |
| 35 } |
| 36 }); |
| 37 |
| 38 const reader = rs.getReader(); |
| 39 |
| 40 // We call delay multiple times to avoid cancelling too early for the |
| 41 // source to enqueue at least one chunk. |
| 42 const cancel = delay(5).then(() => delay(5)).then(() => delay(5)).then(() => r
eader.cancel()); |
| 43 |
| 44 return readableStreamToArray(rs, reader).then(chunks => { |
| 45 assert_greater_than(chunks.length, 0, 'at least one chunk should be read'); |
| 46 for (let i = 0; i < chunks.length; i++) { |
| 47 assert_equals(chunks[i].length, 128, 'chunk ' + i + ' should have 128 byte
s'); |
| 48 } |
| 49 assert_false(cancellationFinished, 'it did not wait for the cancellation pro
cess to finish before closing'); |
| 50 return cancel; |
| 51 }).then(() => { |
| 52 assert_true(cancellationFinished, 'it returns a promise that is fulfilled wh
en the cancellation finishes'); |
| 53 }); |
| 54 |
| 55 }, 'ReadableStream cancellation: integration test on an infinite stream derived
from a random push source'); |
| 56 |
| 57 test(() => { |
| 58 |
| 59 let recordedReason; |
| 60 const rs = new ReadableStream({ |
| 61 cancel(reason) { |
| 62 recordedReason = reason; |
| 63 } |
| 64 }); |
| 65 |
| 66 const passedReason = new Error('Sorry, it just wasn\'t meant to be.'); |
| 67 rs.cancel(passedReason); |
| 68 |
| 69 assert_equals(recordedReason, passedReason, |
| 70 'the error passed to the underlying source\'s cancel method should equal the
one passed to the stream\'s cancel'); |
| 71 |
| 72 }, 'ReadableStream cancellation: cancel(reason) should pass through the given re
ason to the underlying source'); |
| 73 |
| 74 promise_test(() => { |
| 75 |
| 76 const rs = new ReadableStream({ |
| 77 start(c) { |
| 78 c.enqueue('a'); |
| 79 c.close(); |
| 80 }, |
| 81 cancel() { |
| 82 assert_unreached('underlying source cancel() should not have been called')
; |
| 83 } |
| 84 }); |
| 85 |
| 86 const reader = rs.getReader(); |
| 87 |
| 88 return rs.cancel().then(() => { |
| 89 assert_unreached('cancel() should be rejected'); |
| 90 }, e => { |
| 91 assert_equals(e.name, 'TypeError', 'cancel() should be rejected with a TypeE
rror'); |
| 92 }).then(() => { |
| 93 return reader.read(); |
| 94 }).then(result => { |
| 95 assert_object_equals(result, { value: 'a', done: false }, 'read() should sti
ll work after the attempted cancel'); |
| 96 return reader.closed; |
| 97 }); |
| 98 |
| 99 }, 'ReadableStream cancellation: cancel() on a locked stream should fail and not
call the underlying source cancel'); |
| 100 |
| 101 promise_test(() => { |
| 102 |
| 103 let cancelReceived = false; |
| 104 const cancelReason = new Error('I am tired of this stream, I prefer to cancel
it'); |
| 105 const rs = new ReadableStream({ |
| 106 cancel(reason) { |
| 107 cancelReceived = true; |
| 108 assert_equals(reason, cancelReason, 'cancellation reason given to the unde
rlying source should be equal to the one passed'); |
| 109 } |
| 110 }); |
| 111 |
| 112 return rs.cancel(cancelReason).then(() => { |
| 113 assert_true(cancelReceived); |
| 114 }); |
| 115 |
| 116 }, 'ReadableStream cancellation: should fulfill promise when cancel callback wen
t fine'); |
| 117 |
| 118 promise_test(() => { |
| 119 |
| 120 const rs = new ReadableStream({ |
| 121 cancel() { |
| 122 return 'Hello'; |
| 123 } |
| 124 }); |
| 125 |
| 126 return rs.cancel().then(v => { |
| 127 assert_equals(v, undefined, 'cancel() return value should be fulfilled with
undefined'); |
| 128 }); |
| 129 |
| 130 }, 'ReadableStream cancellation: returning a value from the underlying source\'s
cancel should not affect the fulfillment value of the promise returned by the s
tream\'s cancel'); |
| 131 |
| 132 promise_test(() => { |
| 133 |
| 134 const thrownError = new Error('test'); |
| 135 let cancelCalled = false; |
| 136 |
| 137 const rs = new ReadableStream({ |
| 138 cancel() { |
| 139 cancelCalled = true; |
| 140 throw thrownError; |
| 141 } |
| 142 }); |
| 143 |
| 144 return rs.cancel('test').then(() => { |
| 145 assert_unreached('cancel should reject'); |
| 146 }, e => { |
| 147 assert_true(cancelCalled); |
| 148 assert_equals(e, thrownError); |
| 149 }); |
| 150 |
| 151 }, 'ReadableStream cancellation: should reject promise when cancel callback rais
es an exception'); |
| 152 |
| 153 promise_test(() => { |
| 154 |
| 155 const cancelReason = new Error('test'); |
| 156 |
| 157 const rs = new ReadableStream({ |
| 158 cancel(error) { |
| 159 assert_equals(error, cancelReason); |
| 160 return delay(1); |
| 161 } |
| 162 }); |
| 163 |
| 164 return rs.cancel(cancelReason); |
| 165 |
| 166 }, 'ReadableStream cancellation: if the underlying source\'s cancel method retur
ns a promise, the promise returned by the stream\'s cancel should fulfill when t
hat one does (1)'); |
| 167 |
| 168 promise_test(() => { |
| 169 |
| 170 let resolveSourceCancelPromise; |
| 171 let sourceCancelPromiseHasFulfilled = false; |
| 172 |
| 173 const rs = new ReadableStream({ |
| 174 cancel() { |
| 175 const sourceCancelPromise = new Promise(resolve => resolveSourceCancelProm
ise = resolve); |
| 176 |
| 177 sourceCancelPromise.then(() => { |
| 178 sourceCancelPromiseHasFulfilled = true; |
| 179 }); |
| 180 |
| 181 return sourceCancelPromise; |
| 182 } |
| 183 }); |
| 184 |
| 185 setTimeout(() => resolveSourceCancelPromise('Hello'), 1); |
| 186 |
| 187 return rs.cancel().then(value => { |
| 188 assert_true(sourceCancelPromiseHasFulfilled, 'cancel() return value should b
e fulfilled only after the promise returned by the underlying source\'s cancel')
; |
| 189 assert_equals(value, undefined, 'cancel() return value should be fulfilled w
ith undefined'); |
| 190 }); |
| 191 |
| 192 }, 'ReadableStream cancellation: if the underlying source\'s cancel method retur
ns a promise, the promise returned by the stream\'s cancel should fulfill when t
hat one does (2)'); |
| 193 |
| 194 promise_test(() => { |
| 195 |
| 196 let rejectSourceCancelPromise; |
| 197 let sourceCancelPromiseHasRejected = false; |
| 198 |
| 199 const rs = new ReadableStream({ |
| 200 cancel() { |
| 201 const sourceCancelPromise = new Promise((resolve, reject) => rejectSourceC
ancelPromise = reject); |
| 202 |
| 203 sourceCancelPromise.catch(() => { |
| 204 sourceCancelPromiseHasRejected = true; |
| 205 }); |
| 206 |
| 207 return sourceCancelPromise; |
| 208 } |
| 209 }); |
| 210 |
| 211 const errorInCancel = new Error('Sorry, it just wasn\'t meant to be.'); |
| 212 |
| 213 setTimeout(() => rejectSourceCancelPromise(errorInCancel), 1); |
| 214 |
| 215 return rs.cancel().then(() => { |
| 216 assert_unreached('cancel() return value should be rejected'); |
| 217 }, r => { |
| 218 assert_true(sourceCancelPromiseHasRejected, 'cancel() return value should be
rejected only after the promise returned by the underlying source\'s cancel'); |
| 219 assert_equals(r, errorInCancel, 'cancel() return value should be rejected wi
th the underlying source\'s rejection reason'); |
| 220 }); |
| 221 |
| 222 }, 'ReadableStream cancellation: if the underlying source\'s cancel method retur
ns a promise, the promise returned by the stream\'s cancel should reject when th
at one does'); |
| 223 |
| 224 promise_test(() => { |
| 225 |
| 226 const rs = new ReadableStream({ |
| 227 start() { |
| 228 return new Promise(() => {}); |
| 229 }, |
| 230 pull() { |
| 231 assert_unreached('pull should not have been called'); |
| 232 } |
| 233 }); |
| 234 |
| 235 return Promise.all([rs.cancel(), rs.getReader().closed]); |
| 236 |
| 237 }, 'ReadableStream cancellation: cancelling before start finishes should prevent
pull() from being called'); |
| 238 |
| 239 done(); |
OLD | NEW |