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 |