Index: sdk/lib/async/future.dart |
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart |
index b4d9c243393cb33fd47e1be15d4f25e71c8961fe..c64e1c5e0316ca6baa5997c9eb131f6b768bb9bd 100644 |
--- a/sdk/lib/async/future.dart |
+++ b/sdk/lib/async/future.dart |
@@ -287,32 +287,51 @@ abstract class Future<T> { |
} |
} |
- // As each future completes, put its value into the corresponding |
- // position in the list of values. |
- for (Future future in futures) { |
- int pos = remaining++; |
- future.then((Object/*=T*/ value) { |
- remaining--; |
- if (values != null) { |
- values[pos] = value; |
- if (remaining == 0) { |
- result._completeWithValue(values); |
- } |
- } else { |
- if (cleanUp != null && value != null) { |
- // Ensure errors from cleanUp are uncaught. |
- new Future.sync(() { cleanUp(value); }); |
- } |
- if (remaining == 0 && !eagerError) { |
- result._completeError(error, stackTrace); |
+ try { |
+ // As each future completes, put its value into the corresponding |
+ // position in the list of values. |
+ for (Future future in futures) { |
+ int pos = remaining; |
+ future.then((Object/*=T*/ value) { |
+ remaining--; |
+ if (values != null) { |
+ values[pos] = value; |
+ if (remaining == 0) { |
+ result._completeWithValue(values); |
+ } |
+ } else { |
+ if (cleanUp != null && value != null) { |
+ // Ensure errors from cleanUp are uncaught. |
+ new Future.sync(() { cleanUp(value); }); |
+ } |
+ if (remaining == 0 && !eagerError) { |
+ result._completeError(error, stackTrace); |
+ } |
} |
- } |
- }, onError: handleError); |
- } |
- if (remaining == 0) { |
- return new Future.value(const []); |
+ }, onError: handleError); |
+ // Increment the 'remaining' after the call to 'then'. |
+ // If that call throws, we don't expect any future callback from |
+ // the future, and we also don't increment remaining. |
+ remaining++; |
+ } |
+ if (remaining == 0) { |
+ return new Future.value(const []); |
+ } |
+ values = new List/*<T>*/(remaining); |
+ } catch (e, st) { |
+ // The error must have been thrown while iterating over the futures |
+ // list, or while installing a callback handler on the future. |
+ if (remaining == 0 || eagerError) { |
+ // Just complete the error immediately. |
+ result._completeError(e, st); |
+ } else { |
+ // Don't allocate a list for values, thus indicating that there was an |
+ // error. |
+ // Set error to the caught exception. |
+ error = e; |
+ stackTrace = st; |
+ } |
} |
- values = new List/*<T>*/(remaining); |
return result; |
} |