Index: pkg/dev_compiler/tool/input_sdk/lib/async/future.dart |
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/async/future.dart b/pkg/dev_compiler/tool/input_sdk/lib/async/future.dart |
deleted file mode 100644 |
index 5b570c606f6869df24fbe6a621772e8f32634bf5..0000000000000000000000000000000000000000 |
--- a/pkg/dev_compiler/tool/input_sdk/lib/async/future.dart |
+++ /dev/null |
@@ -1,829 +0,0 @@ |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-part of dart.async; |
- |
-/// A type representing values that are either `Future<T>` or `T`. |
-/// |
-/// This class declaration is a public stand-in for an internal |
-/// future-or-value generic type. References to this class are resolved to the |
-/// internal type. |
-/// |
-/// It is a compile-time error for any class to extend, mix in or implement |
-/// `FutureOr`. |
-/// |
-/// Note: the `FutureOr<T>` type is interpreted as `dynamic` in non strong-mode. |
-/// |
-/// # Examples |
-/// ``` dart |
-/// // The `Future<T>.then` function takes a callback [f] that returns either |
-/// // an `S` or a `Future<S>`. |
-/// Future<S> then<S>(FutureOr<S> f(T x), ...); |
-/// |
-/// // `Completer<T>.complete` takes either a `T` or `Future<T>`. |
-/// void complete(FutureOr<T> value); |
-/// ``` |
-/// |
-/// # Advanced |
-/// The `FutureOr<int>` type is actually the "type union" of the types `int` and |
-/// `Future<int>`. This type union is defined in such a way that |
-/// `FutureOr<Object>` is both a super- and sub-type of `Object` (sub-type |
-/// because `Object` is one of the types of the union, super-type because |
-/// `Object` is a super-type of both of the types of the union). Together it |
-/// means that `FutureOr<Object>` is equivalent to `Object`. |
-/// |
-/// As a corollary, `FutureOr<Object>` is equivalent to |
-/// `FutureOr<FutureOr<Object>>`, `FutureOr<Future<Object>> is equivalent to |
-/// `Future<Object>`. |
-abstract class FutureOr<T> { |
- // Private constructor, so that it is not subclassable, mixable, or |
- // instantiable. |
- FutureOr._() { |
- throw new UnsupportedError("FutureOr can't be instantiated"); |
- } |
-} |
- |
-/** |
- * An object representing a delayed computation. |
- * |
- * A [Future] is used to represent a potential value, or error, |
- * that will be available at some time in the future. |
- * Receivers of a [Future] can register callbacks |
- * that handle the value or error once it is available. |
- * For example: |
- * |
- * Future<int> future = getFuture(); |
- * future.then((value) => handleValue(value)) |
- * .catchError((error) => handleError(error)); |
- * |
- * A [Future] can complete in two ways: |
- * with a value ("the future succeeds") |
- * or with an error ("the future fails"). |
- * Users can install callbacks for each case. |
- * The result of registering a pair of callbacks is a new Future (the |
- * "successor") which in turn is completed with the result of invoking the |
- * corresponding callback. |
- * The successor is completed with an error if the invoked callback throws. |
- * For example: |
- * |
- * Future<int> successor = future.then((int value) { |
- * // Invoked when the future is completed with a value. |
- * return 42; // The successor is completed with the value 42. |
- * }, |
- * onError: (e) { |
- * // Invoked when the future is completed with an error. |
- * if (canHandle(e)) { |
- * return 499; // The successor is completed with the value 499. |
- * } else { |
- * throw e; // The successor is completed with the error e. |
- * } |
- * }); |
- * |
- * If a future does not have a successor when it completes with an error, |
- * it forwards the error message to the global error-handler. |
- * This behavior makes sure that no error is silently dropped. |
- * However, it also means that error handlers should be installed early, |
- * so that they are present as soon as a future is completed with an error. |
- * The following example demonstrates this potential bug: |
- * |
- * var future = getFuture(); |
- * new Timer(new Duration(milliseconds: 5), () { |
- * // The error-handler is not attached until 5 ms after the future has |
- * // been received. If the future fails before that, the error is |
- * // forwarded to the global error-handler, even though there is code |
- * // (just below) to eventually handle the error. |
- * future.then((value) { useValue(value); }, |
- * onError: (e) { handleError(e); }); |
- * }); |
- * |
- * When registering callbacks, it's often more readable to register the two |
- * callbacks separately, by first using [then] with one argument |
- * (the value handler) and using a second [catchError] for handling errors. |
- * Each of these will forward the result that they don't handle |
- * to their successors, and together they handle both value and error result. |
- * It also has the additional benefit of the [catchError] handling errors in the |
- * [then] value callback too. |
- * Using sequential handlers instead of parallel ones often leads to code that |
- * is easier to reason about. |
- * It also makes asynchronous code very similar to synchronous code: |
- * |
- * // Synchronous code. |
- * try { |
- * int value = foo(); |
- * return bar(value); |
- * } catch (e) { |
- * return 499; |
- * } |
- * |
- * Equivalent asynchronous code, based on futures: |
- * |
- * Future<int> future = new Future(foo); // Result of foo() as a future. |
- * future.then((int value) => bar(value)) |
- * .catchError((e) => 499); |
- * |
- * Similar to the synchronous code, the error handler (registered with |
- * [catchError]) is handling any errors thrown by either `foo` or `bar`. |
- * If the error-handler had been registered as the `onError` parameter of |
- * the `then` call, it would not catch errors from the `bar` call. |
- * |
- * Futures can have more than one callback-pair registered. Each successor is |
- * treated independently and is handled as if it was the only successor. |
- * |
- * A future may also fail to ever complete. In that case, no callbacks are |
- * called. |
- */ |
-abstract class Future<T> { |
- // The `_nullFuture` is a completed Future with the value `null`. |
- static final _Future _nullFuture = new Future.value(null); |
- |
- /** |
- * Creates a future containing the result of calling [computation] |
- * asynchronously with [Timer.run]. |
- * |
- * If the result of executing [computation] throws, the returned future is |
- * completed with the error. |
- * |
- * If the returned value is itself a [Future], completion of |
- * the created future will wait until the returned future completes, |
- * and will then complete with the same result. |
- * |
- * If a non-future value is returned, the returned future is completed |
- * with that value. |
- */ |
- factory Future(computation()) { |
- _Future<T> result = new _Future<T>(); |
- Timer.run(() { |
- try { |
- result._complete(computation()); |
- } catch (e, s) { |
- _completeWithErrorCallback(result, e, s); |
- } |
- }); |
- return result; |
- } |
- |
- /** |
- * Creates a future containing the result of calling [computation] |
- * asynchronously with [scheduleMicrotask]. |
- * |
- * If executing [computation] throws, |
- * the returned future is completed with the thrown error. |
- * |
- * If calling [computation] returns a [Future], completion of |
- * the created future will wait until the returned future completes, |
- * and will then complete with the same result. |
- * |
- * If calling [computation] returns a non-future value, |
- * the returned future is completed with that value. |
- */ |
- factory Future.microtask(computation()) { |
- _Future<T> result = new _Future<T>(); |
- scheduleMicrotask(() { |
- try { |
- result._complete(computation()); |
- } catch (e, s) { |
- _completeWithErrorCallback(result, e, s); |
- } |
- }); |
- return result; |
- } |
- |
- /** |
- * Creates a future containing the result of immediately calling |
- * [computation]. |
- * |
- * If calling [computation] throws, the returned future is completed with the |
- * error. |
- * |
- * If calling [computation] returns a [Future], completion of |
- * the created future will wait until the returned future completes, |
- * and will then complete with the same result. |
- * |
- * If calling [computation] returns a non-future value, |
- * the returned future is completed with that value. |
- */ |
- factory Future.sync(computation()) { |
- try { |
- var result = computation(); |
- return new Future<T>.value(result); |
- } catch (error, stackTrace) { |
- return new Future<T>.error(error, stackTrace); |
- } |
- } |
- |
- /** |
- * A future whose value is available in the next event-loop iteration. |
- * |
- * If [value] is not a [Future], using this constructor is equivalent |
- * to [:new Future<T>.sync(() => value):]. |
- * |
- * Use [Completer] to create a Future and complete it later. |
- */ |
- factory Future.value([value]) { |
- return new _Future<T>.immediate(value); |
- } |
- |
- /** |
- * A future that completes with an error in the next event-loop iteration. |
- * |
- * If [error] is `null`, it is replaced by a [NullThrownError]. |
- * |
- * Use [Completer] to create a future and complete it later. |
- */ |
- factory Future.error(Object error, [StackTrace stackTrace]) { |
- error = _nonNullError(error); |
- if (!identical(Zone.current, _ROOT_ZONE)) { |
- AsyncError replacement = Zone.current.errorCallback(error, stackTrace); |
- if (replacement != null) { |
- error = _nonNullError(replacement.error); |
- stackTrace = replacement.stackTrace; |
- } |
- } |
- return new _Future<T>.immediateError(error, stackTrace); |
- } |
- |
- /** |
- * Creates a future that runs its computation after a delay. |
- * |
- * The [computation] will be executed after the given [duration] has passed, |
- * and the future is completed with the result. |
- * If the duration is 0 or less, |
- * it completes no sooner than in the next event-loop iteration. |
- * |
- * If [computation] is omitted, |
- * it will be treated as if [computation] was set to `() => null`, |
- * and the future will eventually complete with the `null` value. |
- * |
- * If calling [computation] throws, the created future will complete with the |
- * error. |
- * |
- * 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, [computation()]) { |
- _Future<T> result = new _Future<T>(); |
- new Timer(duration, () { |
- try { |
- result._complete(computation?.call()); |
- } catch (e, s) { |
- _completeWithErrorCallback(result, e, s); |
- } |
- }); |
- return result; |
- } |
- |
- /** |
- * Wait for all the given futures to complete and collect their values. |
- * |
- * 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. |
- * |
- * 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<T>> wait<T>(Iterable<Future<T>> futures, |
- {bool eagerError: false, |
- void cleanUp(T successValue)}) { |
- final _Future<List<T>> result = new _Future<List<T>>(); |
- List<T> values; // Collects the values. Set to null on error. |
- int remaining = 0; // How many futures are we waiting for. |
- var error; // The first error from a future. |
- StackTrace stackTrace; // The stackTrace that came with the error. |
- |
- // Handle an error from any of the futures. |
- void handleError(theError, theStackTrace) { |
- remaining--; |
- 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 { |
- error = theError; |
- stackTrace = theStackTrace; |
- } |
- } else 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((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); |
- // 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) { |
- // Throw a new Future.error. |
- // Don't just call `result._completeError` since that would propagate |
- // the error too eagerly, not giving the callers time to install |
- // error handlers. |
- // Also, don't use `_asyncCompleteError` since that one doesn't give |
- // zones the chance to intercept the error. |
- return new Future.error(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; |
- } |
- } |
- return result; |
- } |
- |
- /** |
- * 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 |
- * only when the [Future] returned by [f] completes. Returns a [Future] that |
- * completes when all elements have been processed. |
- * |
- * The return values of all [Future]s are discarded. Any errors will cause the |
- * iteration to stop and will be piped through the returned [Future]. |
- * |
- * If [f] returns a non-[Future], iteration continues immediately. Otherwise |
- * it waits for the returned [Future] to complete. |
- */ |
- static Future forEach<T>(Iterable<T> input, f(T element)) { |
- var iterator = input.iterator; |
- return doWhile(() { |
- if (!iterator.moveNext()) return false; |
- return new Future.sync(() => f(iterator.current)).then((_) => true); |
- }); |
- } |
- |
- /** |
- * Performs an async operation repeatedly until it returns `false`. |
- * |
- * The function [f] is called repeatedly while it returns either the [bool] |
- * value `true` or a [Future] which completes with the value `true`. |
- * |
- * If a call to [f] returns `false` or a [Future] that completes to `false`, |
- * iteration ends and the future returned by [doWhile] is completed. |
- * |
- * If a future returned by [f] completes with an error, iteration ends and |
- * the future returned by [doWhile] completes with the same error. |
- * |
- * The [f] function must return either a `bool` value or a [Future] completing |
- * with a `bool` value. |
- */ |
- static Future doWhile(f()) { |
- _Future doneSignal = new _Future(); |
- var nextIteration; |
- // Bind this callback explicitly so that each iteration isn't bound in the |
- // context of all the previous iterations' callbacks. |
- nextIteration = Zone.current.bindUnaryCallback((bool keepGoing) { |
- if (keepGoing) { |
- new Future.sync(f).then(nextIteration, |
- onError: doneSignal._completeError); |
- } else { |
- doneSignal._complete(null); |
- } |
- }, runGuarded: true); |
- nextIteration(true); |
- return doneSignal; |
- } |
- |
- /** |
- * Register callbacks to be called when this future completes. |
- * |
- * When this future completes with a value, |
- * the [onValue] callback will be called with that value. |
- * If this future is already completed, the callback will not be called |
- * immediately, but will be scheduled in a later microtask. |
- * |
- * If [onError] is provided, and this future completes with an error, |
- * the `onError` callback is called with that error and its stack trace. |
- * The `onError` callback must accept either one argument or two arguments. |
- * If `onError` accepts two arguments, |
- * it is called with both the error and the stack trace, |
- * otherwise it is called with just the error object. |
- * |
- * Returns a new [Future] |
- * which is completed with the result of the call to `onValue` |
- * (if this future completes with a value) |
- * or to `onError` (if this future completes with an error). |
- * |
- * If the invoked callback throws, |
- * the returned future is completed with the thrown error |
- * and a stack trace for the error. |
- * In the case of `onError`, |
- * if the exception thrown is `identical` to the error argument to `onError`, |
- * the throw is considered a rethrow, |
- * and the original stack trace is used instead. |
- * |
- * If the callback returns a [Future], |
- * the future returned by `then` will be completed with |
- * the same result as the future returned by the callback. |
- * |
- * If [onError] is not given, and this future completes with an error, |
- * the error is forwarded directly to the returned future. |
- * |
- * In most cases, it is more readable to use [catchError] separately, possibly |
- * with a `test` parameter, instead of handling both value and error in a |
- * single [then] call. |
- */ |
- Future<S> then<S>(FutureOr<S> onValue(T value), { Function onError }); |
- |
- /** |
- * Handles errors emitted by this [Future]. |
- * |
- * This is the asynchronous equivalent of a "catch" block. |
- * |
- * Returns a new [Future] that will be completed with either the result of |
- * this future or the result of calling the `onError` callback. |
- * |
- * If this future completes with a value, |
- * the returned future completes with the same value. |
- * |
- * If this future completes with an error, |
- * then [test] is first called with the error value. |
- * |
- * If `test` returns false, the exception is not handled by this `catchError`, |
- * and the returned future completes with the same error and stack trace |
- * as this future. |
- * |
- * If `test` returns `true`, |
- * [onError] is called with the error and possibly stack trace, |
- * and the returned future is completed with the result of this call |
- * in exactly the same way as for [then]'s `onError`. |
- * |
- * If `test` is omitted, it defaults to a function that always returns true. |
- * The `test` function should not throw, but if it does, it is handled as |
- * if the `onError` function had thrown. |
- * |
- * Example: |
- * |
- * foo |
- * .catchError(..., test: (e) => e is ArgumentError) |
- * .catchError(..., test: (e) => e is NoSuchMethodError) |
- * .then((v) { ... }); |
- * |
- * This method is equivalent to: |
- * |
- * Future catchError(onError(error), |
- * {bool test(error)}) { |
- * this.then((v) => v, // Forward the value. |
- * // But handle errors, if the [test] succeeds. |
- * onError: (e, stackTrace) { |
- * if (test == null || test(e)) { |
- * if (onError is ZoneBinaryCallback) { |
- * return onError(e, stackTrace); |
- * } |
- * return onError(e); |
- * } |
- * throw e; |
- * }); |
- * } |
- * |
- */ |
- // 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. |
- * |
- * The [action] function is called when this future completes, whether it |
- * does so with a value or with an error. |
- * |
- * This is the asynchronous equivalent of a "finally" block. |
- * |
- * The future returned by this call, `f`, will complete the same way |
- * as this future unless an error occurs in the [action] call, or in |
- * a [Future] returned by the [action] call. If the call to [action] |
- * does not return a future, its return value is ignored. |
- * |
- * If the call to [action] throws, then `f` is completed with the |
- * thrown error. |
- * |
- * If the call to [action] returns a [Future], `f2`, then completion of |
- * `f` is delayed until `f2` completes. If `f2` completes with |
- * an error, that will be the result of `f` too. The value of `f2` is always |
- * ignored. |
- * |
- * This method is equivalent to: |
- * |
- * Future<T> whenComplete(action()) { |
- * return this.then((v) { |
- * var f2 = action(); |
- * if (f2 is Future) return f2.then((_) => v); |
- * return v |
- * }, onError: (e) { |
- * var f2 = action(); |
- * if (f2 is Future) return f2.then((_) { throw e; }); |
- * throw e; |
- * }); |
- * } |
- */ |
- Future<T> whenComplete(action()); |
- |
- /** |
- * Creates a [Stream] containing the result of this future. |
- * |
- * The stream will produce single data or error event containing the |
- * completion result of this future, and then it will close with a |
- * done event. |
- * |
- * If the future never completes, the stream will not produce any events. |
- */ |
- Stream<T> asStream(); |
- |
- /** |
- * Time-out the future computation after [timeLimit] has passed. |
- * |
- * Returns a new future that completes with the same value as this future, |
- * if this future completes in time. |
- * |
- * 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<T> timeout(Duration timeLimit, {onTimeout()}); |
-} |
- |
-/** |
- * Thrown when a scheduled timeout happens while waiting for an async result. |
- */ |
-class TimeoutException implements Exception { |
- /** Description of the cause of the timeout. */ |
- final String message; |
- /** The duration that was exceeded. */ |
- final Duration duration; |
- |
- TimeoutException(this.message, [this.duration]); |
- |
- String toString() { |
- String result = "TimeoutException"; |
- if (duration != null) result = "TimeoutException after $duration"; |
- if (message != null) result = "$result: $message"; |
- return result; |
- } |
-} |
- |
-/** |
- * A way to produce Future objects and to complete them later |
- * with a value or error. |
- * |
- * Most of the time, the simplest way to create a future is to just use |
- * one of the [Future] constructors to capture the result of a single |
- * asynchronous computation: |
- * |
- * new Future(() { doSomething(); return result; }); |
- * |
- * or, if the future represents the result of a sequence of asynchronous |
- * computations, they can be chained using [Future.then] or similar functions |
- * on [Future]: |
- * |
- * Future doStuff(){ |
- * return someAsyncOperation().then((result) { |
- * return someOtherAsyncOperation(result); |
- * }); |
- * } |
- * |
- * If you do need to create a Future from scratch — for example, |
- * when you're converting a callback-based API into a Future-based |
- * one — you can use a Completer as follows: |
- * |
- * class AsyncOperation { |
- * Completer _completer = new Completer(); |
- * |
- * Future<T> doOperation() { |
- * _startOperation(); |
- * return _completer.future; // Send future object back to client. |
- * } |
- * |
- * // Something calls this when the value is ready. |
- * void _finishOperation(T result) { |
- * _completer.complete(result); |
- * } |
- * |
- * // If something goes wrong, call this. |
- * void _errorHappened(error) { |
- * _completer.completeError(error); |
- * } |
- * } |
- */ |
-abstract class Completer<T> { |
- |
- /** |
- * Creates a new completer. |
- * |
- * The general workflow for creating a new future is to 1) create a |
- * new completer, 2) hand out its future, and, at a later point, 3) invoke |
- * either [complete] or [completeError]. |
- * |
- * The completer completes the future asynchronously. That means that |
- * callbacks registered on the future, are not called immediately when |
- * [complete] or [completeError] is called. Instead the callbacks are |
- * delayed until a later microtask. |
- * |
- * Example: |
- * |
- * var completer = new Completer(); |
- * handOut(completer.future); |
- * later: { |
- * completer.complete('completion value'); |
- * } |
- */ |
- factory Completer() => new _AsyncCompleter<T>(); |
- |
- /** |
- * Completes the future synchronously. |
- * |
- * This constructor should be avoided unless the completion of the future is |
- * known to be the final result of another asynchronous operation. If in doubt |
- * use the default [Completer] constructor. |
- * |
- * Using an normal, asynchronous, completer will never give the wrong |
- * behavior, but using a synchronous completer incorrectly can cause |
- * otherwise correct programs to break. |
- * |
- * 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. |
- * |
- * Completing synchronously means that the completer's future will be |
- * completed immediately when calling the [complete] or [completeError] |
- * method on a synchronous completer, which also calls any callbacks |
- * registered on that future. |
- * |
- * Completing synchronously must not break the rule that when you add a |
- * callback on a future, that callback must not be called until the code |
- * that added the callback has completed. |
- * For that reason, a synchronous completion must only occur at the very end |
- * (in "tail position") of another synchronous event, |
- * because at that point, completing the future immediately is be equivalent |
- * to returning to the event loop and completing the future in the next |
- * microtask. |
- * |
- * Example: |
- * |
- * var completer = new Completer.sync(); |
- * // The completion is the result of the asynchronous onDone event. |
- * // No other operation is performed after the completion. It is safe |
- * // to use the Completer.sync constructor. |
- * stream.listen(print, onDone: () { completer.complete("done"); }); |
- * |
- * Bad example. Do not use this code. Only for illustrative purposes: |
- * |
- * var completer = new Completer.sync(); |
- * completer.future.then((_) { bar(); }); |
- * // The completion is the result of the asynchronous onDone event. |
- * // However, there is still code executed after the completion. This |
- * // operation is *not* safe. |
- * stream.listen(print, onDone: () { |
- * completer.complete("done"); |
- * foo(); // In this case, foo() runs after bar(). |
- * }); |
- */ |
- factory Completer.sync() => new _SyncCompleter<T>(); |
- |
- /** The future that will contain the result provided to this completer. */ |
- Future<T> get future; |
- |
- /** |
- * Completes [future] with the supplied values. |
- * |
- * The value must be either a value of type [T] |
- * or a future of type `Future<T>`. |
- * |
- * If the value is itself a future, the completer will wait for that future |
- * to complete, and complete with the same result, whether it is a success |
- * or an error. |
- * |
- * Calling `complete` or [completeError] must not be done more than once. |
- * |
- * All listeners on the future are informed about the value. |
- */ |
- void complete([value]); |
- |
- /** |
- * Complete [future] with an error. |
- * |
- * Calling [complete] or `completeError` must not be done more than once. |
- * |
- * Completing a future with an error indicates that an exception was thrown |
- * while trying to produce a value. |
- * |
- * If [error] is `null`, it is replaced by a [NullThrownError]. |
- * |
- * If `error` is a `Future`, the future itself is used as the error value. |
- * If you want to complete with the result of the future, you can use: |
- * |
- * thisCompleter.complete(theFuture) |
- * |
- * or if you only want to handle an error from the future: |
- * |
- * theFuture.catchError(thisCompleter.completeError); |
- * |
- */ |
- void completeError(Object error, [StackTrace stackTrace]); |
- |
- /** |
- * Whether the future has been completed. |
- */ |
- bool get isCompleted; |
-} |
- |
-// Helper function completing a _Future with error, but checking the zone |
-// for error replacement first. |
-void _completeWithErrorCallback(_Future result, error, stackTrace) { |
- AsyncError replacement = Zone.current.errorCallback(error, stackTrace); |
- if (replacement != null) { |
- error = _nonNullError(replacement.error); |
- stackTrace = replacement.stackTrace; |
- } |
- result._completeError(error, stackTrace); |
-} |
- |
-/** Helper function that converts `null` to a [NullThrownError]. */ |
-Object _nonNullError(Object error) => |
- (error != null) ? error : new NullThrownError(); |