"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Deferred = void 0;
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
 */
var State;
(function (State) {
    State[State["pending"] = 0] = "pending";
    State[State["fulfilled"] = 1] = "fulfilled";
    State[State["rejected"] = 2] = "rejected";
})(State || (State = {}));
/**
 * Enables a Promise to be resolved or rejected at a future time, outside of
 * the context of the Promise construction. Also exposes the `pending`,
 * `fulfilled`, or `rejected` state of the promise.
 */
class Deferred {
    [Symbol.toStringTag] = "Deferred";
    promise;
    #resolve;
    #reject;
    #state = State.pending;
    constructor() {
        this.promise = new Promise((resolve, reject) => {
            this.#resolve = resolve;
            this.#reject = reject;
        });
    }
    /**
     * @return `true` iff neither `resolve` nor `rejected` have been invoked
     */
    get pending() {
        return this.#state === State.pending;
    }
    /**
     * @return `true` iff `resolve` has been invoked
     */
    get fulfilled() {
        return this.#state === State.fulfilled;
    }
    /**
     * @return `true` iff `rejected` has been invoked
     */
    get rejected() {
        return this.#state === State.rejected;
    }
    /**
     * @return `true` iff `resolve` or `rejected` have been invoked
     */
    get settled() {
        return this.#state !== State.pending;
    }
    then(onfulfilled, onrejected) {
        return this.promise.then(onfulfilled, onrejected);
    }
    catch(onrejected) {
        return this.promise.catch(onrejected);
    }
    resolve(value) {
        if (this.settled) {
            return false;
        }
        else {
            this.#state = State.fulfilled;
            this.#resolve(value);
            return true;
        }
    }
    reject(reason) {
        if (this.settled) {
            return false;
        }
        this.#state = State.rejected;
        this.#reject(reason);
        return true;
    }
    observe(p) {
        void observe(this, p);
        return this;
    }
    observeQuietly(p) {
        void observeQuietly(this, p);
        return this;
    }
}
exports.Deferred = Deferred;
async function observe(d, p) {
    try {
        d.resolve(await p);
    }
    catch (err) {
        d.reject(err instanceof Error ? err : new Error(String(err)));
    }
}
async function observeQuietly(d, p) {
    try {
        d.resolve(await p);
    }
    catch {
        d.resolve(undefined);
    }
}
//# sourceMappingURL=Deferred.js.map