OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart.async; | 5 part of dart.async; |
6 | 6 |
7 /** The onValue and onError handlers return either a value or a future */ | 7 /** The onValue and onError handlers return either a value or a future */ |
8 typedef dynamic _FutureOnValue<T>(T value); | 8 typedef dynamic _FutureOnValue<T>(T value); |
9 /** Test used by [Future.catchError] to handle skip some errors. */ | 9 /** Test used by [Future.catchError] to handle skip some errors. */ |
10 typedef bool _FutureErrorTest(var error); | 10 typedef bool _FutureErrorTest(var error); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 _state = _PENDING_COMPLETE; | 233 _state = _PENDING_COMPLETE; |
234 } | 234 } |
235 | 235 |
236 AsyncError get _error { | 236 AsyncError get _error { |
237 assert(_hasError); | 237 assert(_hasError); |
238 return _resultOrListeners; | 238 return _resultOrListeners; |
239 } | 239 } |
240 | 240 |
241 _Future get _chainSource { | 241 _Future get _chainSource { |
242 assert(_isChained); | 242 assert(_isChained); |
243 return _resultOrListeners; | 243 _Future result = _resultOrListeners; |
| 244 while (result._isChained) { |
| 245 result = result._resultOrListeners; |
| 246 _resultOrListeners = result; |
| 247 } |
| 248 return result; |
244 } | 249 } |
245 | 250 |
246 // This method is used by async/await. | 251 // This method is used by async/await. |
247 void _setValue(T value) { | 252 void _setValue(T value) { |
248 assert(!_isComplete); // But may have a completion pending. | 253 assert(!_isComplete); // But may have a completion pending. |
249 _state = _VALUE; | 254 _state = _VALUE; |
250 _resultOrListeners = value; | 255 _resultOrListeners = value; |
251 } | 256 } |
252 | 257 |
253 void _setErrorObject(AsyncError error) { | 258 void _setErrorObject(AsyncError error) { |
(...skipping 15 matching lines...) Expand all Loading... |
269 _state = source._state; | 274 _state = source._state; |
270 _resultOrListeners = source._resultOrListeners; | 275 _resultOrListeners = source._resultOrListeners; |
271 } | 276 } |
272 | 277 |
273 void _addListener(_FutureListener listener) { | 278 void _addListener(_FutureListener listener) { |
274 assert(listener._nextListener == null); | 279 assert(listener._nextListener == null); |
275 if (_mayAddListener) { | 280 if (_mayAddListener) { |
276 listener._nextListener = _resultOrListeners; | 281 listener._nextListener = _resultOrListeners; |
277 _resultOrListeners = listener; | 282 _resultOrListeners = listener; |
278 } else { | 283 } else { |
279 if (_isChained) { | 284 _handleListener(listener); |
280 // Delegate listeners to chained source future. | |
281 // If the source is complete, instead copy its values and | |
282 // drop the chaining. | |
283 _Future source = _chainSource; | |
284 if (!source._isComplete) { | |
285 source._addListener(listener); | |
286 return; | |
287 } | |
288 _cloneResult(source); | |
289 } | |
290 assert(_isComplete); | |
291 // Handle late listeners asynchronously. | |
292 _zone.scheduleMicrotask(() { | |
293 _propagateToListeners(this, listener); | |
294 }); | |
295 } | 285 } |
296 } | 286 } |
297 | 287 |
| 288 void _handleListener(_FutureListener listener) { |
| 289 assert(listener._nextListener == null); |
| 290 assert(!_mayAddListener); |
| 291 if (_isChained) { |
| 292 _Future source = _chainSource; |
| 293 // Delegate listeners to chained source future. |
| 294 // If the source is complete, instead copy its values and |
| 295 // drop the chaining. |
| 296 if (!source._isComplete) { |
| 297 source._addListener(listener); |
| 298 return; |
| 299 } |
| 300 _cloneResult(source); |
| 301 } |
| 302 assert(_isComplete); |
| 303 // Handle late listeners asynchronously. |
| 304 _zone.scheduleMicrotask(() { |
| 305 _propagateToListeners(this, listener); |
| 306 }); |
| 307 } |
| 308 |
298 void _prependListeners(_FutureListener listeners) { | 309 void _prependListeners(_FutureListener listeners) { |
299 if (listeners == null) return; | 310 while (listeners != null) { |
300 if (_mayAddListener) { | 311 _FutureListener first = listeners; |
301 _FutureListener existingListeners = _resultOrListeners; | 312 listeners = listeners._nextListener; |
302 _resultOrListeners = listeners; | 313 first._nextListener = null; |
303 if (existingListeners != null) { | 314 _addListener(first); |
304 _FutureListener cursor = listeners; | |
305 while (cursor._nextListener != null) { | |
306 cursor = cursor._nextListener; | |
307 } | |
308 cursor._nextListener = existingListeners; | |
309 } | |
310 } else { | |
311 if (_isChained) { | |
312 // Delegate listeners to chained source future. | |
313 // If the source is complete, instead copy its values and | |
314 // drop the chaining. | |
315 _Future source = _chainSource; | |
316 if (!source._isComplete) { | |
317 source._prependListeners(listeners); | |
318 return; | |
319 } | |
320 _cloneResult(source); | |
321 } | |
322 assert(_isComplete); | |
323 listeners = _reverseListeners(listeners); | |
324 _zone.scheduleMicrotask(() { | |
325 _propagateToListeners(this, listeners); | |
326 }); | |
327 } | 315 } |
328 } | 316 } |
329 | 317 |
330 _FutureListener _removeListeners() { | 318 _FutureListener _removeListeners() { |
331 // Reverse listeners before returning them, so the resulting list is in | 319 // Reverse listeners before returning them, so the resulting list is in |
332 // subscription order. | 320 // subscription order. |
333 assert(!_isComplete); | 321 assert(!_isComplete); |
334 _FutureListener current = _resultOrListeners; | 322 _FutureListener current = _resultOrListeners; |
335 _resultOrListeners = null; | 323 _resultOrListeners = null; |
336 return _reverseListeners(current); | |
337 } | |
338 | |
339 _FutureListener _reverseListeners(_FutureListener listeners) { | |
340 _FutureListener prev = null; | 324 _FutureListener prev = null; |
341 _FutureListener current = listeners; | |
342 while (current != null) { | 325 while (current != null) { |
343 _FutureListener next = current._nextListener; | 326 _FutureListener next = current._nextListener; |
344 current._nextListener = prev; | 327 current._nextListener = prev; |
345 prev = current; | 328 prev = current; |
346 current = next; | 329 current = next; |
347 } | 330 } |
348 return prev; | 331 return prev; |
349 } | 332 } |
350 | 333 |
351 // Take the value (when completed) of source and complete target with that | 334 // Take the value (when completed) of source and complete target with that |
(...skipping 30 matching lines...) Expand all Loading... |
382 } | 365 } |
383 } | 366 } |
384 | 367 |
385 // Take the value (when completed) of source and complete target with that | 368 // Take the value (when completed) of source and complete target with that |
386 // value (or error). This function expects that source is a _Future. | 369 // value (or error). This function expects that source is a _Future. |
387 static void _chainCoreFuture(_Future source, _Future target) { | 370 static void _chainCoreFuture(_Future source, _Future target) { |
388 assert(target._mayAddListener); // Not completed, not already chained. | 371 assert(target._mayAddListener); // Not completed, not already chained. |
389 while (source._isChained) { | 372 while (source._isChained) { |
390 source = source._chainSource; | 373 source = source._chainSource; |
391 } | 374 } |
| 375 _FutureListener listeners = target._removeListeners(); |
392 if (source._isComplete) { | 376 if (source._isComplete) { |
393 _FutureListener listeners = target._removeListeners(); | |
394 target._cloneResult(source); | 377 target._cloneResult(source); |
395 _propagateToListeners(target, listeners); | 378 _propagateToListeners(target, listeners); |
396 } else { | 379 } else { |
397 _FutureListener listeners = target._resultOrListeners; | |
398 target._setChained(source); | 380 target._setChained(source); |
399 source._prependListeners(listeners); | 381 source._prependListeners(listeners); |
400 } | 382 } |
401 } | 383 } |
402 | 384 |
403 void _complete(value) { | 385 void _complete(value) { |
404 assert(!_isComplete); | 386 assert(!_isComplete); |
405 if (value is Future) { | 387 if (value is Future) { |
406 if (value is _Future) { | 388 if (value is _Future) { |
407 _chainCoreFuture(value, this); | 389 _chainCoreFuture(value, this); |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 } | 689 } |
708 }, onError: (e, s) { | 690 }, onError: (e, s) { |
709 if (timer.isActive) { | 691 if (timer.isActive) { |
710 timer.cancel(); | 692 timer.cancel(); |
711 result._completeError(e, s); | 693 result._completeError(e, s); |
712 } | 694 } |
713 }); | 695 }); |
714 return result; | 696 return result; |
715 } | 697 } |
716 } | 698 } |
OLD | NEW |