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