// 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;

/// Sets [stackTrace] as [Error.stackTrace] on [error], if that is an [Error].
///
/// If [error] is not an instance of a class which extends [Error],
/// or if it already has an [Error.stackTrace] set, nothing happens.
@pragma("wasm:entry-point")
external void _trySetStackTrace(Object error, StackTrace stackTrace);

/// Calls the [Zone.errorCallback] of the current zone with the error and stack.
///
/// If a non-`null` result is returned, it tries to set the stack trace
/// on the returned error to the returned stack trace.
AsyncError? _interceptError(Object error, StackTrace? stackTrace) {
  var zone = Zone._current;
  if (identical(zone, _rootZone)) return null;
  var replacement = zone.errorCallback(error, stackTrace);
  if (replacement == null) return null;
  _trySetStackTrace(replacement.error, replacement.stackTrace);
  return replacement;
}

/// As [_interceptError], but an `AsyncError` of the error if not replaced.
///
/// Also like [_interceptUserError], but for errors that are already
/// asynchronous.
AsyncError _interceptCaughtError(Object error, StackTrace? stackTrace) =>
    _interceptError(error, stackTrace) ?? AsyncError(error, stackTrace);

/// Used for user-provided error and stack trace that are to become async
/// errors.
///
/// Allows `Zone.current.errorCallback` to intercept and modify the error,
/// and sets the stack trace on the error as if it was thrown.
///
/// Used for errors given to async functions like [Completer.completeError]
/// or [StreamController.addError].
///
/// For errors that are caught (and have therefore been thrown already)
/// use [_interceptCaughtError], which doesn't try to set a stack trace on the
/// error object.
///
/// Errors that are already asynchronous (coming out of streams or futures)
/// should not call [Zone.errorCallback].
AsyncError _interceptUserError(Object error, StackTrace? stackTrace) {
  var zone = Zone.current;
  if (!identical(zone, _rootZone)) {
    var replacement = _interceptError(error, stackTrace);
    if (replacement != null) return replacement;
  }
  if (stackTrace == null) {
    // Inlines `AsyncError.defaultStackTrace`, to reuse the `is Error` check
    // result to also not do `_trySetStackTrace` on known non-`Error`s.
    if (error is Error) {
      stackTrace = error.stackTrace;
      if (stackTrace == null) {
        stackTrace = StackTrace.empty;
        _trySetStackTrace(error, stackTrace);
      }
    } else {
      stackTrace = StackTrace.empty;
    }
  } else {
    _trySetStackTrace(error, stackTrace); // Maybe it's an Error.
  }
  return AsyncError._(error, stackTrace);
}

abstract class _Completer<T> implements Completer<T> {
  @pragma("wasm:entry-point")
  @pragma("vm:entry-point")
  final _Future<T> future = _Future<T>();

  // Overridden by either a synchronous or asynchronous implementation.
  void complete([FutureOr<T>? value]);

  @pragma("wasm:entry-point")
  void completeError(Object error, [StackTrace? stackTrace]) {
    if (!future._mayComplete) throw StateError("Future already completed");
    _completeErrorObject(_interceptUserError(error, stackTrace));
  }

  // Overridden by either a synchronous or asynchronous implementation.
  void _completeErrorObject(AsyncError error);

  // The future's _isComplete doesn't take into account pending completions.
  // We therefore use _mayComplete.
  bool get isCompleted => !future._mayComplete;
}

/// Completer which completes future asynchronously.
@pragma("vm:entry-point")
class _AsyncCompleter<T> extends _Completer<T> {
  @pragma("wasm:entry-point")
  void complete([FutureOr<T>? value]) {
    if (!future._mayComplete) throw StateError("Future already completed");
    future._asyncComplete(value == null ? value as dynamic : value);
  }

  void _completeErrorObject(AsyncError error) {
    future._asyncCompleteErrorObject(error);
  }
}

/// Completer which completes future synchronously.
///
/// Created by [Completer.sync]. Use with caution.
@pragma("vm:entry-point")
class _SyncCompleter<T> extends _Completer<T> {
  void complete([FutureOr<T>? value]) {
    if (!future._mayComplete) throw StateError("Future already completed");
    future._complete(value == null ? value as dynamic : value);
  }

  void _completeErrorObject(AsyncError error) {
    future._completeErrorObject(error);
  }
}

class _FutureListener<S, T> {
  // Keep in sync with sdk/runtime/vm/stack_trace.cc.
  static const int maskValue = 1 << 0;
  static const int maskError = 1 << 1;
  static const int maskTestError = 1 << 2;
  static const int maskWhenComplete = 1 << 3;
  static const int maskAwait = 1 << 4;
  static const int stateChain = 0;
  // Handles values, passes errors on.
  static const int stateThen = maskValue;
  // Handles values and errors.
  static const int stateThenOnerror = maskValue | maskError;
  // Handles values and error. Created by the implementation of `await`.
  static const int stateThenAwait = stateThenOnerror | maskAwait;
  // Handles errors, has errorCallback.
  static const int stateCatchError = maskError;
  // Ignores both values and errors. Has no callback or errorCallback.
  // The [result] future is ignored, its always the same as the source.
  static const int stateCatchErrorTest = maskError | maskTestError;
  static const int stateWhenComplete = maskWhenComplete;
  static const int maskType =
      maskValue | maskError | maskTestError | maskWhenComplete;

  // Listeners on the same future are linked through this link.
  @pragma("vm:entry-point")
  _FutureListener? _nextListener;

  // The future to complete when this listener is activated.
  @pragma("vm:entry-point")
  final _Future<T> result;

  // Which fields means what.
  @pragma("vm:entry-point")
  final int state;

  // Used for then/whenDone callback and error test
  @pragma("vm:entry-point")
  final Function? callback;

  // Used for error callbacks.
  final Function? errorCallback;

  _FutureListener.then(
    this.result,
    FutureOr<T> Function(S) onValue,
    Function? errorCallback,
  ) : callback = onValue,
      errorCallback = errorCallback,
      state = (errorCallback == null) ? stateThen : stateThenOnerror;

  _FutureListener.thenAwait(
    this.result,
    FutureOr<T> Function(S) onValue,
    Function errorCallback,
  ) : callback = onValue,
      errorCallback = errorCallback,
      state = stateThenAwait;

  _FutureListener.catchError(this.result, this.errorCallback, this.callback)
    : state = (callback == null) ? stateCatchError : stateCatchErrorTest;

  _FutureListener.whenComplete(this.result, this.callback)
    : errorCallback = null,
      state = stateWhenComplete;

  _Zone get _zone => result._zone;

  bool get handlesValue => (state & maskValue != 0);
  bool get handlesError => (state & maskError != 0);
  bool get hasErrorTest => (state & maskType == stateCatchErrorTest);
  bool get handlesComplete => (state & maskType == stateWhenComplete);

  FutureOr<T> Function(S) get _onValue {
    assert(handlesValue);
    return unsafeCast<FutureOr<T> Function(S)>(callback);
  }

  Function? get _onError => errorCallback;

  bool Function(Object) get _errorTest {
    assert(hasErrorTest);
    return unsafeCast<bool Function(Object)>(callback);
  }

  dynamic Function() get _whenCompleteAction {
    assert(handlesComplete);
    return unsafeCast<dynamic Function()>(callback);
  }

  /// Whether this listener has an error callback.
  ///
  /// This function must only be called if the listener [handlesError].
  bool get hasErrorCallback {
    assert(handlesError);
    return _onError != null;
  }

  @pragma("vm:recognized", "other")
  @pragma("vm:never-inline")
  FutureOr<T> handleValue(S sourceResult) {
    return _zone.runUnary<FutureOr<T>, S>(_onValue, sourceResult);
  }

  bool matchesErrorTest(AsyncError asyncError) {
    if (!hasErrorTest) return true;
    return _zone.runUnary<bool, Object>(_errorTest, asyncError.error);
  }

  FutureOr<T> handleError(AsyncError asyncError) {
    assert(handlesError && hasErrorCallback);
    var errorCallback = this.errorCallback; // To enable promotion.
    // If the errorCallback returns something which is not a FutureOr<T>,
    // this return statement throws, and the caller handles the error.
    dynamic result;
    if (errorCallback is dynamic Function(Object, StackTrace)) {
      result = _zone.runBinary<dynamic, Object, StackTrace>(
        errorCallback,
        asyncError.error,
        asyncError.stackTrace,
      );
    } else {
      result = _zone.runUnary<dynamic, Object>(
        errorCallback as dynamic,
        asyncError.error,
      );
    }
    // Give better error messages if the result is not a valid
    // FutureOr<T>.
    try {
      return result;
    } on TypeError {
      if (handlesValue) {
        // This is a `.then` callback with an `onError`.
        throw ArgumentError(
          "The error handler of Future.then"
              " must return a value of the returned future's type",
          "onError",
        );
      }
      // This is a `catchError` callback.
      throw ArgumentError(
        "The error handler of "
            "Future.catchError must return a value of the future's type",
        "onError",
      );
    }
  }

  dynamic handleWhenComplete() {
    assert(!handlesError);
    return _zone.run(_whenCompleteAction);
  }

  // Whether the [value] future should be awaited and the [future] completed
  // with its result, rather than just completing the [future] directly
  // with the [value].
  bool shouldChain(Future<dynamic> value) => value is Future<T> || value is! T;
}

@pragma("wasm:entry-point")
class _Future<T> implements Future<T> {
  /// Initial state, waiting for a result. In this state, the
  /// [_resultOrListeners] field holds a single-linked list of
  /// [_FutureListener] listeners.
  static const int _stateIncomplete = 0;

  /// Flag set when an error need not be handled.
  ///
  /// Set by the [FutureExtensions.ignore] method to avoid
  /// having to introduce an unnecessary listener.
  /// Only relevant until the future is completed.
  ///
  /// When changing update runtime/vm/stack_trace.cc
  static const int _stateIgnoreError = 1;

  /// Pending completion. Set when completed using [_asyncComplete] or
  /// [_asyncCompleteError]. It is an error to try to complete it again.
  /// [_resultOrListeners] holds listeners.
  static const int _statePendingComplete = 2;

  /// The future has been chained to another "source" [_Future].
  ///
  /// The result of that other future becomes the result of this future
  /// as well, when the other future completes.
  /// This future cannot be completed again.
  /// [_resultOrListeners] contains the source future.
  /// Listeners have been moved to the chained future.
  static const int _stateChained = 4;

  /// The future has been completed with a value result.
  ///
  /// [_resultOrListeners] contains the value.
  static const int _stateValue = 8;

  /// The future has been completed with an error result.
  ///
  /// [_resultOrListeners] contains an [AsyncError]
  /// holding the error and stack trace.
  static const int _stateError = 16;

  /// Mask for the states above except [_stateIgnoreError].
  static const int _completionStateMask = 30;

  /// Whether the future is complete, and as what.
  @pragma('vm:entry-point')
  int _state = _stateIncomplete;

  /// Zone that the future was completed from.
  /// This is the zone that an error result belongs to.
  ///
  /// Until the future is completed, the field may hold the zone that
  /// listener callbacks used to create this future should be run in.
  final _Zone _zone;

  /// Either the result, a list of listeners or another future.
  ///
  /// The result of the future is either a value or an error.
  /// A result is only stored when the future has completed.
  ///
  /// The listeners is an internally linked list of [_FutureListener]s.
  /// Listeners are only remembered while the future is not yet complete,
  /// and it is not chained to another future.
  ///
  /// The future is another future that this future is chained to. This future
  /// is waiting for the other future to complete, and when it does,
  /// this future will complete with the same result.
  /// All listeners are forwarded to the other future.
  @pragma("vm:entry-point")
  var _resultOrListeners;

  // This constructor is used by async/await.
  _Future() : _zone = Zone._current;

  // Empty `_Future` in a given zone.
  _Future.zone(this._zone);

  // Constructor used by [Future.value].
  _Future.immediate(FutureOr<T> result) : _zone = Zone._current {
    _asyncComplete(result);
  }

  /// Creates a future with the value and the specified zone.
  _Future.zoneValue(T value, this._zone) {
    _setValue(value);
  }

  _Future.immediateError(AsyncError error) : _zone = Zone._current {
    _asyncCompleteErrorObject(error);
  }

  /// Creates a future that is already completed with the value.
  _Future.value(T value) : this.zoneValue(value, Zone._current);

  bool get _mayComplete => (_state & _completionStateMask) == _stateIncomplete;
  bool get _isPendingComplete => (_state & _statePendingComplete) != 0;
  bool get _mayAddListener =>
      _state <= (_statePendingComplete | _stateIgnoreError);
  bool get _isChained => (_state & _stateChained) != 0;
  bool get _isComplete => (_state & (_stateValue | _stateError)) != 0;
  bool get _hasError => (_state & _stateError) != 0;
  bool get _ignoreError => (_state & _stateIgnoreError) != 0;

  void _setChained(_Future source) {
    assert(_mayAddListener);
    _state = _stateChained | (_state & _stateIgnoreError);
    _resultOrListeners = source;
  }

  Future<R> then<R>(FutureOr<R> f(T value), {Function? onError}) {
    Zone currentZone = Zone.current;
    if (identical(currentZone, _rootZone)) {
      if (onError != null &&
          onError is! Function(Object, StackTrace) &&
          onError is! Function(Object)) {
        throw ArgumentError.value(
          onError,
          "onError",
          "Error handler must accept one Object or one Object and a StackTrace"
              " as arguments, and return a value of the returned future's type",
        );
      }
    } else {
      f = currentZone.registerUnaryCallback<FutureOr<R>, T>(f);
      if (onError != null) {
        // This call also checks that onError is assignable to one of:
        //   dynamic Function(Object)
        //   dynamic Function(Object, StackTrace)
        onError = _registerErrorHandler(onError, currentZone);
      }
    }
    _Future<R> result = _Future<R>();
    _addListener(_FutureListener<T, R>.then(result, f, onError));
    return result;
  }

  /// Registers a system created result and error continuation.
  ///
  /// Used by the implementation of `await` to listen to a future.
  /// The system created listeners are not registered in the zone.
  Future<E> _thenAwait<E>(FutureOr<E> f(T value), Function onError) {
    _Future<E> result = _Future<E>();
    _addListener(_FutureListener<T, E>.thenAwait(result, f, onError));
    return result;
  }

  void _ignore() {
    _state |= _stateIgnoreError;
    if (_isChained) {
      // Mark chain source. If it has no listeners at all, then neither
      // does this future. (But this may suppress errors on other futures
      // with the same chain source and no listeners, which haven't been
      // ignored.)
      _Future<Object?> source = this;
      do {
        source = source._chainSource;
      } while (source._isChained);
      source._state |= _stateIgnoreError;
    }
  }

  Future<T> catchError(Function onError, {bool test(Object error)?}) {
    _Future<T> result = _Future<T>();
    if (!identical(result._zone, _rootZone)) {
      onError = _registerErrorHandler(onError, result._zone);
      if (test != null) test = result._zone.registerUnaryCallback(test);
    }
    _addListener(_FutureListener<T, T>.catchError(result, onError, test));
    return result;
  }

  // Used by extension method `onError` to up-cast the result to `R`.
  //
  // Not public because we cannot statically ensure that [R] is a supertype
  // of [T].
  //
  // Avoids needing to allocate an extra value handler to do the up cast,
  // which is needed if using `.then`.
  Future<R> _safeOnError<R>(FutureOr<R> Function(Object, StackTrace) onError) {
    assert(this is _Future<R>); // Is up-cast.
    _Future<R> result = _Future<R>();
    if (!identical(result._zone, _rootZone)) {
      onError = result._zone.registerBinaryCallback(onError);
    }
    _addListener(_FutureListener<T, R>.catchError(result, onError, null));
    return result;
  }

  Future<T> whenComplete(dynamic action()) {
    _Future<T> result = _Future<T>();
    if (!identical(result._zone, _rootZone)) {
      action = result._zone.registerCallback<dynamic>(action);
    }
    _addListener(_FutureListener<T, T>.whenComplete(result, action));
    return result;
  }

  Stream<T> asStream() => Stream<T>.fromFuture(this);

  void _setPendingComplete() {
    assert(_mayComplete); // Aka. _stateIncomplete
    _state ^= _stateIncomplete ^ _statePendingComplete;
  }

  void _clearPendingComplete() {
    assert(_isPendingComplete);
    _state ^= _statePendingComplete ^ _stateIncomplete;
  }

  AsyncError get _error {
    assert(_hasError);
    return _resultOrListeners;
  }

  _Future get _chainSource {
    assert(_isChained);
    return _resultOrListeners;
  }

  // This method is used by async/await.
  void _setValue(T value) {
    assert(!_isComplete); // But may have a completion pending.
    _state = _stateValue;
    _resultOrListeners = value;
  }

  void _setErrorObject(AsyncError error) {
    assert(!_isComplete); // But may have a completion pending.
    _state = _stateError | (_state & _stateIgnoreError);
    _resultOrListeners = error;
  }

  /// Copy the completion result of [source] into this future.
  ///
  /// Used when a chained future notices that its source is completed.
  void _cloneResult(_Future source) {
    assert(!_isComplete);
    assert(source._isComplete);
    _state =
        (source._state & _completionStateMask) | (_state & _stateIgnoreError);
    _resultOrListeners = source._resultOrListeners;
  }

  void _addListener(_FutureListener listener) {
    assert(listener._nextListener == null);
    if (_mayAddListener) {
      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);
      }
      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;
        _FutureListener? next = cursor._nextListener;
        while (next != null) {
          cursor = next;
          next = 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);
      });
    }
  }

  _FutureListener? _removeListeners() {
    // Reverse listeners before returning them, so the resulting list is in
    // subscription order.
    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;
      prev = current;
      current = next;
    }
    return prev;
  }

  /// Completes this future with the result of [source].
  ///
  /// The [source] future should not be a [_Future], use
  /// [_chainCoreFuture] for those.
  ///
  /// Since [source] is an unknown [Future], it's interacted with
  /// through [Future.then], which is required to be asynchronous.
  void _chainForeignFuture(Future source) {
    assert(!_isComplete);
    assert(source is! _Future);

    // Mark the target as chained (and as such half-completed).
    _setPendingComplete();
    try {
      source.then(
        (value) {
          assert(_isPendingComplete);
          _clearPendingComplete(); // Clear this first, it's set again.
          try {
            _completeWithValue(value as T);
          } catch (error, stackTrace) {
            _completeError(error, stackTrace);
          }
        },
        onError: (Object error, StackTrace stackTrace) {
          assert(_isPendingComplete);
          _completeError(error, stackTrace);
        },
      );
    } catch (e, s) {
      // This only happens if the `then` call threw synchronously when given
      // valid arguments.
      // That requires a non-conforming implementation of the Future interface,
      // which should, hopefully, never happen.
      scheduleMicrotask(() {
        _completeError(e, s);
      });
    }
  }

  /// Synchronously completes a target future with another, source, future.
  ///
  /// If the source future is already completed, its result is synchronously
  /// propagated to the target future's listeners.
  /// If the source future is not completed, the target future is made
  /// to listen for its completion.
  static void _chainCoreFuture(_Future source, _Future target, bool sync) {
    assert(target._mayAddListener); // Not completed, not already chained.
    while (source._isChained) {
      source = source._chainSource;
    }
    if (identical(source, target)) {
      target._asyncCompleteError(
        ArgumentError.value(
          source,
          null,
          "Cannot complete a future with itself",
        ),
        StackTrace.current,
      );
      return;
    }
    var ignoreError = target._state & _stateIgnoreError;
    source._state |= ignoreError;
    if (!source._isComplete) {
      // Chain immediately if the source is not complete.
      // This won't call any listeners, whether completing sync or async.
      _FutureListener? listeners = target._resultOrListeners;
      target._setChained(source);
      source._prependListeners(listeners);
      return;
    }

    if (sync ||
        (target._resultOrListeners == null &&
            (!source._hasError || ignoreError != 0))) {
      // Complete synchronously when allowed.
      // If no-one is listening this won't call any listeners synchronously.
      // Do delay un-ignored errors to give time to add listeners.
      _FutureListener? listeners = target._removeListeners();
      target._cloneResult(source);
      _propagateToListeners(target, listeners);
      return;
    }
    // Otherwise delay the chaining to avoid any synchronous callbacks.
    target._setPendingComplete();
    target._zone.scheduleMicrotask(() {
      _chainCoreFuture(source, target, _allowCompleteSync);
    });
  }

  /// Synchronously completes this future with [value].
  ///
  /// If [value] is a value or an already completed [_Future],
  /// the result is immediately used to complete this future.
  /// If [value] is an incomplete future, this future will wait for
  /// it to complete, then use the result.
  void _complete(FutureOr<T> value) {
    assert(!_isComplete);
    if (value is Future<T>) {
      if (value is _Future<T>) {
        _chainCoreFuture(value, this, _allowCompleteSync);
      } else {
        _chainForeignFuture(value);
      }
    } else {
      _FutureListener? listeners = _removeListeners();
      _setValue(value);
      _propagateToListeners(this, listeners);
    }
  }

  void _completeWithValue(T value) {
    assert(!_isComplete);

    _FutureListener? listeners = _removeListeners();
    _setValue(value);
    _propagateToListeners(this, listeners);
  }

  void _completeWithResultOf(_Future<Object?> source) {
    assert(source._isComplete);
    if (source._hasError && !_zone.inSameErrorZone(source._zone)) {
      return;
    }
    _FutureListener? listeners = _removeListeners();
    _cloneResult(source);
    _propagateToListeners(this, listeners);
  }

  void _completeErrorObject(AsyncError error) {
    assert(!_isComplete);

    _FutureListener? listeners = _removeListeners();
    _setErrorObject(error);
    _propagateToListeners(this, listeners);
  }

  void _completeError(Object error, StackTrace stackTrace) {
    _completeErrorObject(AsyncError(error, stackTrace));
  }

  // Completes future in a later microtask.
  void _asyncComplete(FutureOr<T> value) {
    assert(!_isComplete); // Allows both pending complete and incomplete.
    // Two corner cases if the value is a future:
    //   1. the future is already completed and an error.
    //   2. the future is not yet completed but might become an error.
    // The first case means that we must not immediately complete the Future,
    // as our code would immediately start propagating the error without
    // giving the time to install error-handlers.
    // However the second case requires us to deal with the value immediately.
    // Otherwise the value could complete with an error and report an
    // unhandled error, even though we know we are already going to listen to
    // it.

    if (value is Future<T>) {
      _chainFuture(value);
      return;
    }
    _asyncCompleteWithValue(value);
  }

  /// Internal helper function used by the implementation of `async` functions.
  ///
  /// Like [_asyncComplete], but avoids type checks that are guaranteed to
  /// succeed by the way the function is called.
  /// Should be used judiciously.
  void _asyncCompleteUnchecked(/*FutureOr<T>*/ dynamic value) {
    // Ensure [value] is FutureOr<T>, do so using an `as` check so it works
    // also correctly in non-sound null-safety mode.
    assert(identical(value as FutureOr<T>, value));
    final typedValue = unsafeCast<FutureOr<T>>(value);

    // Doing just "is Future" is not sufficient.
    // If `T` is Object` and `value` is `Future<Object?>.value(null)`,
    // then value is a `Future`, but not a `Future<T>`, and going through the
    // `_chainFuture` branch would end up assigning `null` to `Object`.
    if (typedValue is Future<T>) {
      _chainFuture(typedValue);
      return;
    }
    _asyncCompleteWithValue(unsafeCast<T>(typedValue));
  }

  /// Internal helper function used to implement `async` functions.
  ///
  /// Like [_asyncCompleteUnchecked], but avoids a `is Future<T>` check due to
  /// having a static guarantee on the callsite that the [value] cannot be a
  /// [Future].
  /// Should be used judiciously.
  void _asyncCompleteUncheckedNoFuture(/*T*/ dynamic value) {
    // Ensure [value] is T, do so using an `as` check so it works also correctly
    // in non-sound null-safety mode.
    assert(identical(value as T, value));
    _asyncCompleteWithValue(unsafeCast<T>(value));
  }

  void _asyncCompleteWithValue(T value) {
    _setPendingComplete();
    _zone.scheduleMicrotask(() {
      _completeWithValue(value);
    });
  }

  /// Asynchronously completes a future with another future.
  ///
  /// Even if [value] is already completed, it won't synchronously
  /// complete this completer's future.
  void _chainFuture(Future<T> value) {
    assert(_mayComplete);
    if (value is _Future<T>) {
      // Chain ensuring that we don't complete synchronously.
      _chainCoreFuture(value, this, _requireCompleteAsync);
      return;
    }
    // Just listen on the foreign future. This guarantees an async delay.
    _chainForeignFuture(value);
  }

  void _asyncCompleteError(Object error, StackTrace stackTrace) {
    _asyncCompleteErrorObject(AsyncError(error, stackTrace));
  }

  void _asyncCompleteErrorObject(AsyncError error) {
    assert(!_isComplete);

    _setPendingComplete();
    _zone.scheduleMicrotask(() {
      _completeErrorObject(error);
    });
  }

  /// Propagates the value/error of [source] to its [listeners], executing the
  /// listeners' callbacks.
  static void _propagateToListeners(
    _Future source,
    _FutureListener? listeners,
  ) {
    while (true) {
      assert(source._isComplete);
      bool hasError = source._hasError;
      if (listeners == null) {
        if (hasError && !source._ignoreError) {
          AsyncError asyncError = source._error;
          source._zone.handleUncaughtError(
            asyncError.error,
            asyncError.stackTrace,
          );
        }
        return;
      }
      // Usually futures only have one listener. If they have several, we
      // call handle them separately in recursive calls, continuing
      // here only when there is only one listener left.
      _FutureListener listener = listeners;
      _FutureListener? nextListener = listener._nextListener;
      while (nextListener != null) {
        listener._nextListener = null;
        _propagateToListeners(source, listener);
        listener = nextListener;
        nextListener = listener._nextListener;
      }

      final dynamic sourceResult = source._resultOrListeners;
      // Do the actual propagation.
      // Set initial state of listenerHasError and listenerValueOrError. These
      // variables are updated with the outcome of potential callbacks.
      // Non-error results, including futures, are stored in
      // listenerValueOrError and listenerHasError is set to false. Errors
      // are stored in listenerValueOrError as an [AsyncError] and
      // listenerHasError is set to true.
      bool listenerHasError = hasError;
      var listenerValueOrError = sourceResult;

      // Only if we either have an error or callbacks, go into this, somewhat
      // expensive, branch. Here we'll enter/leave the zone. Many futures
      // don't have callbacks, so this is a significant optimization.
      if (hasError || listener.handlesValue || listener.handlesComplete) {
        _Zone zone = listener._zone;
        if (hasError && !source._zone.inSameErrorZone(zone)) {
          // Don't cross zone boundaries with errors.
          AsyncError asyncError = source._error;
          source._zone.handleUncaughtError(
            asyncError.error,
            asyncError.stackTrace,
          );
          return;
        }

        _Zone? oldZone;
        if (!identical(Zone._current, zone)) {
          // Change zone if it's not current.
          oldZone = Zone._enter(zone);
        }

        // These callbacks are abstracted to isolate the try/catch blocks
        // from the rest of the code to work around a V8 glass jaw.
        void handleWhenCompleteCallback() {
          // The whenComplete-handler is not combined with normal value/error
          // handling. This means at most one handleX method is called per
          // listener.
          assert(!listener.handlesValue);
          assert(!listener.handlesError);
          var completeResult;
          try {
            completeResult = listener.handleWhenComplete();
          } catch (e, s) {
            if (hasError && identical(source._error.error, e)) {
              listenerValueOrError = source._error;
            } else {
              listenerValueOrError = AsyncError(e, s);
            }
            listenerHasError = true;
            return;
          }
          if (completeResult is _Future && completeResult._isComplete) {
            if (completeResult._hasError) {
              listenerValueOrError = completeResult._error;
              listenerHasError = true;
            }
            // Otherwise use the existing result of source.
            return;
          }
          if (completeResult is Future) {
            // We have to wait for the completeResult future to complete
            // before knowing if it's an error or we should use the result
            // of source.
            var originalSource = source;
            var joinedResult = source._newFutureWithSameType();
            completeResult.then<void>(
              (_) {
                joinedResult._completeWithResultOf(originalSource);
              },
              onError: (Object e, StackTrace s) {
                joinedResult._completeErrorObject(AsyncError(e, s));
              },
            );
            listenerValueOrError = joinedResult;
            listenerHasError = false;
          }
        }

        void handleValueCallback() {
          try {
            listenerValueOrError = listener.handleValue(sourceResult);
          } catch (e, s) {
            listenerValueOrError = AsyncError(e, s);
            listenerHasError = true;
          }
        }

        void handleError() {
          try {
            AsyncError asyncError = source._error;
            if (listener.matchesErrorTest(asyncError) &&
                listener.hasErrorCallback) {
              listenerValueOrError = listener.handleError(asyncError);
              listenerHasError = false;
            }
          } catch (e, s) {
            if (identical(source._error.error, e)) {
              listenerValueOrError = source._error;
            } else {
              listenerValueOrError = AsyncError(e, s);
            }
            listenerHasError = true;
          }
        }

        if (listener.handlesComplete) {
          handleWhenCompleteCallback();
        } else if (!hasError) {
          if (listener.handlesValue) {
            handleValueCallback();
          }
        } else {
          if (listener.handlesError) {
            handleError();
          }
        }

        // If we changed zone, oldZone will not be null.
        if (oldZone != null) Zone._leave(oldZone);

        // If the listener's value is a future we *might* need to chain it. Note that
        // this can only happen if there is a callback.
        if (listenerValueOrError is Future &&
            listener.shouldChain(listenerValueOrError)) {
          Future chainSource = listenerValueOrError;
          // Shortcut if the chain-source is already completed. Just continue
          // the loop.
          _Future result = listener.result;
          if (chainSource is _Future) {
            if (chainSource._isComplete) {
              listeners = result._removeListeners();
              result._cloneResult(chainSource);
              source = chainSource;
              continue;
            } else {
              _chainCoreFuture(chainSource, result, _allowCompleteSync);
            }
          } else {
            result._chainForeignFuture(chainSource);
          }
          return;
        }
      }

      _Future result = listener.result;
      listeners = result._removeListeners();
      if (!listenerHasError) {
        result._setValue(listenerValueOrError);
      } else {
        AsyncError asyncError = listenerValueOrError;
        result._setErrorObject(asyncError);
      }
      // Prepare for next round.
      source = result;
    }
  }

  /// New uncompleted future with same type.
  ///
  /// In same zone or other [zone] if specified.
  _Future<T> _newFutureWithSameType([_Zone? zone]) =>
      _Future<T>.zone(zone ?? _zone);

  @pragma("vm:entry-point")
  Future<T> timeout(Duration timeLimit, {FutureOr<T> onTimeout()?}) {
    if (_isComplete) return _Future.immediate(this);
    @pragma('vm:awaiter-link')
    _Future<T> _future = _Future<T>();
    Timer timer;
    if (onTimeout == null) {
      timer = Timer(timeLimit, () {
        _future._completeErrorObject(
          AsyncError(
            TimeoutException("Future not completed", timeLimit),
            StackTrace.current,
          ),
        );
      });
    } else {
      Zone zone = Zone.current;
      FutureOr<T> Function() onTimeoutHandler = zone.registerCallback(
        onTimeout,
      );

      timer = Timer(timeLimit, () {
        try {
          _future._complete(zone.run(onTimeoutHandler));
        } catch (e, s) {
          _future._completeErrorObject(AsyncError(e, s));
        }
      });
    }
    this.then(
      (T v) {
        if (timer.isActive) {
          timer.cancel();
          _future._completeWithValue(v);
        }
      },
      onError: (Object e, StackTrace s) {
        if (timer.isActive) {
          timer.cancel();
          _future._completeErrorObject(AsyncError(e, s));
        }
      },
    );
    return _future;
  }
}

/// Registers errorHandler in zone if it has the correct type.
///
/// Checks that the function accepts either an [Object] and a [StackTrace]
/// or just one [Object]. Does not check the return type.
/// The actually returned value must be `FutureOr<R>` where `R` is the
/// value type of the future that the call will complete (either returned
/// by [Future.then] or [Future.catchError]). We check the returned value
/// dynamically because the functions are passed as arguments in positions
/// without inference, so a function expression won't infer the return type.
///
/// Throws if the type is not valid.
Function _registerErrorHandler(Function errorHandler, Zone zone) {
  if (errorHandler is dynamic Function(Object, StackTrace)) {
    return zone.registerBinaryCallback<dynamic, Object, StackTrace>(
      errorHandler,
    );
  }
  if (errorHandler is dynamic Function(Object)) {
    return zone.registerUnaryCallback<dynamic, Object>(errorHandler);
  }
  throw ArgumentError.value(
    errorHandler,
    "onError",
    "Error handler must accept one Object or one Object and a StackTrace"
        " as arguments, and return a value of the returned future's type",
  );
}

// Names for positional arguments to _chainCoreFuture.
const _allowCompleteSync = true;
const _requireCompleteAsync = false;
