"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
0 && (module.exports = {
    accumulateRootVaryParam: null,
    accumulateVaryParam: null,
    createResponseVaryParamsAccumulator: null,
    createVaryParamsAccumulator: null,
    createVaryingParams: null,
    createVaryingSearchParams: null,
    emptyVaryParamsAccumulator: null,
    finishAccumulatingVaryParams: null,
    getMetadataVaryParamsAccumulator: null,
    getMetadataVaryParamsThenable: null,
    getRootParamsVaryParamsAccumulator: null,
    getVaryParamsThenable: null,
    getViewportVaryParamsAccumulator: null
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: all[name]
    });
}
_export(exports, {
    accumulateRootVaryParam: function() {
        return accumulateRootVaryParam;
    },
    accumulateVaryParam: function() {
        return accumulateVaryParam;
    },
    createResponseVaryParamsAccumulator: function() {
        return createResponseVaryParamsAccumulator;
    },
    createVaryParamsAccumulator: function() {
        return createVaryParamsAccumulator;
    },
    createVaryingParams: function() {
        return createVaryingParams;
    },
    createVaryingSearchParams: function() {
        return createVaryingSearchParams;
    },
    emptyVaryParamsAccumulator: function() {
        return emptyVaryParamsAccumulator;
    },
    finishAccumulatingVaryParams: function() {
        return finishAccumulatingVaryParams;
    },
    getMetadataVaryParamsAccumulator: function() {
        return getMetadataVaryParamsAccumulator;
    },
    getMetadataVaryParamsThenable: function() {
        return getMetadataVaryParamsThenable;
    },
    getRootParamsVaryParamsAccumulator: function() {
        return getRootParamsVaryParamsAccumulator;
    },
    getVaryParamsThenable: function() {
        return getVaryParamsThenable;
    },
    getViewportVaryParamsAccumulator: function() {
        return getViewportVaryParamsAccumulator;
    }
});
const _workunitasyncstorageexternal = require("./work-unit-async-storage.external");
function createSegmentVaryParamsAccumulator() {
    const accumulator = {
        varyParams: new Set(),
        status: 'pending',
        value: new Set(),
        then (onfulfilled) {
            if (onfulfilled) {
                if (accumulator.status === 'pending') {
                    accumulator.resolvers.push(onfulfilled);
                } else {
                    onfulfilled(accumulator.value);
                }
            }
        },
        resolvers: []
    };
    return accumulator;
}
/**
 * A singleton accumulator that's already resolved to an empty Set. Use this for
 * segments where we know upfront that no params will be accessed, such as
 * client components or segments without user code.
 *
 * Benefits:
 * - No need to accumulate or resolve later
 * - Resilient: resolves correctly even if other tracking fails
 * - Memory efficient: reuses the same object
 */ const emptySet = new Set();
const emptyVaryParamsAccumulator = {
    varyParams: emptySet,
    status: 'fulfilled',
    value: emptySet,
    then (onfulfilled) {
        if (onfulfilled) {
            onfulfilled(emptySet);
        }
    },
    resolvers: []
};
function createResponseVaryParamsAccumulator() {
    // Create the head and rootParams accumulators as top-level fields.
    // Segment accumulators are added to the segments set as they are created.
    const head = createSegmentVaryParamsAccumulator();
    const rootParams = createSegmentVaryParamsAccumulator();
    const segments = new Set();
    return {
        head,
        rootParams,
        segments
    };
}
function createVaryParamsAccumulator() {
    const workUnitStore = _workunitasyncstorageexternal.workUnitAsyncStorage.getStore();
    if (workUnitStore) {
        switch(workUnitStore.type){
            case 'prerender':
            case 'prerender-runtime':
                {
                    const responseAccumulator = workUnitStore.varyParamsAccumulator;
                    if (responseAccumulator !== null) {
                        const accumulator = createSegmentVaryParamsAccumulator();
                        responseAccumulator.segments.add(accumulator);
                        return accumulator;
                    }
                    return null;
                }
            case 'prerender-ppr':
            case 'prerender-legacy':
            case 'request':
            case 'cache':
            case 'private-cache':
            case 'prerender-client':
            case 'validation-client':
            case 'unstable-cache':
            case 'generate-static-params':
                break;
            default:
                workUnitStore;
        }
    }
    return null;
}
function getMetadataVaryParamsAccumulator() {
    const workUnitStore = _workunitasyncstorageexternal.workUnitAsyncStorage.getStore();
    if (workUnitStore) {
        switch(workUnitStore.type){
            case 'prerender':
            case 'prerender-runtime':
                {
                    const responseAccumulator = workUnitStore.varyParamsAccumulator;
                    if (responseAccumulator !== null) {
                        return responseAccumulator.head;
                    }
                    return null;
                }
            case 'prerender-ppr':
            case 'prerender-legacy':
            case 'request':
            case 'cache':
            case 'private-cache':
            case 'prerender-client':
            case 'validation-client':
            case 'unstable-cache':
            case 'generate-static-params':
                return null;
            default:
                workUnitStore;
        }
    }
    return null;
}
function getVaryParamsThenable(accumulator) {
    return accumulator;
}
function getMetadataVaryParamsThenable() {
    const accumulator = getMetadataVaryParamsAccumulator();
    if (accumulator !== null) {
        return getVaryParamsThenable(accumulator);
    }
    return null;
}
const getViewportVaryParamsAccumulator = getMetadataVaryParamsAccumulator;
function getRootParamsVaryParamsAccumulator() {
    const workUnitStore = _workunitasyncstorageexternal.workUnitAsyncStorage.getStore();
    if (workUnitStore) {
        switch(workUnitStore.type){
            case 'prerender':
            case 'prerender-runtime':
                {
                    const responseAccumulator = workUnitStore.varyParamsAccumulator;
                    if (responseAccumulator !== null) {
                        return responseAccumulator.rootParams;
                    }
                    return null;
                }
            case 'prerender-ppr':
            case 'prerender-legacy':
            case 'request':
            case 'cache':
            case 'private-cache':
            case 'prerender-client':
            case 'validation-client':
            case 'unstable-cache':
            case 'generate-static-params':
                return null;
            default:
                workUnitStore;
        }
    }
    return null;
}
function accumulateVaryParam(accumulator, paramName) {
    accumulator.varyParams.add(paramName);
}
function accumulateRootVaryParam(paramName) {
    const rootParamsAccumulator = getRootParamsVaryParamsAccumulator();
    if (rootParamsAccumulator !== null) {
        accumulateVaryParam(rootParamsAccumulator, paramName);
    }
}
function createVaryingParams(accumulator, originalParamsObject, optionalCatchAllParamName) {
    if (optionalCatchAllParamName !== null) {
        // When there's an optional catch-all param with no value (e.g.,
        // [[...slug]] at /), the param doesn't exist as a property on the params
        // object. Use a Proxy to track all param access — both existing params
        // and the missing optional param — including enumeration patterns like
        // Object.keys(), spread, for...in, and `in` checks.
        return new Proxy(originalParamsObject, {
            get (target, prop, receiver) {
                if (typeof prop === 'string') {
                    if (prop === optionalCatchAllParamName || Object.prototype.hasOwnProperty.call(target, prop)) {
                        accumulateVaryParam(accumulator, prop);
                    }
                }
                return Reflect.get(target, prop, receiver);
            },
            has (target, prop) {
                if (prop === optionalCatchAllParamName) {
                    accumulateVaryParam(accumulator, optionalCatchAllParamName);
                }
                return Reflect.has(target, prop);
            },
            ownKeys (target) {
                // Enumerating the params object means the user's code may depend on
                // which params are present, so conservatively track the optional
                // param as accessed.
                accumulateVaryParam(accumulator, optionalCatchAllParamName);
                return Reflect.ownKeys(target);
            }
        });
    }
    // When there's no optional catch-all, all params exist as properties on the
    // object, so we can use defineProperty getters instead of a Proxy. This is
    // faster because the engine can optimize property access on regular objects
    // more aggressively than Proxy trap calls.
    const underlyingParamsWithVarying = {};
    for(const paramName in originalParamsObject){
        Object.defineProperty(underlyingParamsWithVarying, paramName, {
            get () {
                accumulateVaryParam(accumulator, paramName);
                return originalParamsObject[paramName];
            },
            enumerable: true
        });
    }
    return underlyingParamsWithVarying;
}
function createVaryingSearchParams(accumulator, originalSearchParamsObject) {
    const underlyingSearchParamsWithVarying = {};
    for(const searchParamName in originalSearchParamsObject){
        Object.defineProperty(underlyingSearchParamsWithVarying, searchParamName, {
            get () {
                // TODO: Unlike path params, we don't vary track each search param
                // individually. The entire search string is treated as a single param.
                // This may change in the future.
                accumulateVaryParam(accumulator, '?');
                return originalSearchParamsObject[searchParamName];
            },
            enumerable: true
        });
    }
    return underlyingSearchParamsWithVarying;
}
async function finishAccumulatingVaryParams(responseAccumulator) {
    const rootVaryParams = responseAccumulator.rootParams.varyParams;
    // Resolve head
    finishSegmentAccumulator(responseAccumulator.head, rootVaryParams);
    // Resolve each segment
    for (const segmentAccumulator of responseAccumulator.segments){
        finishSegmentAccumulator(segmentAccumulator, rootVaryParams);
    }
    // Now that the thenables are resolved, Flight should be able to flush the
    // vary params into the response stream. This work gets scheduled internally
    // by Flight using a microtask as soon as we notify the thenable listeners.
    //
    // We need to ensure that Flight's pending queues are emptied before this
    // function returns; the caller will abort the prerender immediately after.
    // We can't use a macrotask, because that would allow dynamic IO to sneak
    // into the response. So we use microtasks instead.
    //
    // The exact number of awaits here isn't important (indeed, one seems to be
    // sufficient, at the time of writing), as long as we wait enough ticks for
    // Flight to finish writing the response.
    //
    // Anything that remains in Flight's internal queue after these awaits must
    // be actual dynamic IO, not caused by pending vary params tasks. In other
    // words, failing to do this would cause us to treat a fully static prerender
    // as if it were partially dynamic.
    await Promise.resolve();
    await Promise.resolve();
    await Promise.resolve();
}
function finishSegmentAccumulator(accumulator, rootVaryParams) {
    if (accumulator.status !== 'pending') {
        return;
    }
    const merged = new Set(accumulator.varyParams);
    for (const param of rootVaryParams){
        merged.add(param);
    }
    accumulator.value = merged;
    accumulator.status = 'fulfilled';
    for (const resolver of accumulator.resolvers){
        resolver(merged);
    }
    accumulator.resolvers = [];
}

//# sourceMappingURL=vary-params.js.map