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