/*!
 * NevWare21 Solutions LLC - ts-async, 0.6.1
 * https://github.com/nevware21/ts-async
 * Copyright (c) NevWare21 Solutions LLC and contributors. All rights reserved.
 * Licensed under the MIT license.
 */
import { isPromiseLike, objDefineProperties, getDocument, createCachedValue, safe, getInst, dumpObj, arrSlice, iterForOf, objDefineProp, hasSymbol, getKnownSymbol, isFunction, throwTypeError, isUndefined, scheduleTimeout, isNode, getWindow, getGlobal, objDefine, objToString, isArray, arrForEach, isIterable, createCustomError, isNumber, scheduleMicrotask, scheduleIdleCallback, utcNow, getLength, isIterator, fnCall, arrIndexOf } from '@nevware21/ts-utils';

var STR_PROMISE = "Promise";
var DONE = "done";
var VALUE = "value";
var RETURN = "return";
var REJECTED = "rejected";

function doAwaitResponse(value, cb) {
    return doAwait(value, function (value) {
        return cb ? cb({
            status: "fulfilled",
            rejected: false,
            value: value
        }) : value;
    }, function (reason) {
        return cb ? cb({
            status: REJECTED,
            rejected: true,
            reason: reason
        }) : reason;
    });
}
function doAwait(value, resolveFn, rejectFn, finallyFn) {
    var result = value;
    try {
        if (isPromiseLike(value)) {
            if (resolveFn || rejectFn) {
                result = value.then(resolveFn, rejectFn);
            }
        }
        else {
            try {
                if (resolveFn) {
                    result = resolveFn(value);
                }
            }
            catch (err) {
                if (rejectFn) {
                    result = rejectFn(err);
                }
                else {
                    throw err;
                }
            }
        }
    }
    finally {
        if (finallyFn) {
            doFinally(result, finallyFn);
        }
    }
    return result;
}
function doFinally(value, finallyFn) {
    var result = value;
    if (finallyFn) {
        if (isPromiseLike(value)) {
            if (value.finally) {
                result = value.finally(finallyFn);
            }
            else {
                result = value.then(function (value) {
                    return doAwait(finallyFn(), function () {
                        return value;
                    });
                }, function (reason) {
                    return doAwait(finallyFn(), function () {
                        throw reason;
                    });
                });
            }
        }
        else {
            finallyFn();
        }
    }
    return result;
}

/*#__NO_SIDE_EFFECTS__*/
function _pureAssign(func1, func2) {
    return func1 || func2;
}

var _debugState;
var _debugResult;
var _debugHandled;
var _promiseDebugEnabled = false;
function _addDebugState$1(thePromise, stateFn, resultFn, handledFn) {
    _debugState = _debugState || { toString: function () { return "[[PromiseState]]"; } };
    _debugResult = _debugResult || { toString: function () { return "[[PromiseResult]]"; } };
    _debugHandled = _debugHandled || { toString: function () { return "[[PromiseIsHandled]]"; } };
    var props = {};
    props[_debugState] = { get: stateFn };
    props[_debugResult] = { get: resultFn };
    props[_debugHandled] = { get: handledFn };
    objDefineProperties(thePromise, props);
}
function setPromiseDebugState(enabled, logger) {
    _promiseDebugEnabled = enabled;
}

var STRING_STATES = [
    "pending", "resolving", "resolved", REJECTED
];

var DISPATCH_EVENT = "dispatchEvent";
var _hasInitEvent;
function _hasInitEventFn(doc) {
    var evt;
    if (doc && doc.createEvent) {
        evt = doc.createEvent("Event");
    }
    return (!!evt && evt.initEvent);
}
function emitEvent(target, evtName, populateEvent, useNewEvent) {
    var doc = getDocument();
    !_hasInitEvent && (_hasInitEvent = createCachedValue(!!safe(_hasInitEventFn, [doc]).v));
    var theEvt = _hasInitEvent.v ? doc.createEvent("Event") : (useNewEvent ? new Event(evtName) : {});
    populateEvent && populateEvent(theEvt);
    if (_hasInitEvent.v) {
        theEvt.initEvent(evtName, false, true);
    }
    if (theEvt && target[DISPATCH_EVENT]) {
        target[DISPATCH_EVENT](theEvt);
    }
    else {
        var handler = target["on" + evtName];
        if (handler) {
            handler(theEvt);
        }
        else {
            var theConsole = getInst("console");
            theConsole && (theConsole["error"] || theConsole["log"])(evtName, dumpObj(theEvt));
        }
    }
}

var NODE_UNHANDLED_REJECTION = "unhandledRejection";
var UNHANDLED_REJECTION = NODE_UNHANDLED_REJECTION.toLowerCase();
var _currentPromiseId = [];
var _uniquePromiseId = 0;
var _unhandledRejectionTimeout = 10;
var _aggregationError;
var _hasPromiseRejectionEvent;
function dumpFnObj(value) {
    if (isFunction(value)) {
        return value.toString();
    }
    return dumpObj(value);
}
/*#__NO_SIDE_EFFECTS__*/
function _createAggregationError(values) {
    !_aggregationError && (_aggregationError = createCachedValue(safe(getInst, ["AggregationError"]).v || createCustomError("AggregationError", function (self, args) {
        self.errors = args[0];
    })));
    return new _aggregationError.v(values);
}
function _createPromise(newPromise, processor, executor) {
    var additionalArgs = arrSlice(arguments, 3);
    var _state = 0 ;
    var _hasResolved = false;
    var _settledValue;
    var _queue = [];
    var _id = _uniquePromiseId++;
    var _parentId = _currentPromiseId.length > 0 ? _currentPromiseId[_currentPromiseId.length - 1] : undefined;
    var _handled = false;
    var _unHandledRejectionHandler = null;
    var _thePromise;
    function _then(onResolved, onRejected) {
        try {
            _currentPromiseId.push(_id);
            _handled = true;
            _unHandledRejectionHandler && _unHandledRejectionHandler.cancel();
            _unHandledRejectionHandler = null;
            var thenPromise = newPromise(function (resolve, reject) {
                _queue.push(function () {
                    try {
                        var handler = _state === 2  ? onResolved : onRejected;
                        var value = isFunction(handler) ? handler(_settledValue) : _settledValue;
                        if (isPromiseLike(value)) {
                            value.then(resolve, reject);
                        }
                        else if (isFunction(handler)) {
                            resolve(value);
                        }
                        else if (_state === 3 ) {
                            reject(value);
                        }
                        else {
                            resolve(value);
                        }
                    }
                    catch (e) {
                        reject(e);
                    }
                });
                if (_hasResolved) {
                    _processQueue();
                }
            }, additionalArgs);
            return thenPromise;
        }
        finally {
            _currentPromiseId.pop();
        }
    }
    function _catch(onRejected) {
        return _then(undefined, onRejected);
    }
    function _finally(onFinally) {
        var thenFinally = onFinally;
        var catchFinally = onFinally;
        if (isFunction(onFinally)) {
            thenFinally = function (value) {
                return doAwait(onFinally && onFinally(), function () {
                    return value;
                });
            };
            catchFinally = function (reason) {
                return doAwait(onFinally && onFinally(), function () {
                    throw reason;
                });
            };
        }
        return _then(thenFinally, catchFinally);
    }
    function _strState() {
        return STRING_STATES[_state];
    }
    function _processQueue() {
        if (_queue.length > 0) {
            var pending = _queue.slice();
            _queue = [];
            _handled = true;
            _unHandledRejectionHandler && _unHandledRejectionHandler.cancel();
            _unHandledRejectionHandler = null;
            processor(pending);
        }
    }
    function _createSettleIfFn(newState, allowState) {
        return function (theValue) {
            if (_state === allowState) {
                if (newState === 2  && isPromiseLike(theValue)) {
                    _state = 1 ;
                    theValue.then(_createSettleIfFn(2 , 1 ), _createSettleIfFn(3 , 1 ));
                    return;
                }
                _state = newState;
                _hasResolved = true;
                _settledValue = theValue;
                _processQueue();
                if (!_handled && newState === 3  && !_unHandledRejectionHandler) {
                    _unHandledRejectionHandler = scheduleTimeout(_notifyUnhandledRejection, _unhandledRejectionTimeout);
                }
            }
        };
    }
    function _notifyUnhandledRejection() {
        if (!_handled) {
            _handled = true;
            if (isNode()) {
                process.emit(NODE_UNHANDLED_REJECTION, _settledValue, _thePromise);
            }
            else {
                var gbl = getWindow() || getGlobal();
                !_hasPromiseRejectionEvent && (_hasPromiseRejectionEvent = createCachedValue(safe((getInst), [STR_PROMISE + "RejectionEvent"]).v));
                emitEvent(gbl, UNHANDLED_REJECTION, function (theEvt) {
                    objDefine(theEvt, "promise", { g: function () { return _thePromise; } });
                    theEvt.reason = _settledValue;
                    return theEvt;
                }, !!_hasPromiseRejectionEvent.v);
            }
        }
    }
    _thePromise = {
        then: _then,
        "catch": _catch,
        finally: _finally
    };
    objDefineProp(_thePromise, "state", {
        get: _strState
    });
    if (_promiseDebugEnabled) {
        _addDebugState$1(_thePromise, _strState, function () { return objToString(_settledValue); }, function () { return _handled; });
    }
    if (hasSymbol()) {
        _thePromise[getKnownSymbol(11 )] = "IPromise";
    }
    function _toString() {
        return "IPromise" + (_promiseDebugEnabled ? "[" + _id + (!isUndefined(_parentId) ? (":" + _parentId) : "") + "]" : "") + " " + _strState() + (_hasResolved ? (" - " + dumpFnObj(_settledValue)) : "") + ("");
    }
    _thePromise.toString = _toString;
    (function _initialize() {
        if (!isFunction(executor)) {
            throwTypeError(STR_PROMISE + ": executor is not a function - " + dumpFnObj(executor));
        }
        var _rejectFn = _createSettleIfFn(3 , 0 );
        try {
            executor.call(_thePromise, _createSettleIfFn(2 , 0 ), _rejectFn);
        }
        catch (e) {
            _rejectFn(e);
        }
    })();
    return _thePromise;
}
/*#__NO_SIDE_EFFECTS__*/
function _createAllPromise(newPromise) {
    return function (input) {
        var additionalArgs = arrSlice(arguments, 1);
        return newPromise(function (resolve, reject) {
            try {
                var values_1 = [];
                var pending_1 = 1;
                iterForOf(input, function (item, idx) {
                    if (item) {
                        pending_1++;
                        doAwait(item, function (value) {
                            values_1[idx] = value;
                            if (--pending_1 === 0) {
                                resolve(values_1);
                            }
                        }, reject);
                    }
                });
                pending_1--;
                if (pending_1 === 0) {
                    resolve(values_1);
                }
            }
            catch (e) {
                reject(e);
            }
        }, additionalArgs);
    };
}
/*#__NO_SIDE_EFFECTS__*/
function _createResolvedPromise(newPromise) {
    return function (value) {
        var additionalArgs = arrSlice(arguments, 1);
        if (isPromiseLike(value)) {
            return value;
        }
        return newPromise(function (resolve) {
            resolve(value);
        }, additionalArgs);
    };
}
/*#__NO_SIDE_EFFECTS__*/
function _createRejectedPromise(newPromise) {
    return function (reason) {
        var additionalArgs = arrSlice(arguments, 1);
        return newPromise(function (_resolve, reject) {
            reject(reason);
        }, additionalArgs);
    };
}
/*#__NO_SIDE_EFFECTS__*/
function _createAllSettledPromise(newPromise) {
    return createCachedValue(function (input) {
        var additionalArgs = arrSlice(arguments, 1);
        return newPromise(function (resolve, reject) {
            var values = [];
            var pending = 1;
            function processItem(item, idx) {
                pending++;
                doAwaitResponse(item, function (value) {
                    if (value.rejected) {
                        values[idx] = {
                            status: REJECTED,
                            reason: value.reason
                        };
                    }
                    else {
                        values[idx] = {
                            status: "fulfilled",
                            value: value.value
                        };
                    }
                    if (--pending === 0) {
                        resolve(values);
                    }
                });
            }
            try {
                if (isArray(input)) {
                    arrForEach(input, processItem);
                }
                else if (isIterable(input)) {
                    iterForOf(input, processItem);
                }
                else {
                    throwTypeError("Input is not an iterable");
                }
                pending--;
                if (pending === 0) {
                    resolve(values);
                }
            }
            catch (e) {
                reject(e);
            }
        }, additionalArgs);
    });
}
/*#__NO_SIDE_EFFECTS__*/
function _createRacePromise(newPromise) {
    return createCachedValue(function (input) {
        var additionalArgs = arrSlice(arguments, 1);
        return newPromise(function (resolve, reject) {
            var isDone = false;
            function processItem(item) {
                doAwaitResponse(item, function (value) {
                    if (!isDone) {
                        isDone = true;
                        if (value.rejected) {
                            reject(value.reason);
                        }
                        else {
                            resolve(value.value);
                        }
                    }
                });
            }
            try {
                if (isArray(input)) {
                    arrForEach(input, processItem);
                }
                else if (isIterable(input)) {
                    iterForOf(input, processItem);
                }
                else {
                    throwTypeError("Input is not an iterable");
                }
            }
            catch (e) {
                reject(e);
            }
        }, additionalArgs);
    });
}
/*#__NO_SIDE_EFFECTS__*/
function _createAnyPromise(newPromise) {
    return createCachedValue(function (input) {
        var additionalArgs = arrSlice(arguments, 1);
        return newPromise(function (resolve, reject) {
            var theErros = [];
            var pending = 1;
            var isDone = false;
            function processItem(item, idx) {
                pending++;
                doAwaitResponse(item, function (value) {
                    if (!value.rejected) {
                        isDone = true;
                        resolve(value.value);
                        return;
                    }
                    else {
                        theErros[idx] = value.reason;
                    }
                    if (--pending === 0 && !isDone) {
                        reject(_createAggregationError(theErros));
                    }
                });
            }
            try {
                if (isArray(input)) {
                    arrForEach(input, processItem);
                }
                else if (isIterable(input)) {
                    iterForOf(input, processItem);
                }
                else {
                    throwTypeError("Input is not an iterable");
                }
                pending--;
                if (pending === 0 && !isDone) {
                    reject(_createAggregationError(theErros));
                }
            }
            catch (e) {
                reject(e);
            }
        }, additionalArgs);
    });
}

/*#__NO_SIDE_EFFECTS__*/
function _normalizeTimeoutValue(timeout, defaultTimeout) {
    var result = defaultTimeout;
    if (!isUndefined(timeout)) {
        if (isNumber(timeout)) {
            result = timeout;
        }
        else {
            while (!isUndefined(timeout) && isArray(timeout) && timeout.length > 0) {
                timeout = timeout[0];
                if (isNumber(timeout)) {
                    result = timeout;
                    break;
                }
            }
        }
    }
    return result;
}

function _isFakeTimersEnabled() {
    var setTimeoutFn = setTimeout;
    return !!(setTimeoutFn && setTimeoutFn.clock);
}
function syncItemProcessor(pending) {
    arrForEach(pending, function (fn) {
        try {
            fn();
        }
        catch (e) {
        }
    });
}
function timeoutItemProcessor(timeout) {
    var timeoutValue = _normalizeTimeoutValue(timeout);
    var hasTimeout = isNumber(timeoutValue);
    var callbackTimeout = hasTimeout ? timeoutValue : 0;
    return function (pending) {
        function _processPending() {
            syncItemProcessor(pending);
        }
        if (hasTimeout && callbackTimeout > 0) {
            scheduleTimeout(_processPending, callbackTimeout);
        }
        else if (_isFakeTimersEnabled()) {
            scheduleTimeout(_processPending, 0);
        }
        else {
            scheduleMicrotask(_processPending);
        }
    };
}

var _allAsyncSettledCreator;
var _raceAsyncCreator;
var _anyAsyncCreator;
function createAsyncPromise(executor, timeout) {
    return _createPromise(createAsyncPromise, timeoutItemProcessor(timeout), executor, timeout);
}
var createAsyncAllPromise = (/*#__PURE__*/_createAllPromise(createAsyncPromise));
var createAsyncResolvedPromise = (/*#__PURE__*/_createResolvedPromise(createAsyncPromise));
var createAsyncRejectedPromise = (/*#__PURE__*/_createRejectedPromise(createAsyncPromise));
function createAsyncAllSettledPromise(input, timeout) {
    !_allAsyncSettledCreator && (_allAsyncSettledCreator = _createAllSettledPromise(createAsyncPromise));
    return _allAsyncSettledCreator.v(input, timeout);
}
function createAsyncRacePromise(values, timeout) {
    !_raceAsyncCreator && (_raceAsyncCreator = _createRacePromise(createAsyncPromise));
    return _raceAsyncCreator.v(values, timeout);
}
function createAsyncAnyPromise(values, timeout) {
    !_anyAsyncCreator && (_anyAsyncCreator = _createAnyPromise(createAsyncPromise));
    return _anyAsyncCreator.v(values, timeout);
}

var _promiseCls;
var _allCreator;
var _allNativeSettledCreator;
var _raceNativeCreator;
var _anyNativeCreator;
/*#__NO_SIDE_EFFECTS__*/
function _createNativePromiseHelper(name, func) {
    !_promiseCls && (_promiseCls = createCachedValue((safe(getInst, [STR_PROMISE]).v) || null));
    if (_promiseCls.v && _promiseCls.v[name]) {
        return createCachedValue(function (input, timeout) {
            return createNativePromise(function (resolve, reject) {
                _promiseCls.v[name](input).then(resolve, reject);
            });
        });
    }
    return func();
}
function createNativePromise(executor, timeout) {
    !_promiseCls && (_promiseCls = createCachedValue((safe(getInst, [STR_PROMISE]).v) || null));
    var PrmCls = _promiseCls.v;
    if (!PrmCls) {
        return createAsyncPromise(executor);
    }
    if (!isFunction(executor)) {
        throwTypeError(STR_PROMISE + ": executor is not a function - " + dumpObj(executor));
    }
    var _state = 0 ;
    function _strState() {
        return STRING_STATES[_state];
    }
    var thePromise = new PrmCls(function (resolve, reject) {
        function _resolve(value) {
            _state = 2 ;
            resolve(value);
        }
        function _reject(reason) {
            _state = 3 ;
            reject(reason);
        }
        executor(_resolve, _reject);
    });
    objDefineProp(thePromise, "state", {
        get: _strState
    });
    return thePromise;
}
function createNativeAllPromise(input, timeout) {
    !_allCreator && (_allCreator = _createNativePromiseHelper("all", function () { return createCachedValue(_createAllPromise(createNativePromise)); }));
    return _allCreator.v(input, timeout);
}
var createNativeResolvedPromise = (/*#__PURE__*/_createResolvedPromise(createNativePromise));
var createNativeRejectedPromise = (/*#__PURE__*/_createRejectedPromise(createNativePromise));
function createNativeAllSettledPromise(input, timeout) {
    !_allNativeSettledCreator && (_allNativeSettledCreator = _createNativePromiseHelper("allSettled", function () { return _createAllSettledPromise(createNativePromise); }));
    return _allNativeSettledCreator.v(input, timeout);
}
function createNativeRacePromise(values, timeout) {
    !_raceNativeCreator && (_raceNativeCreator = _createNativePromiseHelper("race", function () { return _createRacePromise(createNativePromise); }));
    return _raceNativeCreator.v(values, timeout);
}
function createNativeAnyPromise(values, timeout) {
    !_anyNativeCreator && (_anyNativeCreator = _createNativePromiseHelper("any", function () { return _createAnyPromise(createNativePromise); }));
    return _anyNativeCreator.v(values, timeout);
}

var _allSyncSettledCreator;
var _raceSyncCreator;
var _anySyncCreator;
function createSyncPromise(executor) {
    return _createPromise(createSyncPromise, syncItemProcessor, executor);
}
var createSyncAllPromise = (/*#__PURE__*/_createAllPromise(createSyncPromise));
var createSyncResolvedPromise = (/*#__PURE__*/_createResolvedPromise(createSyncPromise));
var createSyncRejectedPromise = (/*#__PURE__*/_createRejectedPromise(createSyncPromise));
function createSyncAllSettledPromise(input, timeout) {
    !_allSyncSettledCreator && (_allSyncSettledCreator = _createAllSettledPromise(createSyncPromise));
    return _allSyncSettledCreator.v(input, timeout);
}
function createSyncRacePromise(values, timeout) {
    !_raceSyncCreator && (_raceSyncCreator = _createRacePromise(createSyncPromise));
    return _raceSyncCreator.v(values, timeout);
}
function createSyncAnyPromise(values, timeout) {
    !_anySyncCreator && (_anySyncCreator = _createAnyPromise(createSyncPromise));
    return _anySyncCreator.v(values, timeout);
}

var _defaultIdleTimeout;
var _allIdleSettledCreator;
var _raceIdleCreator;
var _anyIdleCreator;
function setDefaultIdlePromiseTimeout(idleDeadline) {
    _defaultIdleTimeout = idleDeadline;
}
var setDefaultIdleTimeout = (/*#__PURE__*/_pureAssign(setDefaultIdlePromiseTimeout));
function createIdlePromise(executor, timeout) {
    var options;
    var theTimeout = _normalizeTimeoutValue(timeout, _defaultIdleTimeout);
    if (isNumber(theTimeout) && theTimeout >= 0) {
        options = {
            timeout: theTimeout
        };
    }
    var processor = function (pending) {
        scheduleIdleCallback(function (deadline) {
            syncItemProcessor(pending);
        }, options);
    };
    return _createPromise(createIdlePromise, processor, executor, theTimeout);
}
var createIdleAllPromise = (/*#__PURE__*/_createAllPromise(createIdlePromise));
var createIdleResolvedPromise = (/*#__PURE__*/_createResolvedPromise(createIdlePromise));
var createIdleRejectedPromise = (/*#__PURE__*/_createRejectedPromise(createIdlePromise));
function createIdleAllSettledPromise(input, timeout) {
    !_allIdleSettledCreator && (_allIdleSettledCreator = _createAllSettledPromise(createIdlePromise));
    return _allIdleSettledCreator.v(input, timeout);
}
function createIdleRacePromise(values, timeout) {
    !_raceIdleCreator && (_raceIdleCreator = _createRacePromise(createIdlePromise));
    return _raceIdleCreator.v(values, timeout);
}
function createIdleAnyPromise(values, timeout) {
    !_anyIdleCreator && (_anyIdleCreator = _createAnyPromise(createIdlePromise));
    return _anyIdleCreator.v(values, timeout);
}

var _promiseCreator;
var _allSettledCreator;
var _raceCreator;
var _anyCreator;
function setCreatePromiseImpl(creator) {
    _promiseCreator = creator ? createCachedValue(creator) : null;
}
function createPromise(executor, timeout) {
    !_promiseCreator && (_promiseCreator = createCachedValue(createNativePromise));
    return _promiseCreator.v.call(this, executor, timeout);
}
var createAllPromise = (/*#__PURE__*/_createAllPromise(createPromise));
var createResolvedPromise = (/*#__PURE__*/_createResolvedPromise(createPromise));
var createRejectedPromise = (/*#__PURE__*/_createRejectedPromise(createPromise));
function createAllSettledPromise(input, timeout) {
    !_allSettledCreator && (_allSettledCreator = _createAllSettledPromise(createPromise));
    return _allSettledCreator.v(input, timeout);
}
function createRacePromise(values, timeout) {
    !_raceCreator && (_raceCreator = _createRacePromise(createPromise));
    return _raceCreator.v(values, timeout);
}
function createAnyPromise(values, timeout) {
    !_anyCreator && (_anyCreator = _createAnyPromise(createPromise));
    return _anyCreator.v(values, timeout);
}

function createTimeoutPromise(timeout, resolveReject, message) {
    return createPromise(function (resolve, reject) {
        scheduleTimeout(function () {
            (resolveReject ? resolve : reject)(!isUndefined(message) ? message : "Timeout of " + timeout + "ms exceeded");
        }, timeout);
    });
}

function _doneChk(isDone, state, value, thisArg) {
    var result = isDone;
    state.res = value;
    if (!result) {
        if (state.isDone && isFunction(state.isDone)) {
            return doAwait(state.isDone.call(thisArg, state), function (done) {
                state.iter++;
                return !!done;
            });
        }
        else {
            result = !!state.isDone;
        }
    }
    state.iter++;
    return result;
}
function doWhileAsync(callbackFn, isDoneFn, thisArg) {
    var promise;
    var resolve;
    var reject = function (reason) {
        isDone = true;
        throw reason;
    };
    var isDone = false;
    var state = {
        st: utcNow(),
        iter: 0,
        isDone: isDoneFn || false
    };
    if (callbackFn) {
        var _createPromise_1 = function () {
            return createPromise(function (res, rej) {
                resolve = res;
                reject = rej;
            });
        };
        var _handleAsyncDone_1 = function (done) {
            isDone = !!done;
            if (!isDone) {
                _processNext_1();
            }
            else {
                resolve(state.res);
            }
        };
        var _processNext_1 = function () {
            while (!isDone) {
                try {
                    var cbResult = callbackFn.call(thisArg, state);
                    if (isPromiseLike(cbResult)) {
                        promise = promise || _createPromise_1();
                        doAwait(cbResult, function (res) {
                            try {
                                doAwait(_doneChk(isDone, state, res, thisArg), _handleAsyncDone_1, reject);
                            }
                            catch (e) {
                                reject(e);
                            }
                        }, reject);
                        return promise;
                    }
                    else {
                        var dnRes = _doneChk(isDone, state, cbResult, thisArg);
                        if (isPromiseLike(dnRes)) {
                            promise = promise || _createPromise_1();
                            doAwait(dnRes, _handleAsyncDone_1, reject);
                            return promise;
                        }
                        else {
                            isDone = !!dnRes;
                        }
                    }
                }
                catch (e) {
                    reject(e);
                    return promise;
                }
            }
            if (isDone && resolve) {
                resolve(state.res);
            }
            return promise || state.res;
        };
        return _processNext_1();
    }
}

function arrForEachAsync(theArray, callbackFn, thisArg) {
    if (theArray) {
        var len_1 = getLength(theArray);
        if (len_1) {
            var isDone = function (state) {
                if (state.iter >= len_1 || state.res === -1) {
                    return true;
                }
            };
            return doWhileAsync(function (state) {
                var idx = state.iter;
                if (idx in theArray) {
                    return callbackFn.call(thisArg || theArray, theArray[idx], idx, theArray);
                }
            }, isDone);
        }
    }
}

var _iterSymbol;
var _iterAsyncSymbol;
function iterForOfAsync(iter, callbackFn, thisArg) {
    var err;
    var iterResult;
    var theIter = iter;
    function onFailed(failed) {
        err = { e: failed };
        if (theIter.throw) {
            iterResult = null;
            theIter.throw(err);
        }
        throw failed;
    }
    function onFinally() {
        try {
            if (iterResult && !iterResult[DONE]) {
                theIter[RETURN] && theIter[RETURN](iterResult);
            }
        }
        finally {
            if (err) {
                throw err.e;
            }
        }
    }
    if (iter) {
        if (!isIterator(iter)) {
            !_iterAsyncSymbol && (_iterAsyncSymbol = createCachedValue(getKnownSymbol(0 )));
            theIter = iter[_iterAsyncSymbol.v] ? iter[_iterAsyncSymbol.v]() : null;
            if (!theIter) {
                !_iterSymbol && (_iterSymbol = createCachedValue(getKnownSymbol(3 )));
                theIter = iter[_iterSymbol.v] ? iter[_iterSymbol.v]() : null;
            }
        }
        if (theIter && isIterator(theIter)) {
            var result = void 0;
            try {
                result = doWhileAsync(function (state) {
                    return doAwait(theIter.next(), function (res) {
                        iterResult = res;
                        if (!res[DONE]) {
                            return fnCall(callbackFn, thisArg || theIter, iterResult[VALUE], state.iter, theIter);
                        }
                    }, function (reason) {
                        state.isDone = true;
                        onFailed(reason);
                    });
                }, function (state) {
                    if (!iterResult || iterResult[DONE] || state.res === -1) {
                        onFinally();
                        return true;
                    }
                }, thisArg || theIter);
                if (isPromiseLike(result)) {
                    result = doFinally(result.catch(onFailed), onFinally);
                }
                return result;
            }
            catch (failed) {
                onFailed(failed);
            }
            finally {
                if (result && !isPromiseLike(result)) {
                    onFinally();
                }
            }
        }
    }
}

var REJECT = "reject";
var REJECTED_ERROR = "Rejected";
var _schedulerId = 0;
var _debugName;
var _debugIntState;
var _customErrors = {};
function _rejectDone() {
}
function _createError(type, evt, message) {
    !_customErrors[type] && (_customErrors[type] = createCustomError(type));
    var now = utcNow();
    return new (_customErrors[type])("Task [".concat(evt.id, "] ").concat(message || "", "- ").concat((evt.st ? "Running" : "Waiting"), ": ").concat(_calcTime(now, evt.st || evt.cr)));
}
function _calcTime(now, start) {
    return ((now - start) || "0") + " ms";
}
function _abortStaleTasks(taskQueue, staleTimeoutPeriod) {
    var now = utcNow();
    var expired = now - staleTimeoutPeriod;
    arrForEach(taskQueue, function (evt) {
        if (evt && !evt.rj && (evt.st && evt.st < expired) || (!evt.st && evt.cr && evt.cr < expired)) {
            evt && evt[REJECT](evt.rj || _createError("Aborted", evt, "Stale "));
        }
    });
}
function _removeTask(queue, taskDetail) {
    var idx = arrIndexOf(queue, taskDetail);
    if (idx !== -1) {
        queue.splice(idx, 1);
    }
}
function _addDebugState(theScheduler, nameFn, stateFn) {
    _debugName = _debugName || { toString: function () { return "[[SchedulerName]]"; } };
    _debugIntState = _debugIntState || { toString: function () { return "[[SchedulerState]]"; } };
    objDefineProp(theScheduler, _debugName, { get: nameFn });
    objDefineProp(theScheduler, _debugIntState, { get: stateFn });
}
function createTaskScheduler(newPromise, name) {
    var _theTask;
    var _running = [];
    var _waiting = [];
    var _staleTimeoutPeriod = 600000;
    var _staleTimeoutCheckPeriod = _staleTimeoutPeriod / 10;
    var _taskCount = 0;
    var _schedulerName = (name ? (name + ".") : "") + _schedulerId++;
    var _blockedTimer;
    newPromise = newPromise || createPromise;
    var _startBlockedTimer = function () {
        var hasTasks = (getLength(_running) + getLength(_waiting)) > 0;
        if (_staleTimeoutPeriod > 0) {
            if (!_blockedTimer) {
                _blockedTimer = scheduleTimeout(function () {
                    _abortStaleTasks(_running, _staleTimeoutPeriod);
                    _abortStaleTasks(_waiting, _staleTimeoutPeriod);
                    _blockedTimer && (_blockedTimer.enabled = ((getLength(_running) + getLength(_waiting)) > 0));
                }, _staleTimeoutCheckPeriod);
                _blockedTimer.unref();
            }
            _blockedTimer && (_blockedTimer.enabled = hasTasks);
        }
    };
    var _queueTask = function (startAction, taskName, timeout) {
        var _a;
        var taskId = _schedulerName + "." + _taskCount++;
        if (taskName) {
            taskId += "-(" + taskName + ")";
        }
        var newTask = (_a = {
                id: taskId,
                cr: utcNow(),
                to: timeout
            },
            _a[REJECT] = function (reason) {
                newTask.rj = reason || _createError(REJECTED_ERROR, newTask);
                newTask[REJECT] = _rejectDone;
            },
            _a);
        if (!_theTask) {
            newTask.p = newPromise(_runTask(newTask, startAction));
        }
        else {
            newTask.p = _waitForPreviousTask(newTask, _theTask, startAction);
        }
        _theTask = newTask;
        return newTask.p;
    };
    var _runTask = function (taskDetail, startAction) {
        taskDetail.st = utcNow();
        _running.push(taskDetail);
        _startBlockedTimer();
        return function (onTaskResolve, onTaskReject) {
            var _promiseReject = function (reason) {
                taskDetail.rj = taskDetail.rj || reason || _createError(REJECTED_ERROR, taskDetail);
                taskDetail[REJECT] = _rejectDone;
                _doCleanup(taskDetail);
                onTaskResolve = null;
                onTaskReject && onTaskReject(reason);
                onTaskReject = null;
            };
            var taskId = taskDetail.id;
            if (taskDetail.rj) {
                _promiseReject(taskDetail.rj);
            }
            else {
                taskDetail[REJECT] = _promiseReject;
                try {
                    var startResult = startAction(taskId);
                    if (taskDetail.to && isPromiseLike(startResult)) {
                        taskDetail.t = scheduleTimeout(function () {
                            _promiseReject(_createError("Timeout", taskDetail));
                        }, taskDetail.to);
                    }
                    doAwait(startResult, function (theResult) {
                        _doCleanup(taskDetail);
                        try {
                            onTaskResolve && onTaskResolve(theResult);
                        }
                        catch (e) {
                            onTaskReject && onTaskReject(e);
                        }
                        onTaskReject = null;
                        onTaskResolve = null;
                    }, _promiseReject);
                }
                catch (e) {
                    _promiseReject(e);
                }
            }
        };
    };
    var _waitForPreviousTask = function (taskDetail, prevTask, startAction) {
        _waiting.push(taskDetail);
        _startBlockedTimer();
        return newPromise(function (onWaitResolve, onWaitReject) {
            doAwaitResponse(prevTask.p, function () {
                _removeTask(_waiting, taskDetail);
                _runTask(taskDetail, startAction)(onWaitResolve, onWaitReject);
            });
        });
    };
    var _doCleanup = function (taskDetail) {
        _removeTask(_running, taskDetail);
        _removeTask(_waiting, taskDetail);
        taskDetail.t && taskDetail.t.cancel();
        taskDetail.t = null;
        if (_theTask && _theTask === taskDetail) {
            _theTask = null;
            if (getLength(_running) + getLength(_waiting) === 0) {
                _blockedTimer && _blockedTimer.cancel();
                _blockedTimer = null;
            }
        }
    };
    var theScheduler = {
        idle: true,
        queue: _queueTask,
        setStaleTimeout: function (staleTimeout, staleCheckPeriod) {
            _blockedTimer && _blockedTimer.cancel();
            _blockedTimer = null;
            _staleTimeoutPeriod = staleTimeout;
            _staleTimeoutCheckPeriod = staleCheckPeriod || staleTimeout / 10;
            _startBlockedTimer();
        }
    };
    objDefine(theScheduler, "idle", {
        g: function () {
            return getLength(_running) + getLength(_waiting) === 0;
        }
    });
    _addDebugState(theScheduler, function () { return _schedulerName; }, function () {
        return {
            l: _theTask,
            r: _running,
            w: _waiting
        };
    });
    return theScheduler;
}

var toStringTagSymbol = getKnownSymbol(11 );
var PolyPromise = (/*#__PURE__*/(function () {
    function PolyPromiseImpl(executor) {
        this._$ = createAsyncPromise(executor);
        if (toStringTagSymbol) {
            this[toStringTagSymbol] = "Promise";
        }
        objDefineProp(this, "state", {
            get: function () {
                return this._$.state;
            }
        });
    }
    PolyPromiseImpl.all = createAsyncAllPromise;
    PolyPromiseImpl.race = createAsyncRacePromise;
    PolyPromiseImpl.any = createAsyncAnyPromise;
    PolyPromiseImpl.reject = createAsyncRejectedPromise;
    PolyPromiseImpl.resolve = createAsyncResolvedPromise;
    PolyPromiseImpl.allSettled = createAsyncAllSettledPromise;
    var theProto = PolyPromiseImpl.prototype;
    theProto.then = function (onResolved, onRejected) {
        return this._$.then(onResolved, onRejected);
    };
    theProto.catch = function (onRejected) {
        return this._$.catch(onRejected);
    };
    theProto.finally = function (onfinally) {
        return this._$.finally(onfinally);
    };
    return PolyPromiseImpl;
}()));

export { PolyPromise, arrForEachAsync, createAllPromise, createAllSettledPromise, createAnyPromise, createAsyncAllPromise, createAsyncAllSettledPromise, createAsyncAnyPromise, createAsyncPromise, createAsyncRacePromise, createAsyncRejectedPromise, createAsyncResolvedPromise, createIdleAllPromise, createIdleAllSettledPromise, createIdleAnyPromise, createIdlePromise, createIdleRacePromise, createIdleRejectedPromise, createIdleResolvedPromise, createNativeAllPromise, createNativeAllSettledPromise, createNativeAnyPromise, createNativePromise, createNativeRacePromise, createNativeRejectedPromise, createNativeResolvedPromise, createPromise, createRacePromise, createRejectedPromise, createResolvedPromise, createSyncAllPromise, createSyncAllSettledPromise, createSyncAnyPromise, createSyncPromise, createSyncRacePromise, createSyncRejectedPromise, createSyncResolvedPromise, createTaskScheduler, createTimeoutPromise, doAwait, doAwaitResponse, doFinally, doWhileAsync, iterForOfAsync, setCreatePromiseImpl, setDefaultIdlePromiseTimeout, setDefaultIdleTimeout, setPromiseDebugState };
//# sourceMappingURL=ts-async.js.map
