| Index: sdk/lib/async/future_impl.dart
|
| diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
|
| index 68dbbc041e7f49408f1edec2aa481a3cf0805d93..bb92fb7905bc7a774bb3689c92e122a7a5756871 100644
|
| --- a/sdk/lib/async/future_impl.dart
|
| +++ b/sdk/lib/async/future_impl.dart
|
| @@ -240,7 +240,12 @@ class _Future<T> implements Future<T> {
|
|
|
| _Future get _chainSource {
|
| assert(_isChained);
|
| - return _resultOrListeners;
|
| + _Future result = _resultOrListeners;
|
| + while (result._isChained) {
|
| + result = result._resultOrListeners;
|
| + _resultOrListeners = result;
|
| + }
|
| + return result;
|
| }
|
|
|
| // This method is used by async/await.
|
| @@ -276,54 +281,37 @@ class _Future<T> implements Future<T> {
|
| listener._nextListener = _resultOrListeners;
|
| _resultOrListeners = listener;
|
| } else {
|
| - if (_isChained) {
|
| - // Delegate listeners to chained source future.
|
| - // If the source is complete, instead copy its values and
|
| - // drop the chaining.
|
| - _Future source = _chainSource;
|
| - if (!source._isComplete) {
|
| - source._addListener(listener);
|
| - return;
|
| - }
|
| - _cloneResult(source);
|
| + _handleListener(listener);
|
| + }
|
| + }
|
| +
|
| + void _handleListener(_FutureListener listener) {
|
| + assert(listener._nextListener == null);
|
| + assert(!_mayAddListener);
|
| + if (_isChained) {
|
| + _Future source = _chainSource;
|
| + // Delegate listeners to chained source future.
|
| + // If the source is complete, instead copy its values and
|
| + // drop the chaining.
|
| + if (!source._isComplete) {
|
| + source._addListener(listener);
|
| + return;
|
| }
|
| - assert(_isComplete);
|
| - // Handle late listeners asynchronously.
|
| - _zone.scheduleMicrotask(() {
|
| - _propagateToListeners(this, listener);
|
| - });
|
| + _cloneResult(source);
|
| }
|
| + assert(_isComplete);
|
| + // Handle late listeners asynchronously.
|
| + _zone.scheduleMicrotask(() {
|
| + _propagateToListeners(this, listener);
|
| + });
|
| }
|
|
|
| void _prependListeners(_FutureListener listeners) {
|
| - if (listeners == null) return;
|
| - if (_mayAddListener) {
|
| - _FutureListener existingListeners = _resultOrListeners;
|
| - _resultOrListeners = listeners;
|
| - if (existingListeners != null) {
|
| - _FutureListener cursor = listeners;
|
| - while (cursor._nextListener != null) {
|
| - cursor = cursor._nextListener;
|
| - }
|
| - cursor._nextListener = existingListeners;
|
| - }
|
| - } else {
|
| - if (_isChained) {
|
| - // Delegate listeners to chained source future.
|
| - // If the source is complete, instead copy its values and
|
| - // drop the chaining.
|
| - _Future source = _chainSource;
|
| - if (!source._isComplete) {
|
| - source._prependListeners(listeners);
|
| - return;
|
| - }
|
| - _cloneResult(source);
|
| - }
|
| - assert(_isComplete);
|
| - listeners = _reverseListeners(listeners);
|
| - _zone.scheduleMicrotask(() {
|
| - _propagateToListeners(this, listeners);
|
| - });
|
| + while (listeners != null) {
|
| + _FutureListener first = listeners;
|
| + listeners = listeners._nextListener;
|
| + first._nextListener = null;
|
| + _addListener(first);
|
| }
|
| }
|
|
|
| @@ -333,12 +321,7 @@ class _Future<T> implements Future<T> {
|
| assert(!_isComplete);
|
| _FutureListener current = _resultOrListeners;
|
| _resultOrListeners = null;
|
| - return _reverseListeners(current);
|
| - }
|
| -
|
| - _FutureListener _reverseListeners(_FutureListener listeners) {
|
| _FutureListener prev = null;
|
| - _FutureListener current = listeners;
|
| while (current != null) {
|
| _FutureListener next = current._nextListener;
|
| current._nextListener = prev;
|
| @@ -389,12 +372,11 @@ class _Future<T> implements Future<T> {
|
| while (source._isChained) {
|
| source = source._chainSource;
|
| }
|
| + _FutureListener listeners = target._removeListeners();
|
| if (source._isComplete) {
|
| - _FutureListener listeners = target._removeListeners();
|
| target._cloneResult(source);
|
| _propagateToListeners(target, listeners);
|
| } else {
|
| - _FutureListener listeners = target._resultOrListeners;
|
| target._setChained(source);
|
| source._prependListeners(listeners);
|
| }
|
|
|