| Index: sdk/lib/async/future.dart
|
| diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
|
| index 10aa237f9f08d0a8cca20e86d44fcf227ea69874..7f4050cf8cb6dc661af812fb51bb6f0267b9de57 100644
|
| --- a/sdk/lib/async/future.dart
|
| +++ b/sdk/lib/async/future.dart
|
| @@ -239,14 +239,24 @@ abstract class Future<T> {
|
| * Returns a future which will complete once all the futures in a list are
|
| * complete. If any of the futures in the list completes with an error,
|
| * the resulting future also completes with an error. Otherwise the value
|
| - * of the returned future will be a list of all the values that were produced.
|
| + * of the returned future will be a list of all the values that were
|
| + * produced.
|
| *
|
| * If `eagerError` is true, the future completes with an error immediately on
|
| * the first error from one of the futures. Otherwise all futures must
|
| * complete before the returned future is completed (still with the first
|
| * error to occur, the remaining errors are silently dropped).
|
| + *
|
| + * If [cleanUp] is provided, in the case of an error, any non-null result of
|
| + * a successful future is passed to `cleanUp`, which can then release any
|
| + * resources that the successful operation allocated.
|
| + *
|
| + * The call to `cleanUp` should not throw. If it does, the error will be an
|
| + * uncaught asynchronous error.
|
| */
|
| - static Future<List> wait(Iterable<Future> futures, {bool eagerError: false}) {
|
| + static Future<List> wait(Iterable<Future> futures,
|
| + {bool eagerError: false,
|
| + void cleanUp(successValue)}) {
|
| final _Future<List> result = new _Future<List>();
|
| List values; // Collects the values. Set to null on error.
|
| int remaining = 0; // How many futures are we waiting for.
|
| @@ -254,11 +264,18 @@ abstract class Future<T> {
|
| StackTrace stackTrace; // The stackTrace that came with the error.
|
|
|
| // Handle an error from any of the futures.
|
| - handleError(theError, theStackTrace) {
|
| - final bool isFirstError = (values != null);
|
| - values = null;
|
| + void handleError(theError, theStackTrace) {
|
| remaining--;
|
| - if (isFirstError) {
|
| + if (values != null) {
|
| + if (cleanUp != null) {
|
| + for (var value in values) {
|
| + if (value != null) {
|
| + // Ensure errors from cleanUp are uncaught.
|
| + new Future.sync(() { cleanUp(value); });
|
| + }
|
| + }
|
| + }
|
| + values = null;
|
| if (remaining == 0 || eagerError) {
|
| result._completeError(theError, theStackTrace);
|
| } else {
|
| @@ -281,8 +298,14 @@ abstract class Future<T> {
|
| if (remaining == 0) {
|
| result._completeWithValue(values);
|
| }
|
| - } else if (remaining == 0 && !eagerError) {
|
| - result._completeError(error, stackTrace);
|
| + } 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);
|
| }
|
|
|