| 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 | |
| 11 class _CompleterImpl<T> implements Completer<T> { | 10 class _CompleterImpl<T> implements Completer<T> { |
| 12 final Future<T> future; | 11 final Future<T> future; |
| 13 bool _isComplete = false; | 12 bool _isComplete = false; |
| 14 | 13 |
| 15 _CompleterImpl() : future = new _FutureImpl<T>(); | 14 _CompleterImpl() : future = new _FutureImpl<T>(); |
| 16 | 15 |
| 17 void complete([T value]) { | 16 void complete([T value]) { |
| 18 if (_isComplete) throw new StateError("Future already completed"); | 17 if (_isComplete) throw new StateError("Future already completed"); |
| 19 _isComplete = true; | 18 _isComplete = true; |
| 20 _FutureImpl future = this.future; | 19 _FutureImpl future = this.future; |
| 21 future._setValue(value); | 20 future._setValue(value); |
| 22 } | 21 } |
| 23 | 22 |
| 24 void completeError(Object error, [Object stackTrace = null]) { | 23 void completeError(Object error, [Object stackTrace = null]) { |
| 25 if (_isComplete) throw new StateError("Future already completed"); | 24 if (_isComplete) throw new StateError("Future already completed"); |
| 26 _isComplete = true; | 25 _isComplete = true; |
| 27 AsyncError asyncError; | 26 if (stackTrace != null) { |
| 28 if (error is AsyncError) { | 27 // Force the stack trace onto the error, even if it already had one. |
| 29 asyncError = error; | 28 _attachStackTrace(error, stackTrace); |
| 30 } else { | |
| 31 asyncError = new AsyncError(error, stackTrace); | |
| 32 } | 29 } |
| 33 _FutureImpl future = this.future; | 30 _FutureImpl future = this.future; |
| 34 future._setError(asyncError); | 31 future._setError(error); |
| 35 } | 32 } |
| 36 | 33 |
| 37 bool get isCompleted => _isComplete; | 34 bool get isCompleted => _isComplete; |
| 38 } | 35 } |
| 39 | 36 |
| 40 /** | 37 /** |
| 41 * A listener on a future. | 38 * A listener on a future. |
| 42 * | 39 * |
| 43 * When the future completes, the [_sendValue] or [_sendError] method | 40 * When the future completes, the [_sendValue] or [_sendError] method |
| 44 * is invoked with the result. | 41 * is invoked with the result. |
| 45 * | 42 * |
| 46 * Listeners are kept in a linked list. | 43 * Listeners are kept in a linked list. |
| 47 */ | 44 */ |
| 48 abstract class _FutureListener<T> { | 45 abstract class _FutureListener<T> { |
| 49 _FutureListener _nextListener; | 46 _FutureListener _nextListener; |
| 50 factory _FutureListener.wrap(_FutureImpl future) { | 47 factory _FutureListener.wrap(_FutureImpl future) { |
| 51 return new _FutureListenerWrapper(future); | 48 return new _FutureListenerWrapper(future); |
| 52 } | 49 } |
| 53 void _sendValue(T value); | 50 void _sendValue(T value); |
| 54 void _sendError(AsyncError error); | 51 void _sendError(error); |
| 55 } | 52 } |
| 56 | 53 |
| 57 /** Adapter for a [_FutureImpl] to be a future result listener. */ | 54 /** Adapter for a [_FutureImpl] to be a future result listener. */ |
| 58 class _FutureListenerWrapper<T> implements _FutureListener<T> { | 55 class _FutureListenerWrapper<T> implements _FutureListener<T> { |
| 59 _FutureImpl future; | 56 _FutureImpl future; |
| 60 _FutureListener _nextListener; | 57 _FutureListener _nextListener; |
| 61 _FutureListenerWrapper(this.future); | 58 _FutureListenerWrapper(this.future); |
| 62 _sendValue(T value) { future._setValue(value); } | 59 _sendValue(T value) { future._setValue(value); } |
| 63 _sendError(AsyncError error) { future._setError(error); } | 60 _sendError(error) { future._setError(error); } |
| 64 } | 61 } |
| 65 | 62 |
| 66 class _FutureImpl<T> implements Future<T> { | 63 class _FutureImpl<T> implements Future<T> { |
| 67 static const int _INCOMPLETE = 0; | 64 static const int _INCOMPLETE = 0; |
| 68 static const int _VALUE = 1; | 65 static const int _VALUE = 1; |
| 69 static const int _ERROR = 2; | 66 static const int _ERROR = 2; |
| 70 static const int _UNHANDLED_ERROR = 4; | 67 static const int _UNHANDLED_ERROR = 4; |
| 71 | 68 |
| 72 /** Whether the future is complete, and as what. */ | 69 /** Whether the future is complete, and as what. */ |
| 73 int _state = _INCOMPLETE; | 70 int _state = _INCOMPLETE; |
| 74 | 71 |
| 75 bool get _isComplete => _state != _INCOMPLETE; | 72 bool get _isComplete => _state != _INCOMPLETE; |
| 76 bool get _hasValue => _state == _VALUE; | 73 bool get _hasValue => _state == _VALUE; |
| 77 bool get _hasError => (_state & _ERROR) != 0; | 74 bool get _hasError => (_state & _ERROR) != 0; |
| 78 bool get _hasUnhandledError => (_state & _UNHANDLED_ERROR) != 0; | 75 bool get _hasUnhandledError => (_state & _UNHANDLED_ERROR) != 0; |
| 79 | 76 |
| 80 void _clearUnhandledError() { | 77 void _clearUnhandledError() { |
| 81 // Works because _UNHANDLED_ERROR is highest bit in use. | 78 // Works because _UNHANDLED_ERROR is highest bit in use. |
| 82 _state &= ~_UNHANDLED_ERROR; | 79 _state &= ~_UNHANDLED_ERROR; |
| 83 } | 80 } |
| 84 | 81 |
| 85 /** | 82 /** |
| 86 * Either the result, or a list of listeners until the future completes. | 83 * Either the result, or a list of listeners until the future completes. |
| 87 * | 84 * |
| 88 * The result of the future is either a value or an [AsyncError]. | 85 * The result of the future is either a value or an error. |
| 89 * A result is only stored when the future has completed. | 86 * A result is only stored when the future has completed. |
| 90 * | 87 * |
| 91 * The listeners is an internally linked list of [_FutureListener]s. | 88 * The listeners is an internally linked list of [_FutureListener]s. |
| 92 * Listeners are only remembered while the future is not yet complete. | 89 * Listeners are only remembered while the future is not yet complete. |
| 93 * | 90 * |
| 94 * Since the result and the listeners cannot occur at the same time, | 91 * Since the result and the listeners cannot occur at the same time, |
| 95 * we can use the same field for both. | 92 * we can use the same field for both. |
| 96 */ | 93 */ |
| 97 var _resultOrListeners; | 94 var _resultOrListeners; |
| 98 | 95 |
| 99 _FutureImpl(); | 96 _FutureImpl(); |
| 100 | 97 |
| 101 _FutureImpl.immediate(T value) { | 98 _FutureImpl.immediate(T value) { |
| 102 _state = _VALUE; | 99 _state = _VALUE; |
| 103 _resultOrListeners = value; | 100 _resultOrListeners = value; |
| 104 } | 101 } |
| 105 | 102 |
| 106 _FutureImpl.immediateError(var error, [Object stackTrace]) { | 103 _FutureImpl.immediateError(var error, [Object stackTrace]) { |
| 107 AsyncError asyncError; | 104 if (stackTrace != null) { |
| 108 if (error is AsyncError) { | 105 // Force stack trace onto error, even if it had already one. |
| 109 asyncError = error; | 106 _attachStackTrace(error, stackTrace); |
| 110 } else { | |
| 111 asyncError = new AsyncError(error, stackTrace); | |
| 112 } | 107 } |
| 113 _setError(asyncError); | 108 _setError(error); |
| 114 } | 109 } |
| 115 | 110 |
| 116 factory _FutureImpl.wait(Iterable<Future> futures) { | 111 factory _FutureImpl.wait(Iterable<Future> futures) { |
| 117 Completer completer; | 112 Completer completer; |
| 118 // List collecting values from the futures. | 113 // List collecting values from the futures. |
| 119 // Set to null if an error occurs. | 114 // Set to null if an error occurs. |
| 120 List values; | 115 List values; |
| 121 void handleError(error) { | 116 void handleError(error) { |
| 122 if (values != null) { | 117 if (values != null) { |
| 123 values = null; | 118 values = null; |
| 124 completer.completeError(error.error, error.stackTrace); | 119 completer.completeError(error); |
| 125 } | 120 } |
| 126 } | 121 } |
| 127 // As each future completes, put its value into the corresponding | 122 // As each future completes, put its value into the corresponding |
| 128 // position in the list of values. | 123 // position in the list of values. |
| 129 int remaining = 0; | 124 int remaining = 0; |
| 130 for (Future future in futures) { | 125 for (Future future in futures) { |
| 131 int pos = remaining++; | 126 int pos = remaining++; |
| 132 future.catchError(handleError).then((Object value) { | 127 future.catchError(handleError).then((Object value) { |
| 133 if (values == null) return null; | 128 if (values == null) return null; |
| 134 values[pos] = value; | 129 values[pos] = value; |
| 135 remaining--; | 130 remaining--; |
| 136 if (remaining == 0) { | 131 if (remaining == 0) { |
| 137 completer.complete(values); | 132 completer.complete(values); |
| 138 } | 133 } |
| 139 }); | 134 }); |
| 140 } | 135 } |
| 141 if (remaining == 0) { | 136 if (remaining == 0) { |
| 142 return new Future.immediate(const []); | 137 return new Future.immediate(const []); |
| 143 } | 138 } |
| 144 values = new List(remaining); | 139 values = new List(remaining); |
| 145 completer = new Completer<List>(); | 140 completer = new Completer<List>(); |
| 146 return completer.future; | 141 return completer.future; |
| 147 } | 142 } |
| 148 | 143 |
| 149 Future then(f(T value), { onError(AsyncError error) }) { | 144 Future then(f(T value), { onError(error) }) { |
| 150 if (!_isComplete) { | 145 if (!_isComplete) { |
| 151 if (onError == null) { | 146 if (onError == null) { |
| 152 return new _ThenFuture(f).._subscribeTo(this); | 147 return new _ThenFuture(f).._subscribeTo(this); |
| 153 } | 148 } |
| 154 return new _SubscribeFuture(f, onError).._subscribeTo(this); | 149 return new _SubscribeFuture(f, onError).._subscribeTo(this); |
| 155 } | 150 } |
| 156 if (_hasError) { | 151 if (_hasError) { |
| 157 if (onError != null) { | 152 if (onError != null) { |
| 158 return _handleError(onError, null); | 153 return _handleError(onError, null); |
| 159 } | 154 } |
| 160 // The "f" funtion will never be called, so just return | 155 // The "f" funtion will never be called, so just return |
| 161 // a future that delegates to this. We don't want to return | 156 // a future that delegates to this. We don't want to return |
| 162 // this itself to give a signal that the future is complete. | 157 // this itself to give a signal that the future is complete. |
| 163 return new _FutureWrapper(this); | 158 return new _FutureWrapper(this); |
| 164 } else { | 159 } else { |
| 165 assert(_hasValue); | 160 assert(_hasValue); |
| 166 return _handleValue(f); | 161 return _handleValue(f); |
| 167 } | 162 } |
| 168 } | 163 } |
| 169 | 164 |
| 170 Future catchError(f(AsyncError asyncError), { bool test(error) }) { | 165 Future catchError(f(error), { bool test(error) }) { |
| 171 if (_hasValue) { | 166 if (_hasValue) { |
| 172 return new _FutureWrapper(this); | 167 return new _FutureWrapper(this); |
| 173 } | 168 } |
| 174 if (!_isComplete) { | 169 if (!_isComplete) { |
| 175 return new _CatchErrorFuture(f, test).._subscribeTo(this); | 170 return new _CatchErrorFuture(f, test).._subscribeTo(this); |
| 176 } else { | 171 } else { |
| 177 return _handleError(f, test); | 172 return _handleError(f, test); |
| 178 } | 173 } |
| 179 } | 174 } |
| 180 | 175 |
| 181 Future<T> whenComplete(action()) { | 176 Future<T> whenComplete(action()) { |
| 182 _WhenFuture<T> whenFuture = new _WhenFuture<T>(action); | 177 _WhenFuture<T> whenFuture = new _WhenFuture<T>(action); |
| 183 if (!_isComplete) { | 178 if (!_isComplete) { |
| 184 _addListener(whenFuture); | 179 _addListener(whenFuture); |
| 185 } else if (_hasValue) { | 180 } else if (_hasValue) { |
| 186 T value = _resultOrListeners; | 181 T value = _resultOrListeners; |
| 187 Timer.run(() { | 182 Timer.run(() { |
| 188 whenFuture._sendValue(value); | 183 whenFuture._sendValue(value); |
| 189 }); | 184 }); |
| 190 } else { | 185 } else { |
| 191 assert(_hasError); | 186 assert(_hasError); |
| 192 _clearUnhandledError(); | 187 _clearUnhandledError(); |
| 193 AsyncError error = _resultOrListeners; | 188 var error = _resultOrListeners; |
| 194 Timer.run(() { | 189 Timer.run(() { |
| 195 whenFuture._sendError(error); | 190 whenFuture._sendError(error); |
| 196 }); | 191 }); |
| 197 } | 192 } |
| 198 return whenFuture; | 193 return whenFuture; |
| 199 } | 194 } |
| 200 | 195 |
| 201 /** Handle a late listener on a completed future with a value. */ | 196 /** Handle a late listener on a completed future with a value. */ |
| 202 Future _handleValue(onValue(var value)) { | 197 Future _handleValue(onValue(var value)) { |
| 203 assert(_hasValue); | 198 assert(_hasValue); |
| 204 _ThenFuture thenFuture = new _ThenFuture(onValue); | 199 _ThenFuture thenFuture = new _ThenFuture(onValue); |
| 205 T value = _resultOrListeners; | 200 T value = _resultOrListeners; |
| 206 Timer.run(() { thenFuture._sendValue(value); }); | 201 Timer.run(() { thenFuture._sendValue(value); }); |
| 207 return thenFuture; | 202 return thenFuture; |
| 208 } | 203 } |
| 209 | 204 |
| 210 /** Handle a late listener on a completed future with an error. */ | 205 /** Handle a late listener on a completed future with an error. */ |
| 211 Future _handleError(onError(AsyncError error), bool test(error)) { | 206 Future _handleError(onError(error), bool test(error)) { |
| 212 assert(_hasError); | 207 assert(_hasError); |
| 213 _clearUnhandledError(); | 208 _clearUnhandledError(); |
| 214 AsyncError error = _resultOrListeners; | 209 var error = _resultOrListeners; |
| 215 _CatchErrorFuture errorFuture = new _CatchErrorFuture(onError, test); | 210 _CatchErrorFuture errorFuture = new _CatchErrorFuture(onError, test); |
| 216 Timer.run(() { errorFuture._sendError(error); }); | 211 Timer.run(() { errorFuture._sendError(error); }); |
| 217 return errorFuture; | 212 return errorFuture; |
| 218 } | 213 } |
| 219 | 214 |
| 220 Stream<T> asStream() => new Stream.fromFuture(this); | 215 Stream<T> asStream() => new Stream.fromFuture(this); |
| 221 | 216 |
| 222 void _setValue(T value) { | 217 void _setValue(T value) { |
| 223 if (_isComplete) throw new StateError("Future already completed"); | 218 if (_isComplete) throw new StateError("Future already completed"); |
| 224 _FutureListener listeners = _removeListeners(); | 219 _FutureListener listeners = _removeListeners(); |
| 225 _state = _VALUE; | 220 _state = _VALUE; |
| 226 _resultOrListeners = value; | 221 _resultOrListeners = value; |
| 227 while (listeners != null) { | 222 while (listeners != null) { |
| 228 _FutureListener listener = listeners; | 223 _FutureListener listener = listeners; |
| 229 listeners = listener._nextListener; | 224 listeners = listener._nextListener; |
| 230 listener._nextListener = null; | 225 listener._nextListener = null; |
| 231 listener._sendValue(value); | 226 listener._sendValue(value); |
| 232 } | 227 } |
| 233 } | 228 } |
| 234 | 229 |
| 235 void _setError(AsyncError error) { | 230 void _setError(error) { |
| 236 if (_isComplete) throw new StateError("Future already completed"); | 231 if (_isComplete) throw new StateError("Future already completed"); |
| 237 _FutureListener listeners = _removeListeners(); | 232 _FutureListener listeners = _removeListeners(); |
| 238 _state = _ERROR; | 233 _state = _ERROR; |
| 239 _resultOrListeners = error; | 234 _resultOrListeners = error; |
| 240 if (listeners == null) { | 235 if (listeners == null) { |
| 241 _scheduleUnhandledError(); | 236 _scheduleUnhandledError(); |
| 242 return; | 237 return; |
| 243 } | 238 } |
| 244 do { | 239 do { |
| 245 _FutureListener listener = listeners; | 240 _FutureListener listener = listeners; |
| 246 listeners = listener._nextListener; | 241 listeners = listener._nextListener; |
| 247 listener._nextListener = null; | 242 listener._nextListener = null; |
| 248 listener._sendError(error); | 243 listener._sendError(error); |
| 249 } while (listeners != null); | 244 } while (listeners != null); |
| 250 } | 245 } |
| 251 | 246 |
| 252 void _scheduleUnhandledError() { | 247 void _scheduleUnhandledError() { |
| 253 _state |= _UNHANDLED_ERROR; | 248 _state |= _UNHANDLED_ERROR; |
| 254 // Wait for the rest of the current event's duration to see | 249 // Wait for the rest of the current event's duration to see |
| 255 // if a subscriber is added to handle the error. | 250 // if a subscriber is added to handle the error. |
| 256 Timer.run(() { | 251 Timer.run(() { |
| 257 if (_hasUnhandledError) { | 252 if (_hasUnhandledError) { |
| 258 // No error handler has been added since the error was set. | 253 // No error handler has been added since the error was set. |
| 259 _clearUnhandledError(); | 254 _clearUnhandledError(); |
| 260 AsyncError error = _resultOrListeners; | 255 var error = _resultOrListeners; |
| 261 print("Uncaught Error: ${error.error}"); | 256 print("Uncaught Error: ${error}"); |
| 262 if (error.stackTrace != null) { | 257 var trace = getAttachedStackTrace(error); |
| 263 print("Stack Trace:\n${error.stackTrace}\n"); | 258 if (trace != null) { |
| 259 print("Stack Trace:\n$trace\n"); |
| 264 } | 260 } |
| 265 throw error.error; | 261 throw error; |
| 266 } | 262 } |
| 267 }); | 263 }); |
| 268 } | 264 } |
| 269 | 265 |
| 270 void _addListener(_FutureListener listener) { | 266 void _addListener(_FutureListener listener) { |
| 271 assert(!_isComplete); | 267 assert(!_isComplete); |
| 272 assert(listener._nextListener == null); | 268 assert(listener._nextListener == null); |
| 273 listener._nextListener = _resultOrListeners; | 269 listener._nextListener = _resultOrListeners; |
| 274 _resultOrListeners = listener; | 270 _resultOrListeners = listener; |
| 275 } | 271 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 * Subclasses override [_sendValue]/[_sendError] to intercept | 340 * Subclasses override [_sendValue]/[_sendError] to intercept |
| 345 * the results of a previous future. | 341 * the results of a previous future. |
| 346 */ | 342 */ |
| 347 abstract class _TransformFuture<S, T> extends _FutureImpl<T> | 343 abstract class _TransformFuture<S, T> extends _FutureImpl<T> |
| 348 implements _FutureListener<S> { | 344 implements _FutureListener<S> { |
| 349 // _FutureListener implementation. | 345 // _FutureListener implementation. |
| 350 _FutureListener _nextListener; | 346 _FutureListener _nextListener; |
| 351 | 347 |
| 352 void _sendValue(S value); | 348 void _sendValue(S value); |
| 353 | 349 |
| 354 void _sendError(AsyncError error); | 350 void _sendError(error); |
| 355 | 351 |
| 356 void _subscribeTo(_FutureImpl future) { | 352 void _subscribeTo(_FutureImpl future) { |
| 357 future._addListener(this); | 353 future._addListener(this); |
| 358 } | 354 } |
| 359 } | 355 } |
| 360 | 356 |
| 361 /** The onValue and onError handlers return either a value or a future */ | 357 /** The onValue and onError handlers return either a value or a future */ |
| 362 typedef dynamic _FutureOnValue<T>(T value); | 358 typedef dynamic _FutureOnValue<T>(T value); |
| 363 typedef dynamic _FutureOnError(AsyncError error); | 359 typedef dynamic _FutureOnError(error); |
| 364 /** Test used by [Future.catchError] to handle skip some errors. */ | 360 /** Test used by [Future.catchError] to handle skip some errors. */ |
| 365 typedef bool _FutureErrorTest(var error); | 361 typedef bool _FutureErrorTest(var error); |
| 366 /** Used by [WhenFuture]. */ | 362 /** Used by [WhenFuture]. */ |
| 367 typedef _FutureAction(); | 363 typedef _FutureAction(); |
| 368 | 364 |
| 369 /** Future returned by [Future.then] with no [:onError:] parameter. */ | 365 /** Future returned by [Future.then] with no [:onError:] parameter. */ |
| 370 class _ThenFuture<S, T> extends _TransformFuture<S, T> { | 366 class _ThenFuture<S, T> extends _TransformFuture<S, T> { |
| 371 // TODO(ahe): Restore type when feature is implemented in dart2js | 367 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 372 // checked mode. | 368 // checked mode. |
| 373 final /* _FutureOnValue<S> */ _onValue; | 369 final /* _FutureOnValue<S> */ _onValue; |
| 374 | 370 |
| 375 _ThenFuture(this._onValue); | 371 _ThenFuture(this._onValue); |
| 376 | 372 |
| 377 _sendValue(S value) { | 373 _sendValue(S value) { |
| 378 assert(_onValue != null); | 374 assert(_onValue != null); |
| 379 var result; | 375 var result; |
| 380 try { | 376 try { |
| 381 result = _onValue(value); | 377 result = _onValue(value); |
| 382 } on AsyncError catch (e) { | |
| 383 _setError(e); | |
| 384 return; | |
| 385 } catch (e, s) { | 378 } catch (e, s) { |
| 386 _setError(new AsyncError(e, s)); | 379 _setError(_asyncError(e, s)); |
| 387 return; | 380 return; |
| 388 } | 381 } |
| 389 _setOrChainValue(result); | 382 _setOrChainValue(result); |
| 390 } | 383 } |
| 391 | 384 |
| 392 void _sendError(AsyncError error) { | 385 void _sendError(error) { |
| 393 _setError(error); | 386 _setError(error); |
| 394 } | 387 } |
| 395 } | 388 } |
| 396 | 389 |
| 397 /** Future returned by [Future.catchError]. */ | 390 /** Future returned by [Future.catchError]. */ |
| 398 class _CatchErrorFuture<T> extends _TransformFuture<T,T> { | 391 class _CatchErrorFuture<T> extends _TransformFuture<T,T> { |
| 399 final _FutureErrorTest _test; | 392 final _FutureErrorTest _test; |
| 400 final _FutureOnError _onError; | 393 final _FutureOnError _onError; |
| 401 | 394 |
| 402 _CatchErrorFuture(this._onError, this._test); | 395 _CatchErrorFuture(this._onError, this._test); |
| 403 | 396 |
| 404 _sendValue(T value) { | 397 _sendValue(T value) { |
| 405 _setValue(value); | 398 _setValue(value); |
| 406 } | 399 } |
| 407 | 400 |
| 408 _sendError(AsyncError error) { | 401 _sendError(error) { |
| 409 assert(_onError != null); | 402 assert(_onError != null); |
| 410 // if _test is supplied, check if it returns true, otherwise just | 403 // if _test is supplied, check if it returns true, otherwise just |
| 411 // forward the error unmodified. | 404 // forward the error unmodified. |
| 412 if (_test != null) { | 405 if (_test != null) { |
| 413 bool matchesTest; | 406 bool matchesTest; |
| 414 try { | 407 try { |
| 415 matchesTest = _test(error.error); | 408 matchesTest = _test(error); |
| 416 } catch (e, s) { | 409 } catch (e, s) { |
| 417 _setError(new AsyncError.withCause(e, s, error)); | 410 _setError(_asyncError(e, s)); |
| 418 return; | 411 return; |
| 419 } | 412 } |
| 420 if (!matchesTest) { | 413 if (!matchesTest) { |
| 421 _setError(error); | 414 _setError(error); |
| 422 return; | 415 return; |
| 423 } | 416 } |
| 424 } | 417 } |
| 425 // Act on the error, and use the result as this future's result. | 418 // Act on the error, and use the result as this future's result. |
| 426 var result; | 419 var result; |
| 427 try { | 420 try { |
| 428 result = _onError(error); | 421 result = _onError(error); |
| 429 } on AsyncError catch (e) { | |
| 430 _setError(e); | |
| 431 return; | |
| 432 } catch (e, s) { | 422 } catch (e, s) { |
| 433 _setError(new AsyncError.withCause(e, s, error)); | 423 _setError(_asyncError(e, s)); |
| 434 return; | 424 return; |
| 435 } | 425 } |
| 436 _setOrChainValue(result); | 426 _setOrChainValue(result); |
| 437 } | 427 } |
| 438 } | 428 } |
| 439 | 429 |
| 440 /** Future returned by [Future.then] with an [:onError:] parameter. */ | 430 /** Future returned by [Future.then] with an [:onError:] parameter. */ |
| 441 class _SubscribeFuture<S, T> extends _ThenFuture<S, T> { | 431 class _SubscribeFuture<S, T> extends _ThenFuture<S, T> { |
| 442 final _FutureOnError _onError; | 432 final _FutureOnError _onError; |
| 443 | 433 |
| 444 _SubscribeFuture(onValue(S value), this._onError) : super(onValue); | 434 _SubscribeFuture(onValue(S value), this._onError) : super(onValue); |
| 445 | 435 |
| 446 // The _sendValue method is inherited from ThenFuture. | 436 // The _sendValue method is inherited from ThenFuture. |
| 447 | 437 |
| 448 void _sendError(AsyncError error) { | 438 void _sendError(error) { |
| 449 assert(_onError != null); | 439 assert(_onError != null); |
| 450 var result; | 440 var result; |
| 451 try { | 441 try { |
| 452 result = _onError(error); | 442 result = _onError(error); |
| 453 } on AsyncError catch (e) { | |
| 454 _setError(e); | |
| 455 return; | |
| 456 } catch (e, s) { | 443 } catch (e, s) { |
| 457 _setError(new AsyncError.withCause(e, s, error)); | 444 _setError(_asyncError(e, s)); |
| 458 return; | 445 return; |
| 459 } | 446 } |
| 460 _setOrChainValue(result); | 447 _setOrChainValue(result); |
| 461 } | 448 } |
| 462 } | 449 } |
| 463 | 450 |
| 464 /** Future returned by [Future.whenComplete]. */ | 451 /** Future returned by [Future.whenComplete]. */ |
| 465 class _WhenFuture<T> extends _TransformFuture<T, T> { | 452 class _WhenFuture<T> extends _TransformFuture<T, T> { |
| 466 final _FutureAction _action; | 453 final _FutureAction _action; |
| 467 | 454 |
| 468 _WhenFuture(this._action); | 455 _WhenFuture(this._action); |
| 469 | 456 |
| 470 void _sendValue(T value) { | 457 void _sendValue(T value) { |
| 471 try { | 458 try { |
| 472 var result = _action(); | 459 var result = _action(); |
| 473 if (result is Future) { | 460 if (result is Future) { |
| 474 Future resultFuture = result; | 461 Future resultFuture = result; |
| 475 resultFuture.then((_) { | 462 resultFuture.then((_) { |
| 476 _setValue(value); | 463 _setValue(value); |
| 477 }, onError: _setError); | 464 }, onError: _setError); |
| 478 return; | 465 return; |
| 479 } | 466 } |
| 480 } on AsyncError catch (e) { | |
| 481 _setError(e); | |
| 482 return; | |
| 483 } catch (e, s) { | 467 } catch (e, s) { |
| 484 _setError(new AsyncError(e, s)); | 468 _setError(_asyncError(e, s)); |
| 485 return; | 469 return; |
| 486 } | 470 } |
| 487 _setValue(value); | 471 _setValue(value); |
| 488 } | 472 } |
| 489 | 473 |
| 490 void _sendError(AsyncError error) { | 474 void _sendError(error) { |
| 491 try { | 475 try { |
| 492 var result = _action(); | 476 var result = _action(); |
| 493 if (result is Future) { | 477 if (result is Future) { |
| 494 Future resultFuture = result; | 478 Future resultFuture = result; |
| 495 // TODO(lrn): Find a way to combine [error] into [e]. | 479 // TODO(lrn): Find a way to combine [error] into [e]. |
| 496 resultFuture.then((_) { | 480 resultFuture.then((_) { |
| 497 _setError(error); | 481 _setError(error); |
| 498 }, onError: _setError); | 482 }, onError: _setError); |
| 499 return; | 483 return; |
| 500 } | 484 } |
| 501 } on AsyncError catch (e) { | |
| 502 error = e; | |
| 503 } catch (e, s) { | 485 } catch (e, s) { |
| 504 error = new AsyncError.withCause(e, s, error); | 486 error = _asyncError(e, s); |
| 505 } | 487 } |
| 506 _setError(error); | 488 _setError(error); |
| 507 } | 489 } |
| 508 } | 490 } |
| 509 | 491 |
| 510 /** | 492 /** |
| 511 * Thin wrapper around a [Future]. | 493 * Thin wrapper around a [Future]. |
| 512 * | 494 * |
| 513 * This is used to return a "new" [Future] that effectively work just | 495 * This is used to return a "new" [Future] that effectively work just |
| 514 * as an existing [Future], without making this discoverable by comparing | 496 * as an existing [Future], without making this discoverable by comparing |
| 515 * identities. | 497 * identities. |
| 516 */ | 498 */ |
| 517 class _FutureWrapper<T> implements Future<T> { | 499 class _FutureWrapper<T> implements Future<T> { |
| 518 final Future<T> _future; | 500 final Future<T> _future; |
| 519 | 501 |
| 520 _FutureWrapper(this._future); | 502 _FutureWrapper(this._future); |
| 521 | 503 |
| 522 Future then(function(T value), { onError(AsyncError error) }) { | 504 Future then(function(T value), { onError(error) }) { |
| 523 return _future.then(function, onError: onError); | 505 return _future.then(function, onError: onError); |
| 524 } | 506 } |
| 525 | 507 |
| 526 Future catchError(function(AsyncError error), {bool test(var error)}) { | 508 Future catchError(function(error), {bool test(var error)}) { |
| 527 return _future.catchError(function, test: test); | 509 return _future.catchError(function, test: test); |
| 528 } | 510 } |
| 529 | 511 |
| 530 Future<T> whenComplete(action()) { | 512 Future<T> whenComplete(action()) { |
| 531 return _future.whenComplete(action); | 513 return _future.whenComplete(action); |
| 532 } | 514 } |
| 533 | 515 |
| 534 Stream<T> asStream() => new Stream.fromFuture(_future); | 516 Stream<T> asStream() => new Stream.fromFuture(_future); |
| 535 } | 517 } |
| OLD | NEW |