| 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 deprecatedFutureValue(_FutureImpl future) => | 7 deprecatedFutureValue(_FutureImpl future) => |
| 8 future._isComplete ? future._resultOrListeners : null; | 8 future._isComplete ? future._resultOrListeners : null; |
| 9 | 9 |
| 10 abstract class _Completer<T> implements Completer<T> { | 10 abstract class _Completer<T> implements Completer<T> { |
| 11 final Future<T> future; | 11 final Future<T> future; |
| 12 bool _isComplete = false; | 12 bool _isComplete = false; |
| 13 | 13 |
| 14 _Completer() : future = new _FutureImpl<T>(); | 14 _Completer() : future = new _FutureImpl<T>() { |
| 15 _FutureImpl futureImpl = future; |
| 16 futureImpl._zone.expectCallback(); |
| 17 } |
| 15 | 18 |
| 16 void _setFutureValue(T value); | 19 void _setFutureValue(T value); |
| 17 void _setFutureError(error); | 20 void _setFutureError(error); |
| 18 | 21 |
| 19 void complete([T value]) { | 22 void complete([T value]) { |
| 20 if (_isComplete) throw new StateError("Future already completed"); | 23 if (_isComplete) throw new StateError("Future already completed"); |
| 21 _isComplete = true; | 24 _isComplete = true; |
| 25 _FutureImpl futureImpl = future; |
| 26 futureImpl._zone.cancelCallbackExpectation(); |
| 22 _setFutureValue(value); | 27 _setFutureValue(value); |
| 23 } | 28 } |
| 24 | 29 |
| 25 void completeError(Object error, [Object stackTrace = null]) { | 30 void completeError(Object error, [Object stackTrace = null]) { |
| 26 if (_isComplete) throw new StateError("Future already completed"); | 31 if (_isComplete) throw new StateError("Future already completed"); |
| 27 _isComplete = true; | 32 _isComplete = true; |
| 28 if (stackTrace != null) { | 33 if (stackTrace != null) { |
| 29 // Force the stack trace onto the error, even if it already had one. | 34 // Force the stack trace onto the error, even if it already had one. |
| 30 _attachStackTrace(error, stackTrace); | 35 _attachStackTrace(error, stackTrace); |
| 31 } | 36 } |
| 32 _setFutureError(error); | 37 _FutureImpl futureImpl = future; |
| 38 if (futureImpl._inSameErrorZone(_Zone.current)) { |
| 39 futureImpl._zone.cancelCallbackExpectation(); |
| 40 _setFutureError(error); |
| 41 } else { |
| 42 _Zone.current.handleUncaughtError(error); |
| 43 } |
| 33 } | 44 } |
| 34 | 45 |
| 35 bool get isCompleted => _isComplete; | 46 bool get isCompleted => _isComplete; |
| 36 } | 47 } |
| 37 | 48 |
| 38 class _AsyncCompleter<T> extends _Completer<T> { | 49 class _AsyncCompleter<T> extends _Completer<T> { |
| 39 void _setFutureValue(T value) { | 50 void _setFutureValue(T value) { |
| 40 _FutureImpl future = this.future; | 51 _FutureImpl future = this.future; |
| 41 runAsync(() { future._setValue(value); }); | 52 runAsync(() { future._setValue(value); }); |
| 42 } | 53 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 67 * | 78 * |
| 68 * Listeners are kept in a linked list. | 79 * Listeners are kept in a linked list. |
| 69 */ | 80 */ |
| 70 abstract class _FutureListener<T> { | 81 abstract class _FutureListener<T> { |
| 71 _FutureListener _nextListener; | 82 _FutureListener _nextListener; |
| 72 factory _FutureListener.wrap(_FutureImpl future) { | 83 factory _FutureListener.wrap(_FutureImpl future) { |
| 73 return new _FutureListenerWrapper(future); | 84 return new _FutureListenerWrapper(future); |
| 74 } | 85 } |
| 75 void _sendValue(T value); | 86 void _sendValue(T value); |
| 76 void _sendError(error); | 87 void _sendError(error); |
| 88 |
| 89 bool _inSameErrorZone(_Zone otherZone); |
| 77 } | 90 } |
| 78 | 91 |
| 79 /** Adapter for a [_FutureImpl] to be a future result listener. */ | 92 /** Adapter for a [_FutureImpl] to be a future result listener. */ |
| 80 class _FutureListenerWrapper<T> implements _FutureListener<T> { | 93 class _FutureListenerWrapper<T> implements _FutureListener<T> { |
| 81 _FutureImpl future; | 94 _FutureImpl future; |
| 82 _FutureListener _nextListener; | 95 _FutureListener _nextListener; |
| 83 _FutureListenerWrapper(this.future); | 96 _FutureListenerWrapper(this.future); |
| 84 _sendValue(T value) { future._setValue(value); } | 97 _sendValue(T value) { future._setValue(value); } |
| 85 _sendError(error) { future._setError(error); } | 98 _sendError(error) { future._setError(error); } |
| 99 bool _inSameErrorZone(_Zone otherZone) => future._inSameErrorZone(otherZone); |
| 100 } |
| 101 |
| 102 /** |
| 103 * This listener is installed at error-zone boundaries. It signals an |
| 104 * uncaught error in the zone of origin when an error is sent from one error |
| 105 * zone to another. |
| 106 * |
| 107 * When a Future is listening to another Future and they have not been |
| 108 * instantiated in the same error-zone then Futures put an instance of this |
| 109 * class between them (see [_FutureImpl._addListener]). |
| 110 * |
| 111 * For example: |
| 112 * |
| 113 * var completer = new Completer(); |
| 114 * var future = completer.future.then((x) => x); |
| 115 * catchErrors(() { |
| 116 * var future2 = future.catchError(print); |
| 117 * }); |
| 118 * completer.completeError(499); |
| 119 * |
| 120 * In this example `future` and `future2` are in different error-zones. The |
| 121 * error (499) that originates outside `catchErrors` must not reach the |
| 122 * `catchError` future (`future2`) inside `catchErrors`. |
| 123 * |
| 124 * When invoking `catchError` on `future` the Future installs an |
| 125 * [_ErrorZoneBoundaryListener] between itself and the result, `future2`. |
| 126 * |
| 127 * Conceptually _ErrorZoneBoundaryListeners could be implemented as |
| 128 * `catchError`s on the origin future as well. |
| 129 */ |
| 130 class _ErrorZoneBoundaryListener implements _FutureListener { |
| 131 _FutureListener _nextListener; |
| 132 final _FutureListener _listener; |
| 133 |
| 134 _ErrorZoneBoundaryListener(this._listener); |
| 135 |
| 136 bool _inSameErrorZone(_Zone otherZone) { |
| 137 // Should never be called. We use [_inSameErrorZone] to know if we have |
| 138 // to insert an instance of [_ErrorZoneBoundaryListener] (and in the |
| 139 // controller). Once we have inserted one we should never need to use it |
| 140 // anymore. |
| 141 throw new UnsupportedError( |
| 142 "A Zone boundary doesn't support the inSameErrorZone test."); |
| 143 } |
| 144 |
| 145 void _sendValue(value) { |
| 146 _listener._sendValue(value); |
| 147 } |
| 148 |
| 149 void _sendError(error) { |
| 150 // We are not allowed to send an error from one error-zone to another. |
| 151 // This is the whole purpose of this class. |
| 152 _Zone.current.handleUncaughtError(error); |
| 153 } |
| 86 } | 154 } |
| 87 | 155 |
| 88 class _FutureImpl<T> implements Future<T> { | 156 class _FutureImpl<T> implements Future<T> { |
| 89 // State of the future. The state determines the interpretation of the | 157 // State of the future. The state determines the interpretation of the |
| 90 // [resultOrListeners] field. | 158 // [resultOrListeners] field. |
| 91 // TODO(lrn): rename field since it can also contain a chained future. | 159 // TODO(lrn): rename field since it can also contain a chained future. |
| 92 | 160 |
| 93 /// Initial state, waiting for a result. In this state, the | 161 /// Initial state, waiting for a result. In this state, the |
| 94 /// [resultOrListeners] field holds a single-linked list of | 162 /// [resultOrListeners] field holds a single-linked list of |
| 95 /// [FutureListener] listeners. | 163 /// [FutureListener] listeners. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 111 /// Extra bit set when the future has been completed with an error result. | 179 /// Extra bit set when the future has been completed with an error result. |
| 112 /// but no listener has been scheduled to receive the error. | 180 /// but no listener has been scheduled to receive the error. |
| 113 /// If the bit is still set when a [runAsync] call triggers, the error will | 181 /// If the bit is still set when a [runAsync] call triggers, the error will |
| 114 /// be reported to the top-level handler. | 182 /// be reported to the top-level handler. |
| 115 /// Assigning a listener before that time will clear the bit. | 183 /// Assigning a listener before that time will clear the bit. |
| 116 static const int _UNHANDLED_ERROR = 8; | 184 static const int _UNHANDLED_ERROR = 8; |
| 117 | 185 |
| 118 /** Whether the future is complete, and as what. */ | 186 /** Whether the future is complete, and as what. */ |
| 119 int _state = _INCOMPLETE; | 187 int _state = _INCOMPLETE; |
| 120 | 188 |
| 189 final _Zone _zone = _Zone.current.fork(); |
| 190 |
| 121 bool get _isChained => (_state & _CHAINED) != 0; | 191 bool get _isChained => (_state & _CHAINED) != 0; |
| 122 bool get _hasChainedListener => _state == _CHAINED; | 192 bool get _hasChainedListener => _state == _CHAINED; |
| 123 bool get _isComplete => _state >= _VALUE; | 193 bool get _isComplete => _state >= _VALUE; |
| 124 bool get _hasValue => _state == _VALUE; | 194 bool get _hasValue => _state == _VALUE; |
| 125 bool get _hasError => _state >= _ERROR; | 195 bool get _hasError => _state >= _ERROR; |
| 126 bool get _hasUnhandledError => _state >= _UNHANDLED_ERROR; | 196 bool get _hasUnhandledError => _state >= _UNHANDLED_ERROR; |
| 127 | 197 |
| 128 void _clearUnhandledError() { | 198 void _clearUnhandledError() { |
| 129 _state &= ~_UNHANDLED_ERROR; | 199 _state &= ~_UNHANDLED_ERROR; |
| 130 } | 200 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 Future catchError(f(error), { bool test(error) }) { | 278 Future catchError(f(error), { bool test(error) }) { |
| 209 return new _CatchErrorFuture(f, test).._subscribeTo(this); | 279 return new _CatchErrorFuture(f, test).._subscribeTo(this); |
| 210 } | 280 } |
| 211 | 281 |
| 212 Future<T> whenComplete(action()) { | 282 Future<T> whenComplete(action()) { |
| 213 return new _WhenFuture<T>(action).._subscribeTo(this); | 283 return new _WhenFuture<T>(action).._subscribeTo(this); |
| 214 } | 284 } |
| 215 | 285 |
| 216 Stream<T> asStream() => new Stream.fromFuture(this); | 286 Stream<T> asStream() => new Stream.fromFuture(this); |
| 217 | 287 |
| 288 bool _inSameErrorZone(_Zone otherZone) { |
| 289 return _zone.inSameErrorZone(otherZone); |
| 290 } |
| 291 |
| 218 void _setValue(T value) { | 292 void _setValue(T value) { |
| 219 if (_isComplete) throw new StateError("Future already completed"); | 293 if (_isComplete) throw new StateError("Future already completed"); |
| 220 _FutureListener listeners = _isChained ? null : _removeListeners(); | 294 _FutureListener listeners = _isChained ? null : _removeListeners(); |
| 221 _state = _VALUE; | 295 _state = _VALUE; |
| 222 _resultOrListeners = value; | 296 _resultOrListeners = value; |
| 223 while (listeners != null) { | 297 while (listeners != null) { |
| 224 _FutureListener listener = listeners; | 298 _FutureListener listener = listeners; |
| 225 listeners = listener._nextListener; | 299 listeners = listener._nextListener; |
| 226 listener._nextListener = null; | 300 listener._nextListener = null; |
| 227 listener._sendValue(value); | 301 listener._sendValue(value); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 assert(_state == _ERROR); | 334 assert(_state == _ERROR); |
| 261 _state = _ERROR | _UNHANDLED_ERROR; | 335 _state = _ERROR | _UNHANDLED_ERROR; |
| 262 // Wait for the rest of the current event's duration to see | 336 // Wait for the rest of the current event's duration to see |
| 263 // if a subscriber is added to handle the error. | 337 // if a subscriber is added to handle the error. |
| 264 runAsync(() { | 338 runAsync(() { |
| 265 if (_hasUnhandledError) { | 339 if (_hasUnhandledError) { |
| 266 // No error handler has been added since the error was set. | 340 // No error handler has been added since the error was set. |
| 267 _clearUnhandledError(); | 341 _clearUnhandledError(); |
| 268 // TODO(floitsch): Hook this into unhandled error handling. | 342 // TODO(floitsch): Hook this into unhandled error handling. |
| 269 var error = _resultOrListeners; | 343 var error = _resultOrListeners; |
| 270 print("Uncaught Error: ${error}"); | 344 _zone.handleUncaughtError(error); |
| 271 var trace = getAttachedStackTrace(error); | |
| 272 if (trace != null) { | |
| 273 print("Stack Trace:\n$trace\n"); | |
| 274 } | |
| 275 throw error; | |
| 276 } | 345 } |
| 277 }); | 346 }); |
| 278 } | 347 } |
| 279 | 348 |
| 280 void _addListener(_FutureListener listener) { | 349 void _addListener(_FutureListener listener) { |
| 350 assert(listener._nextListener == null); |
| 351 if (!listener._inSameErrorZone(_zone)) { |
| 352 listener = new _ErrorZoneBoundaryListener(listener); |
| 353 } |
| 281 if (_isChained) { | 354 if (_isChained) { |
| 282 _state = _CHAINED; // In case it was _CHAINED_UNLISTENED. | 355 _state = _CHAINED; // In case it was _CHAINED_UNLISTENED. |
| 283 _FutureImpl resultSource = _chainSource; | 356 _FutureImpl resultSource = _chainSource; |
| 284 resultSource._addListener(listener); | 357 resultSource._addListener(listener); |
| 285 return; | 358 return; |
| 286 } | 359 } |
| 287 if (_isComplete) { | 360 if (_isComplete) { |
| 288 _clearUnhandledError(); | 361 _clearUnhandledError(); |
| 289 // Handle late listeners asynchronously. | 362 // Handle late listeners asynchronously. |
| 290 runAsync(() { | 363 runAsync(() { |
| 291 if (_hasValue) { | 364 if (_hasValue) { |
| 292 T value = _resultOrListeners; | 365 T value = _resultOrListeners; |
| 293 listener._sendValue(value); | 366 listener._sendValue(value); |
| 294 } else { | 367 } else { |
| 295 assert(_hasError); | 368 assert(_hasError); |
| 296 listener._sendError(_resultOrListeners); | 369 listener._sendError(_resultOrListeners); |
| 297 } | 370 } |
| 298 }); | 371 }); |
| 299 } else { | 372 } else { |
| 300 assert(!_isComplete); | 373 assert(!_isComplete); |
| 301 assert(listener._nextListener == null); | |
| 302 listener._nextListener = _resultOrListeners; | 374 listener._nextListener = _resultOrListeners; |
| 303 _resultOrListeners = listener; | 375 _resultOrListeners = listener; |
| 304 } | 376 } |
| 305 } | 377 } |
| 306 | 378 |
| 307 _FutureListener _removeListeners() { | 379 _FutureListener _removeListeners() { |
| 308 // Reverse listeners before returning them, so the resulting list is in | 380 // Reverse listeners before returning them, so the resulting list is in |
| 309 // subscription order. | 381 // subscription order. |
| 310 assert(!_isComplete); | 382 assert(!_isComplete); |
| 311 _FutureListener current = _resultOrListeners; | 383 _FutureListener current = _resultOrListeners; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 * | 499 * |
| 428 * A transforming future is itself a future and a future listener. | 500 * A transforming future is itself a future and a future listener. |
| 429 * Subclasses override [_sendValue]/[_sendError] to intercept | 501 * Subclasses override [_sendValue]/[_sendError] to intercept |
| 430 * the results of a previous future. | 502 * the results of a previous future. |
| 431 */ | 503 */ |
| 432 abstract class _TransformFuture<S, T> extends _FutureImpl<T> | 504 abstract class _TransformFuture<S, T> extends _FutureImpl<T> |
| 433 implements _FutureListener<S> { | 505 implements _FutureListener<S> { |
| 434 // _FutureListener implementation. | 506 // _FutureListener implementation. |
| 435 _FutureListener _nextListener; | 507 _FutureListener _nextListener; |
| 436 | 508 |
| 437 void _sendValue(S value); | 509 _TransformFuture() { |
| 510 _zone.expectCallback(); |
| 511 } |
| 438 | 512 |
| 439 void _sendError(error); | 513 void _sendValue(S value) { |
| 514 _zone.executeCallback(() => _zonedSendValue(value)); |
| 515 } |
| 516 |
| 517 void _sendError(error) { |
| 518 _zone.executeCallback(() => _zonedSendError(error)); |
| 519 } |
| 440 | 520 |
| 441 void _subscribeTo(_FutureImpl future) { | 521 void _subscribeTo(_FutureImpl future) { |
| 442 future._addListener(this); | 522 future._addListener(this); |
| 443 } | 523 } |
| 524 |
| 525 void _zonedSendValue(S value); |
| 526 void _zonedSendError(error); |
| 444 } | 527 } |
| 445 | 528 |
| 446 /** The onValue and onError handlers return either a value or a future */ | 529 /** The onValue and onError handlers return either a value or a future */ |
| 447 typedef dynamic _FutureOnValue<T>(T value); | 530 typedef dynamic _FutureOnValue<T>(T value); |
| 448 typedef dynamic _FutureOnError(error); | 531 typedef dynamic _FutureOnError(error); |
| 449 /** Test used by [Future.catchError] to handle skip some errors. */ | 532 /** Test used by [Future.catchError] to handle skip some errors. */ |
| 450 typedef bool _FutureErrorTest(var error); | 533 typedef bool _FutureErrorTest(var error); |
| 451 /** Used by [WhenFuture]. */ | 534 /** Used by [WhenFuture]. */ |
| 452 typedef _FutureAction(); | 535 typedef _FutureAction(); |
| 453 | 536 |
| 454 /** Future returned by [Future.then] with no [:onError:] parameter. */ | 537 /** Future returned by [Future.then] with no [:onError:] parameter. */ |
| 455 class _ThenFuture<S, T> extends _TransformFuture<S, T> { | 538 class _ThenFuture<S, T> extends _TransformFuture<S, T> { |
| 456 // TODO(ahe): Restore type when feature is implemented in dart2js | 539 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 457 // checked mode. | 540 // checked mode. |
| 458 final /* _FutureOnValue<S> */ _onValue; | 541 final /* _FutureOnValue<S> */ _onValue; |
| 459 | 542 |
| 460 _ThenFuture(this._onValue); | 543 _ThenFuture(this._onValue); |
| 461 | 544 |
| 462 _sendValue(S value) { | 545 _zonedSendValue(S value) { |
| 463 assert(_onValue != null); | 546 assert(_onValue != null); |
| 464 var result; | 547 var result; |
| 465 try { | 548 try { |
| 466 result = _onValue(value); | 549 result = _onValue(value); |
| 467 } catch (e, s) { | 550 } catch (e, s) { |
| 468 _setError(_asyncError(e, s)); | 551 _setError(_asyncError(e, s)); |
| 469 return; | 552 return; |
| 470 } | 553 } |
| 471 _setOrChainValue(result); | 554 _setOrChainValue(result); |
| 472 } | 555 } |
| 473 | 556 |
| 474 void _sendError(error) { | 557 void _zonedSendError(error) { |
| 475 _setError(error); | 558 _setError(error); |
| 476 } | 559 } |
| 477 } | 560 } |
| 478 | 561 |
| 479 /** Future returned by [Future.catchError]. */ | 562 /** Future returned by [Future.catchError]. */ |
| 480 class _CatchErrorFuture<T> extends _TransformFuture<T,T> { | 563 class _CatchErrorFuture<T> extends _TransformFuture<T,T> { |
| 481 final _FutureErrorTest _test; | 564 final _FutureErrorTest _test; |
| 482 final _FutureOnError _onError; | 565 final _FutureOnError _onError; |
| 483 | 566 |
| 484 _CatchErrorFuture(this._onError, this._test); | 567 _CatchErrorFuture(this._onError, this._test); |
| 485 | 568 |
| 486 _sendValue(T value) { | 569 _zonedSendValue(T value) { |
| 487 _setValue(value); | 570 _setValue(value); |
| 488 } | 571 } |
| 489 | 572 |
| 490 _sendError(error) { | 573 _zonedSendError(error) { |
| 491 assert(_onError != null); | 574 assert(_onError != null); |
| 492 // if _test is supplied, check if it returns true, otherwise just | 575 // if _test is supplied, check if it returns true, otherwise just |
| 493 // forward the error unmodified. | 576 // forward the error unmodified. |
| 494 if (_test != null) { | 577 if (_test != null) { |
| 495 bool matchesTest; | 578 bool matchesTest; |
| 496 try { | 579 try { |
| 497 matchesTest = _test(error); | 580 matchesTest = _test(error); |
| 498 } catch (e, s) { | 581 } catch (e, s) { |
| 499 _setError(_asyncError(e, s)); | 582 _setError(_asyncError(e, s)); |
| 500 return; | 583 return; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 517 } | 600 } |
| 518 | 601 |
| 519 /** Future returned by [Future.then] with an [:onError:] parameter. */ | 602 /** Future returned by [Future.then] with an [:onError:] parameter. */ |
| 520 class _SubscribeFuture<S, T> extends _ThenFuture<S, T> { | 603 class _SubscribeFuture<S, T> extends _ThenFuture<S, T> { |
| 521 final _FutureOnError _onError; | 604 final _FutureOnError _onError; |
| 522 | 605 |
| 523 _SubscribeFuture(onValue(S value), this._onError) : super(onValue); | 606 _SubscribeFuture(onValue(S value), this._onError) : super(onValue); |
| 524 | 607 |
| 525 // The _sendValue method is inherited from ThenFuture. | 608 // The _sendValue method is inherited from ThenFuture. |
| 526 | 609 |
| 527 void _sendError(error) { | 610 void _zonedSendError(error) { |
| 528 assert(_onError != null); | 611 assert(_onError != null); |
| 529 var result; | 612 var result; |
| 530 try { | 613 try { |
| 531 result = _onError(error); | 614 result = _onError(error); |
| 532 } catch (e, s) { | 615 } catch (e, s) { |
| 533 _setError(_asyncError(e, s)); | 616 _setError(_asyncError(e, s)); |
| 534 return; | 617 return; |
| 535 } | 618 } |
| 536 _setOrChainValue(result); | 619 _setOrChainValue(result); |
| 537 } | 620 } |
| 538 } | 621 } |
| 539 | 622 |
| 540 /** Future returned by [Future.whenComplete]. */ | 623 /** Future returned by [Future.whenComplete]. */ |
| 541 class _WhenFuture<T> extends _TransformFuture<T, T> { | 624 class _WhenFuture<T> extends _TransformFuture<T, T> { |
| 542 final _FutureAction _action; | 625 final _FutureAction _action; |
| 543 | 626 |
| 544 _WhenFuture(this._action); | 627 _WhenFuture(this._action); |
| 545 | 628 |
| 546 void _sendValue(T value) { | 629 void _zonedSendValue(T value) { |
| 547 try { | 630 try { |
| 548 var result = _action(); | 631 var result = _action(); |
| 549 if (result is Future) { | 632 if (result is Future) { |
| 550 Future resultFuture = result; | 633 Future resultFuture = result; |
| 551 resultFuture.then((_) { | 634 resultFuture.then((_) { |
| 552 _setValue(value); | 635 _setValue(value); |
| 553 }, onError: _setError); | 636 }, onError: _setError); |
| 554 return; | 637 return; |
| 555 } | 638 } |
| 556 } catch (e, s) { | 639 } catch (e, s) { |
| 557 _setError(_asyncError(e, s)); | 640 _setError(_asyncError(e, s)); |
| 558 return; | 641 return; |
| 559 } | 642 } |
| 560 _setValue(value); | 643 _setValue(value); |
| 561 } | 644 } |
| 562 | 645 |
| 563 void _sendError(error) { | 646 void _zonedSendError(error) { |
| 564 try { | 647 try { |
| 565 var result = _action(); | 648 var result = _action(); |
| 566 if (result is Future) { | 649 if (result is Future) { |
| 567 Future resultFuture = result; | 650 Future resultFuture = result; |
| 568 // TODO(lrn): Find a way to combine [error] into [e]. | 651 // TODO(lrn): Find a way to combine [error] into [e]. |
| 569 resultFuture.then((_) { | 652 resultFuture.then((_) { |
| 570 _setError(error); | 653 _setError(error); |
| 571 }, onError: _setError); | 654 }, onError: _setError); |
| 572 return; | 655 return; |
| 573 } | 656 } |
| 574 } catch (e, s) { | 657 } catch (e, s) { |
| 575 error = _asyncError(e, s); | 658 error = _asyncError(e, s); |
| 576 } | 659 } |
| 577 _setError(error); | 660 _setError(error); |
| 578 } | 661 } |
| 579 } | 662 } |
| OLD | NEW |