Chromium Code Reviews| 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.incrementOpenCallbackCount(); | |
| 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.decrementOpenCallbackCount(); | |
| 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.decrementOpenCallbackCount(); | |
| 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 switches. It guarantees that no | |
|
Lasse Reichstein Nielsen
2013/05/21 08:19:57
Need more explanation.
What is it installed on? By
floitsch
2013/05/21 18:08:32
Done.
| |
| 104 * error runs through zone boundaries that change error-handling. | |
| 105 */ | |
| 106 class _ErrorZoneBoundaryListener implements _FutureListener { | |
| 107 _FutureListener _nextListener; | |
| 108 final _FutureListener _listener; | |
| 109 | |
| 110 _ErrorZoneBoundaryListener(this._listener) { | |
| 111 assert(!_nextListener._inSameErrorZone(_Zone.current)); | |
| 112 } | |
| 113 | |
| 114 bool _inSameErrorZone(_Zone otherZone) { | |
|
Lasse Reichstein Nielsen
2013/05/21 08:19:57
Why is it not supported? Could it just return fals
floitsch
2013/05/21 18:08:32
It's basically an assert. It could return anything
| |
| 115 throw new UnsupportedError( | |
| 116 "A Zone boundary doesn't support the inSameErrorZone test."); | |
| 117 } | |
| 118 | |
| 119 void _sendValue(value) { | |
| 120 _listener._sendValue(value); | |
| 121 } | |
| 122 | |
| 123 void _sendError(error) { | |
| 124 // We are not allowed to send an error from one error-zone to another. | |
| 125 // This is the whole purpose of this class. | |
| 126 _Zone.current._addError(error); | |
| 127 } | |
| 86 } | 128 } |
| 87 | 129 |
| 88 class _FutureImpl<T> implements Future<T> { | 130 class _FutureImpl<T> implements Future<T> { |
| 89 static const int _INCOMPLETE = 0; | 131 static const int _INCOMPLETE = 0; |
| 90 static const int _VALUE = 1; | 132 static const int _VALUE = 1; |
| 91 static const int _ERROR = 2; | 133 static const int _ERROR = 2; |
| 92 static const int _UNHANDLED_ERROR = 4; | 134 static const int _UNHANDLED_ERROR = 4; |
| 93 | 135 |
| 94 /** Whether the future is complete, and as what. */ | 136 /** Whether the future is complete, and as what. */ |
| 95 int _state = _INCOMPLETE; | 137 int _state = _INCOMPLETE; |
| 96 | 138 |
| 139 final _Zone _zone = _Zone.current.fork(); | |
| 140 | |
| 97 bool get _isComplete => _state != _INCOMPLETE; | 141 bool get _isComplete => _state != _INCOMPLETE; |
| 98 bool get _hasValue => _state == _VALUE; | 142 bool get _hasValue => _state == _VALUE; |
| 99 bool get _hasError => (_state & _ERROR) != 0; | 143 bool get _hasError => (_state & _ERROR) != 0; |
| 100 bool get _hasUnhandledError => (_state & _UNHANDLED_ERROR) != 0; | 144 bool get _hasUnhandledError => (_state & _UNHANDLED_ERROR) != 0; |
| 101 | 145 |
| 102 void _clearUnhandledError() { | 146 void _clearUnhandledError() { |
| 103 // Works because _UNHANDLED_ERROR is highest bit in use. | 147 // Works because _UNHANDLED_ERROR is highest bit in use. |
| 104 _state &= ~_UNHANDLED_ERROR; | 148 _state &= ~_UNHANDLED_ERROR; |
| 105 } | 149 } |
| 106 | 150 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 Future catchError(f(error), { bool test(error) }) { | 220 Future catchError(f(error), { bool test(error) }) { |
| 177 return new _CatchErrorFuture(f, test).._subscribeTo(this); | 221 return new _CatchErrorFuture(f, test).._subscribeTo(this); |
| 178 } | 222 } |
| 179 | 223 |
| 180 Future<T> whenComplete(action()) { | 224 Future<T> whenComplete(action()) { |
| 181 return new _WhenFuture<T>(action).._subscribeTo(this); | 225 return new _WhenFuture<T>(action).._subscribeTo(this); |
| 182 } | 226 } |
| 183 | 227 |
| 184 Stream<T> asStream() => new Stream.fromFuture(this); | 228 Stream<T> asStream() => new Stream.fromFuture(this); |
| 185 | 229 |
| 230 bool _inSameErrorZone(_Zone otherZone) { | |
| 231 return _zone.inSameErrorZone(otherZone); | |
| 232 } | |
| 233 | |
| 186 void _setValue(T value) { | 234 void _setValue(T value) { |
| 187 if (_isComplete) throw new StateError("Future already completed"); | 235 if (_isComplete) throw new StateError("Future already completed"); |
| 188 _FutureListener listeners = _removeListeners(); | 236 _FutureListener listeners = _removeListeners(); |
| 189 _state = _VALUE; | 237 _state = _VALUE; |
| 190 _resultOrListeners = value; | 238 _resultOrListeners = value; |
| 191 while (listeners != null) { | 239 while (listeners != null) { |
| 192 _FutureListener listener = listeners; | 240 _FutureListener listener = listeners; |
| 193 listeners = listener._nextListener; | 241 listeners = listener._nextListener; |
| 194 listener._nextListener = null; | 242 listener._nextListener = null; |
| 195 listener._sendValue(value); | 243 listener._sendValue(value); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 215 | 263 |
| 216 void _scheduleUnhandledError() { | 264 void _scheduleUnhandledError() { |
| 217 _state |= _UNHANDLED_ERROR; | 265 _state |= _UNHANDLED_ERROR; |
| 218 // Wait for the rest of the current event's duration to see | 266 // Wait for the rest of the current event's duration to see |
| 219 // if a subscriber is added to handle the error. | 267 // if a subscriber is added to handle the error. |
| 220 runAsync(() { | 268 runAsync(() { |
| 221 if (_hasUnhandledError) { | 269 if (_hasUnhandledError) { |
| 222 // No error handler has been added since the error was set. | 270 // No error handler has been added since the error was set. |
| 223 _clearUnhandledError(); | 271 _clearUnhandledError(); |
| 224 var error = _resultOrListeners; | 272 var error = _resultOrListeners; |
| 225 print("Uncaught Error: ${error}"); | 273 _zone.handleUncaughtError(error); |
| 226 var trace = getAttachedStackTrace(error); | |
| 227 if (trace != null) { | |
| 228 print("Stack Trace:\n$trace\n"); | |
| 229 } | |
| 230 throw error; | |
| 231 } | 274 } |
| 232 }); | 275 }); |
| 233 } | 276 } |
| 234 | 277 |
| 235 void _addListener(_FutureListener listener) { | 278 void _addListener(_FutureListener listener) { |
| 279 assert(listener._nextListener == null); | |
| 280 if (!listener._inSameErrorZone(_zone)) { | |
| 281 listener = new _ErrorZoneBoundaryListener(listener); | |
| 282 } | |
| 236 if (_isComplete) { | 283 if (_isComplete) { |
| 237 _clearUnhandledError(); | 284 _clearUnhandledError(); |
| 238 // Handle late listeners asynchronously. | 285 // Handle late listeners asynchronously. |
| 239 runAsync(() { | 286 runAsync(() { |
| 240 if (_hasValue) { | 287 if (_hasValue) { |
| 241 T value = _resultOrListeners; | 288 T value = _resultOrListeners; |
| 242 listener._sendValue(value); | 289 listener._sendValue(value); |
| 243 } else { | 290 } else { |
| 244 assert(_hasError); | 291 assert(_hasError); |
| 245 listener._sendError(_resultOrListeners); | 292 listener._sendError(_resultOrListeners); |
| 246 } | 293 } |
| 247 }); | 294 }); |
| 248 } else { | 295 } else { |
| 249 assert(!_isComplete); | 296 assert(!_isComplete); |
| 250 assert(listener._nextListener == null); | |
| 251 listener._nextListener = _resultOrListeners; | 297 listener._nextListener = _resultOrListeners; |
| 252 _resultOrListeners = listener; | 298 _resultOrListeners = listener; |
| 253 } | 299 } |
| 254 } | 300 } |
| 255 | 301 |
| 256 _FutureListener _removeListeners() { | 302 _FutureListener _removeListeners() { |
| 257 // Reverse listeners before returning them, so the resulting list is in | 303 // Reverse listeners before returning them, so the resulting list is in |
| 258 // subscription order. | 304 // subscription order. |
| 259 assert(!_isComplete); | 305 assert(!_isComplete); |
| 260 _FutureListener current = _resultOrListeners; | 306 _FutureListener current = _resultOrListeners; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 * | 367 * |
| 322 * A transforming future is itself a future and a future listener. | 368 * A transforming future is itself a future and a future listener. |
| 323 * Subclasses override [_sendValue]/[_sendError] to intercept | 369 * Subclasses override [_sendValue]/[_sendError] to intercept |
| 324 * the results of a previous future. | 370 * the results of a previous future. |
| 325 */ | 371 */ |
| 326 abstract class _TransformFuture<S, T> extends _FutureImpl<T> | 372 abstract class _TransformFuture<S, T> extends _FutureImpl<T> |
| 327 implements _FutureListener<S> { | 373 implements _FutureListener<S> { |
| 328 // _FutureListener implementation. | 374 // _FutureListener implementation. |
| 329 _FutureListener _nextListener; | 375 _FutureListener _nextListener; |
| 330 | 376 |
| 331 void _sendValue(S value); | 377 _TransformFuture() { |
| 378 _zone.incrementOpenCallbackCount(); | |
| 379 } | |
| 332 | 380 |
| 333 void _sendError(error); | 381 void _sendValue(S value) { |
| 382 _zone.executeCallback(() => _zonedSendValue(value)); | |
| 383 } | |
| 384 | |
| 385 void _sendError(error) { | |
| 386 _zone.executeCallback(() => _zonedSendError(error)); | |
| 387 } | |
| 334 | 388 |
| 335 void _subscribeTo(_FutureImpl future) { | 389 void _subscribeTo(_FutureImpl future) { |
| 336 future._addListener(this); | 390 future._addListener(this); |
| 337 } | 391 } |
| 392 | |
| 393 void _zonedSendValue(S value); | |
| 394 void _zonedSendError(error); | |
| 338 } | 395 } |
| 339 | 396 |
| 340 /** The onValue and onError handlers return either a value or a future */ | 397 /** The onValue and onError handlers return either a value or a future */ |
| 341 typedef dynamic _FutureOnValue<T>(T value); | 398 typedef dynamic _FutureOnValue<T>(T value); |
| 342 typedef dynamic _FutureOnError(error); | 399 typedef dynamic _FutureOnError(error); |
| 343 /** Test used by [Future.catchError] to handle skip some errors. */ | 400 /** Test used by [Future.catchError] to handle skip some errors. */ |
| 344 typedef bool _FutureErrorTest(var error); | 401 typedef bool _FutureErrorTest(var error); |
| 345 /** Used by [WhenFuture]. */ | 402 /** Used by [WhenFuture]. */ |
| 346 typedef _FutureAction(); | 403 typedef _FutureAction(); |
| 347 | 404 |
| 348 /** Future returned by [Future.then] with no [:onError:] parameter. */ | 405 /** Future returned by [Future.then] with no [:onError:] parameter. */ |
| 349 class _ThenFuture<S, T> extends _TransformFuture<S, T> { | 406 class _ThenFuture<S, T> extends _TransformFuture<S, T> { |
| 350 // TODO(ahe): Restore type when feature is implemented in dart2js | 407 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 351 // checked mode. | 408 // checked mode. |
| 352 final /* _FutureOnValue<S> */ _onValue; | 409 final /* _FutureOnValue<S> */ _onValue; |
| 353 | 410 |
| 354 _ThenFuture(this._onValue); | 411 _ThenFuture(this._onValue); |
| 355 | 412 |
| 356 _sendValue(S value) { | 413 _zonedSendValue(S value) { |
| 357 assert(_onValue != null); | 414 assert(_onValue != null); |
| 358 var result; | 415 var result; |
| 359 try { | 416 try { |
| 360 result = _onValue(value); | 417 result = _onValue(value); |
| 361 } catch (e, s) { | 418 } catch (e, s) { |
| 362 _setError(_asyncError(e, s)); | 419 _setError(_asyncError(e, s)); |
| 363 return; | 420 return; |
| 364 } | 421 } |
| 365 _setOrChainValue(result); | 422 _setOrChainValue(result); |
| 366 } | 423 } |
| 367 | 424 |
| 368 void _sendError(error) { | 425 void _zonedSendError(error) { |
| 369 _setError(error); | 426 _setError(error); |
| 370 } | 427 } |
| 371 } | 428 } |
| 372 | 429 |
| 373 /** Future returned by [Future.catchError]. */ | 430 /** Future returned by [Future.catchError]. */ |
| 374 class _CatchErrorFuture<T> extends _TransformFuture<T,T> { | 431 class _CatchErrorFuture<T> extends _TransformFuture<T,T> { |
| 375 final _FutureErrorTest _test; | 432 final _FutureErrorTest _test; |
| 376 final _FutureOnError _onError; | 433 final _FutureOnError _onError; |
| 377 | 434 |
| 378 _CatchErrorFuture(this._onError, this._test); | 435 _CatchErrorFuture(this._onError, this._test); |
| 379 | 436 |
| 380 _sendValue(T value) { | 437 _zonedSendValue(T value) { |
| 381 _setValue(value); | 438 _setValue(value); |
| 382 } | 439 } |
| 383 | 440 |
| 384 _sendError(error) { | 441 _zonedSendError(error) { |
| 385 assert(_onError != null); | 442 assert(_onError != null); |
| 386 // if _test is supplied, check if it returns true, otherwise just | 443 // if _test is supplied, check if it returns true, otherwise just |
| 387 // forward the error unmodified. | 444 // forward the error unmodified. |
| 388 if (_test != null) { | 445 if (_test != null) { |
| 389 bool matchesTest; | 446 bool matchesTest; |
| 390 try { | 447 try { |
| 391 matchesTest = _test(error); | 448 matchesTest = _test(error); |
| 392 } catch (e, s) { | 449 } catch (e, s) { |
| 393 _setError(_asyncError(e, s)); | 450 _setError(_asyncError(e, s)); |
| 394 return; | 451 return; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 411 } | 468 } |
| 412 | 469 |
| 413 /** Future returned by [Future.then] with an [:onError:] parameter. */ | 470 /** Future returned by [Future.then] with an [:onError:] parameter. */ |
| 414 class _SubscribeFuture<S, T> extends _ThenFuture<S, T> { | 471 class _SubscribeFuture<S, T> extends _ThenFuture<S, T> { |
| 415 final _FutureOnError _onError; | 472 final _FutureOnError _onError; |
| 416 | 473 |
| 417 _SubscribeFuture(onValue(S value), this._onError) : super(onValue); | 474 _SubscribeFuture(onValue(S value), this._onError) : super(onValue); |
| 418 | 475 |
| 419 // The _sendValue method is inherited from ThenFuture. | 476 // The _sendValue method is inherited from ThenFuture. |
| 420 | 477 |
| 421 void _sendError(error) { | 478 void _zonedSendError(error) { |
| 422 assert(_onError != null); | 479 assert(_onError != null); |
| 423 var result; | 480 var result; |
| 424 try { | 481 try { |
| 425 result = _onError(error); | 482 result = _onError(error); |
| 426 } catch (e, s) { | 483 } catch (e, s) { |
| 427 _setError(_asyncError(e, s)); | 484 _setError(_asyncError(e, s)); |
| 428 return; | 485 return; |
| 429 } | 486 } |
| 430 _setOrChainValue(result); | 487 _setOrChainValue(result); |
| 431 } | 488 } |
| 432 } | 489 } |
| 433 | 490 |
| 434 /** Future returned by [Future.whenComplete]. */ | 491 /** Future returned by [Future.whenComplete]. */ |
| 435 class _WhenFuture<T> extends _TransformFuture<T, T> { | 492 class _WhenFuture<T> extends _TransformFuture<T, T> { |
| 436 final _FutureAction _action; | 493 final _FutureAction _action; |
| 437 | 494 |
| 438 _WhenFuture(this._action); | 495 _WhenFuture(this._action); |
| 439 | 496 |
| 440 void _sendValue(T value) { | 497 void _zonedSendValue(T value) { |
| 441 try { | 498 try { |
| 442 var result = _action(); | 499 var result = _action(); |
| 443 if (result is Future) { | 500 if (result is Future) { |
| 444 Future resultFuture = result; | 501 Future resultFuture = result; |
| 445 resultFuture.then((_) { | 502 resultFuture.then((_) { |
| 446 _setValue(value); | 503 _setValue(value); |
| 447 }, onError: _setError); | 504 }, onError: _setError); |
| 448 return; | 505 return; |
| 449 } | 506 } |
| 450 } catch (e, s) { | 507 } catch (e, s) { |
| 451 _setError(_asyncError(e, s)); | 508 _setError(_asyncError(e, s)); |
| 452 return; | 509 return; |
| 453 } | 510 } |
| 454 _setValue(value); | 511 _setValue(value); |
| 455 } | 512 } |
| 456 | 513 |
| 457 void _sendError(error) { | 514 void _zonedSendError(error) { |
| 458 try { | 515 try { |
| 459 var result = _action(); | 516 var result = _action(); |
| 460 if (result is Future) { | 517 if (result is Future) { |
| 461 Future resultFuture = result; | 518 Future resultFuture = result; |
| 462 // TODO(lrn): Find a way to combine [error] into [e]. | 519 // TODO(lrn): Find a way to combine [error] into [e]. |
| 463 resultFuture.then((_) { | 520 resultFuture.then((_) { |
| 464 _setError(error); | 521 _setError(error); |
| 465 }, onError: _setError); | 522 }, onError: _setError); |
| 466 return; | 523 return; |
| 467 } | 524 } |
| 468 } catch (e, s) { | 525 } catch (e, s) { |
| 469 error = _asyncError(e, s); | 526 error = _asyncError(e, s); |
| 470 } | 527 } |
| 471 _setError(error); | 528 _setError(error); |
| 472 } | 529 } |
| 473 } | 530 } |
| OLD | NEW |