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 |