| Index: tool/input_sdk/lib/async/future.dart
|
| diff --git a/tool/input_sdk/lib/async/future.dart b/tool/input_sdk/lib/async/future.dart
|
| index 7d41d89adfaccbeb1a2e7ab27ca447301c4e9a22..418b2eccb97059b24cebdfb9599da7daf116e379 100644
|
| --- a/tool/input_sdk/lib/async/future.dart
|
| +++ b/tool/input_sdk/lib/async/future.dart
|
| @@ -95,7 +95,7 @@ part of dart.async;
|
| */
|
| abstract class Future<T> {
|
| // The `_nullFuture` is a completed Future with the value `null`.
|
| - static final _Future _nullFuture = new _Future.immediate(null);
|
| + static final _Future _nullFuture = new Future.value(null);
|
|
|
| /**
|
| * Creates a future containing the result of calling [computation]
|
| @@ -112,7 +112,7 @@ abstract class Future<T> {
|
| * with that value.
|
| */
|
| factory Future(computation()) {
|
| - _Future result = new _Future<T>();
|
| + _Future<T> result = new _Future<T>();
|
| Timer.run(() {
|
| try {
|
| result._complete(computation());
|
| @@ -138,7 +138,7 @@ abstract class Future<T> {
|
| * the returned future is completed with that value.
|
| */
|
| factory Future.microtask(computation()) {
|
| - _Future result = new _Future<T>();
|
| + _Future<T> result = new _Future<T>();
|
| scheduleMicrotask(() {
|
| try {
|
| result._complete(computation());
|
| @@ -221,8 +221,8 @@ abstract class Future<T> {
|
| * See also [Completer] for a way to create and complete a future at a
|
| * later time that isn't necessarily after a known fixed duration.
|
| */
|
| - factory Future.delayed(Duration duration, [T computation()]) {
|
| - _Future result = new _Future<T>();
|
| + factory Future.delayed(Duration duration, [computation()]) {
|
| + _Future<T> result = new _Future<T>();
|
| new Timer(duration, () {
|
| try {
|
| result._complete(computation == null ? null : computation());
|
| @@ -268,10 +268,10 @@ abstract class Future<T> {
|
| remaining--;
|
| if (values != null) {
|
| if (cleanUp != null) {
|
| - for (var value2 in values) {
|
| - if (value2 != null) {
|
| + for (var value in values) {
|
| + if (value != null) {
|
| // Ensure errors from cleanUp are uncaught.
|
| - new Future.sync(() { cleanUp(value2); });
|
| + new Future.sync(() { cleanUp(value); });
|
| }
|
| }
|
| }
|
| @@ -291,7 +291,7 @@ abstract class Future<T> {
|
| // position in the list of values.
|
| for (Future future in futures) {
|
| int pos = remaining++;
|
| - future.then((Object value) {
|
| + future.then((Object/*=T*/ value) {
|
| remaining--;
|
| if (values != null) {
|
| values[pos] = value;
|
| @@ -317,6 +317,31 @@ abstract class Future<T> {
|
| }
|
|
|
| /**
|
| + * Returns the result of the first future in [futures] to complete.
|
| + *
|
| + * The returned future is completed with the result of the first
|
| + * future in [futures] to report that it is complete.
|
| + * The results of all the other futures are discarded.
|
| + *
|
| + * If [futures] is empty, or if none of its futures complete,
|
| + * the returned future never completes.
|
| + */
|
| + static Future/*<T>*/ any/*<T>*/(Iterable<Future/*<T>*/> futures) {
|
| + var completer = new Completer/*<T>*/.sync();
|
| + var onValue = (/*=T*/ value) {
|
| + if (!completer.isCompleted) completer.complete(value);
|
| + };
|
| + var onError = (error, stack) {
|
| + if (!completer.isCompleted) completer.completeError(error, stack);
|
| + };
|
| + for (var future in futures) {
|
| + future.then(onValue, onError: onError);
|
| + }
|
| + return completer.future;
|
| + }
|
| +
|
| +
|
| + /**
|
| * Perform an async operation for each element of the iterable, in turn.
|
| *
|
| * Runs [f] for each element in [input] in order, moving to the next element
|
| @@ -461,8 +486,17 @@ abstract class Future<T> {
|
| * }
|
| *
|
| */
|
| - Future catchError(Function onError,
|
| - {bool test(Object error)});
|
| + // The `Function` below can stand for several types:
|
| + // - (dynamic) -> T
|
| + // - (dynamic, StackTrace) -> T
|
| + // - (dynamic) -> Future<T>
|
| + // - (dynamic, StackTrace) -> Future<T>
|
| + // Given that there is a `test` function that is usually used to do an
|
| + // `isCheck` we should also expect functions that take a specific argument.
|
| + // Note: making `catchError` return a `Future<T>` in non-strong mode could be
|
| + // a breaking change.
|
| + Future/*<T>*/ catchError(Function onError,
|
| + {bool test(Object error)});
|
|
|
| /**
|
| * Register a function to be called when this future completes.
|
| @@ -521,11 +555,12 @@ abstract class Future<T> {
|
| * If this future does not complete before `timeLimit` has passed,
|
| * the [onTimeout] action is executed instead, and its result (whether it
|
| * returns or throws) is used as the result of the returned future.
|
| + * The [onTimeout] function must return a [T] or a `Future<T>`.
|
| *
|
| * If `onTimeout` is omitted, a timeout will cause the returned future to
|
| * complete with a [TimeoutException].
|
| */
|
| - Future timeout(Duration timeLimit, {onTimeout()});
|
| + Future<T> timeout(Duration timeLimit, {onTimeout()});
|
| }
|
|
|
| /**
|
| @@ -625,7 +660,7 @@ abstract class Completer<T> {
|
| * behavior, but using a synchronous completer incorrectly can cause
|
| * otherwise correct programs to break.
|
| *
|
| - * An asynchronous completer is only intended for optimizing event
|
| + * A synchronous completer is only intended for optimizing event
|
| * propagation when one asynchronous event immediately triggers another.
|
| * It should not be used unless the calls to [complete] and [completeError]
|
| * are guaranteed to occur in places where it won't break `Future` invariants.
|
|
|