// 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("vm:entry-point")
  final _Future<T> future = _Future<T>();

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

  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> {
  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")
  @pragma("vm:invisible")
  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;
}

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;
