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); |
} |