| 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 |