"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "AfterContext", {
    enumerable: true,
    get: function() {
        return AfterContext;
    }
});
const _pqueue = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/p-queue"));
const _requestasyncstorageexternal = require("../../client/components/request-async-storage.external");
const _cookies = require("../web/spec-extension/cookies");
const _invarianterror = require("../../shared/lib/invariant-error");
const _isthenable = require("../../shared/lib/is-thenable");
const _workasyncstorageexternal = require("../../client/components/work-async-storage.external");
const _revalidationutils = require("./revalidation-utils");
function _interop_require_default(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
class AfterContext {
    constructor({ waitUntil, onClose }){
        this.waitUntil = waitUntil;
        this.onClose = onClose;
        this.callbackQueue = new _pqueue.default();
        this.callbackQueue.pause();
    }
    run(requestStore, callback) {
        this.requestStore = requestStore;
        return callback();
    }
    after(task) {
        if ((0, _isthenable.isThenable)(task)) {
            task.catch(()=>{}) // avoid unhandled rejection crashes
            ;
            if (!this.waitUntil) {
                errorWaitUntilNotAvailable();
            }
            this.waitUntil(task);
        } else if (typeof task === 'function') {
            // TODO(after): implement tracing
            this.addCallback(task);
        } else {
            throw new Error('`unstable_after()`: Argument must be a promise or a function');
        }
    }
    addCallback(callback) {
        // if something is wrong, throw synchronously, bubbling up to the `unstable_after` callsite.
        if (!this.waitUntil) {
            errorWaitUntilNotAvailable();
        }
        if (!this.requestStore) {
            throw new _invarianterror.InvariantError('unstable_after: Expected `AfterContext.requestStore` to be initialized');
        }
        if (!this.onClose) {
            throw new _invarianterror.InvariantError('unstable_after: Missing `onClose` implementation');
        }
        // this should only happen once.
        if (!this.runCallbacksOnClosePromise) {
            // NOTE: We're creating a promise here, which means that
            // we will propagate any AsyncLocalStorage contexts we're currently in
            // to the callbacks that'll execute later.
            // This includes e.g. `requestAsyncStorage` and React's `requestStorage` (which backs `React.cache()`).
            this.runCallbacksOnClosePromise = this.runCallbacksOnClose();
            this.waitUntil(this.runCallbacksOnClosePromise);
        }
        const wrappedCallback = async ()=>{
            try {
                await callback();
            } catch (err) {
                // TODO(after): this is fine for now, but will need better intergration with our error reporting.
                console.error('An error occurred in a function passed to `unstable_after()`:', err);
            }
        };
        this.callbackQueue.add(wrappedCallback);
    }
    async runCallbacksOnClose() {
        await new Promise((resolve)=>this.onClose(resolve));
        return this.runCallbacks(this.requestStore);
    }
    async runCallbacks(requestStore) {
        if (this.callbackQueue.size === 0) return;
        const readonlyRequestStore = wrapRequestStoreForAfterCallbacks(requestStore);
        const workStore = _workasyncstorageexternal.workAsyncStorage.getStore();
        return (0, _revalidationutils.withExecuteRevalidates)(workStore, ()=>_requestasyncstorageexternal.requestAsyncStorage.run(readonlyRequestStore, async ()=>{
                this.callbackQueue.start();
                await this.callbackQueue.onIdle();
            }));
    }
}
function errorWaitUntilNotAvailable() {
    throw new Error('`unstable_after()` will not work correctly, because `waitUntil` is not available in the current environment.');
}
/** Disable mutations of `requestStore` within `after()` and disallow nested after calls.  */ function wrapRequestStoreForAfterCallbacks(requestStore) {
    return {
        url: requestStore.url,
        get headers () {
            return requestStore.headers;
        },
        get cookies () {
            return requestStore.cookies;
        },
        get draftMode () {
            return requestStore.draftMode;
        },
        // TODO(after): calling a `cookies.set()` in an after() that's in an action doesn't currently error.
        mutableCookies: new _cookies.ResponseCookies(new Headers()),
        afterContext: requestStore.afterContext,
        isHmrRefresh: requestStore.isHmrRefresh,
        serverComponentsHmrCache: requestStore.serverComponentsHmrCache
    };
}

//# sourceMappingURL=after-context.js.map