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