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