Esempio n. 1
0
        public static Future sync(Func <FutureOr> computation)
        {
            try {
                var result = computation();
                if (result.isFuture)
                {
                    return(result.f);
                }
                else
                {
                    return(_Future.value(result));
                }
            }
            catch (Exception error) {
                var        future      = new _Future();
                AsyncError replacement = Zone.current.errorCallback(error);
                if (replacement != null)
                {
                    future._asyncCompleteError(async_._nonNullError(replacement.InnerException));
                }
                else
                {
                    future._asyncCompleteError(error);
                }

                return(future);
            }
        }
Esempio n. 2
0
        public FutureOr handleError(AsyncError asyncError)
        {
            D.assert(handlesError && hasErrorCallback);

            var errorCallback = this.errorCallback;

            return((FutureOr)_zone.runUnary(arg => errorCallback((Exception)arg), asyncError.InnerException));
        }
Esempio n. 3
0
 public bool matchesErrorTest(AsyncError asyncError)
 {
     if (!hasErrorTest)
     {
         return(true);
     }
     return((bool)_zone.runUnary(arg => _errorTest((Exception)arg), asyncError.InnerException));
 }
Esempio n. 4
0
        // @Since("2.5")
        public static Stream <T> error(object error, string stackTrace = null)
        {
            // ArgumentError.checkNotNull(error, "error");
            var result = new _AsyncStreamController <T>(null, null, null, null);

            result._addError(error, stackTrace ?? AsyncError.defaultStackTrace(error));
            result._closeUnchecked();
            return(result.stream);
        }
Esempio n. 5
0
        internal static void _asyncCompleteWithErrorCallback(_Future result, Exception error)
        {
            AsyncError replacement = Zone.current.errorCallback(error);

            if (replacement != null)
            {
                error = _nonNullError(replacement.InnerException);
            }

            result._asyncCompleteError(error);
        }
Esempio n. 6
0
//
        internal static void _addErrorWithReplacement <T>(_EventSink <T> sink, Exception error, string stackTrace)
        {
            AsyncError replacement = Zone.current.errorCallback(error);

            if (replacement != null)
            {
                error      = async_._nonNullError(replacement);
                stackTrace = replacement.StackTrace;
            }

            sink._addError(error, stackTrace);
        }
Esempio n. 7
0
        internal static void _cancelAndErrorWithReplacement <T>(StreamSubscription <T> subscription,
                                                                _Future future, Exception error)
        {
            AsyncError replacement = Zone.current.errorCallback(error);

            if (replacement != null)
            {
                error = (Exception)_async._nonNullError(replacement);
            }

            _cancelAndError(subscription, future, error);
        }
Esempio n. 8
0
        public override void addError(object error, string stackTrace)
        {
            // ArgumentError.checkNotNull(error, "error");
            if (_isClosed)
            {
                throw new Exception("Sink is closed");
            }

            if (_handleError != null)
            {
                stackTrace = stackTrace ?? AsyncError.defaultStackTrace(error);
                _handleError(error, stackTrace, _sink);
            }
            else
            {
                _sink.addError(error, stackTrace);
            }
        }
Esempio n. 9
0
        public static Future error(Exception error)
        {
            if (error == null)
            {
                throw new ArgumentNullException(nameof(error));
            }

            if (!ReferenceEquals(Zone.current, async_._rootZone))
            {
                AsyncError replacement = Zone.current.errorCallback(error);
                if (replacement != null)
                {
                    error = async_._nonNullError(replacement.InnerException);
                }
            }

            return(_Future.immediateError(error));
        }
Esempio n. 10
0
 /** Runs user code and takes actions depending on success or failure. */
 internal static void _runUserCode <T>(
     Func <T> userCode, Action <T> onSuccess, Action <Exception> onError)
 {
     try {
         onSuccess(userCode());
     }
     catch (Exception e) {
         AsyncError replacement = Zone.current.errorCallback(e);
         if (replacement == null)
         {
             onError(e);
         }
         else
         {
             var error = async_._nonNullError(replacement);
             onError(error);
         }
     }
 }
Esempio n. 11
0
        public override void completeError(Exception error)
        {
            if (error == null)
            {
                throw new ArgumentNullException(nameof(error));
            }

            if (!_future._mayComplete)
            {
                throw new Exception("Future already completed");
            }
            AsyncError replacement = Zone.current.errorCallback(error);

            if (replacement != null)
            {
                error = async_._nonNullError(replacement.InnerException);
            }

            _completeError(error);
        }
Esempio n. 12
0
 public override void addError(object error, string stackTrace)
 {
     _sink._addError(error, stackTrace ?? AsyncError.defaultStackTrace(error));
 }
Esempio n. 13
0
        static void _propagateToListeners(_Future source, _FutureListener listeners)
        {
            while (true)
            {
                D.assert(source._isComplete);
                bool hasError = source._hasError;
                if (listeners == null)
                {
                    if (hasError)
                    {
                        AsyncError asyncError = source._error;
                        source._zone.handleUncaughtError(asyncError);
                    }

                    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.
                while (listeners._nextListener != null)
                {
                    _FutureListener currentListener = listeners;
                    listeners = currentListener._nextListener;
                    currentListener._nextListener = null;
                    _propagateToListeners(source, currentListener);
                }

                _FutureListener listener     = listeners;
                var             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);
                        return;
                    }

                    Zone oldZone = null;
                    if (!ReferenceEquals(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.
                    Action handleWhenCompleteCallback = () => {
                        // The whenComplete-handler is not combined with normal value/error
                        // handling. This means at most one handleX method is called per
                        // listener.
                        D.assert(!listener.handlesValue);
                        D.assert(!listener.handlesError);
                        FutureOr completeResult;
                        try {
                            completeResult = listener.handleWhenComplete();
                        }
                        catch (Exception e) {
                            if (hasError && ReferenceEquals(source._error.InnerException, e))
                            {
                                listenerValueOrError = source._error;
                            }
                            else
                            {
                                listenerValueOrError = new AsyncError(e);
                            }

                            listenerHasError = true;
                            return;
                        }

                        if (completeResult.isFuture)
                        {
                            var completeResultFuture = completeResult.f;
                            if (completeResultFuture is _Future completeResultCoreFuture &&
                                completeResultCoreFuture._isComplete)
                            {
                                if (completeResultCoreFuture._hasError)
                                {
                                    listenerValueOrError = completeResultCoreFuture._error;
                                    listenerHasError     = true;
                                }

                                // Otherwise use the existing result of source.
                                return;
                            }

                            // 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;
                            listenerValueOrError =
                                completeResultFuture.then((_) => FutureOr.future(originalSource));
                            listenerHasError = false;
                        }
                    };

                    Action handleValueCallback = () => {
                        try {
                            listenerValueOrError = listener.handleValue(sourceResult);
                        }
                        catch (Exception e) {
                            listenerValueOrError = new AsyncError(e);
                            listenerHasError     = true;
                        }
                    };

                    Action handleError = () => {
                        try {
                            AsyncError asyncError = source._error;
                            if (listener.matchesErrorTest(asyncError) &&
                                listener.hasErrorCallback)
                            {
                                listenerValueOrError = listener.handleError(asyncError);
                                listenerHasError     = false;
                            }
                        }
                        catch (Exception e) {
                            if (ReferenceEquals(source._error.InnerException, e))
                            {
                                listenerValueOrError = source._error;
                            }
                            else
                            {
                                listenerValueOrError = new AsyncError(e);
                            }

                            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 (listenerValueOrError is FutureOr futureOr)
                    {
                        listenerValueOrError = futureOr.isFuture ? futureOr.f : futureOr.v;
                    }

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

                        return;
                    }
                }

                _Future result = listener.result;
                listeners = result._removeListeners();
                if (!listenerHasError)
                {
                    result._setValue(listenerValueOrError);
                }
                else
                {
                    AsyncError asyncError = (AsyncError)listenerValueOrError;
                    result._setErrorObject(asyncError);
                }

                // Prepare for next round.
                source = result;
            }
        }
Esempio n. 14
0
 internal void _setErrorObject(AsyncError error)
 {
     D.assert(!_isComplete); // But may have a completion pending.
     _state             = _stateError;
     _resultOrListeners = error;
 }