"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
0 && (module.exports = {
    ValidationPrefetchKind: null,
    collectStagedSegmentData: null,
    createCombinedPayloadAtDepth: null,
    createCombinedPayloadStream: null,
    discoverValidationDepths: null
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: all[name]
    });
}
_export(exports, {
    ValidationPrefetchKind: function() {
        return ValidationPrefetchKind;
    },
    collectStagedSegmentData: function() {
        return collectStagedSegmentData;
    },
    createCombinedPayloadAtDepth: function() {
        return createCombinedPayloadAtDepth;
    },
    createCombinedPayloadStream: function() {
        return createCombinedPayloadStream;
    },
    discoverValidationDepths: function() {
        return discoverValidationDepths;
    }
});
const _jsxruntime = require("react/jsx-runtime");
const _invarianterror = require("../../../shared/lib/invariant-error");
const _stagedrendering = require("../staged-rendering");
const _manifestssingleton = require("../manifests-singleton");
const _apprenderrenderutils = require("../app-render-render-utils");
const _workasyncstorageexternal = require("../work-async-storage.external");
const _prospectiverenderutils = require("../prospective-render-utils");
const _createerrorhandler = require("../create-error-handler");
const _boundary = require("../../../client/components/instant-validation/boundary");
const _boundaryconstants = require("./boundary-constants");
const _appdirmodule = require("../../lib/app-dir-module");
const _parseloadertree = require("../../../shared/lib/router/utils/parse-loader-tree");
const _nodestream = require("node:stream");
const _streamutils = require("./stream-utils");
const _client = require("react-server-dom-webpack/client");
const _segment = require("../../../shared/lib/segment");
const _instantconfig = require("./instant-config");
const filterStackFrame = process.env.NODE_ENV !== 'production' ? require('../../lib/source-maps').filterStackFrameDEV : undefined;
const findSourceMapURL = process.env.NODE_ENV !== 'production' ? require('../../lib/source-maps').findSourceMapURLDEV : undefined;
const debug = process.env.NEXT_PRIVATE_DEBUG_VALIDATION === '1' ? console.log : undefined;
function traverseRootSeedDataSegments(initialRSCPayload, processSegment) {
    const { flightRouterState, seedData } = getRootDataFromPayload(initialRSCPayload);
    const [rootSegment] = flightRouterState;
    const rootPath = stringifySegment(rootSegment);
    return traverseCacheNodeSegments(rootPath, flightRouterState, seedData, processSegment);
}
function traverseCacheNodeSegments(path, route, seedData, processSegment) {
    processSegment(path, seedData);
    const [_segment, childRoutes] = route;
    const [_node, parallelRoutesData, _loading, _isPartial] = seedData;
    for(const parallelRouteKey in childRoutes){
        const childSeedData = parallelRoutesData[parallelRouteKey];
        if (!childSeedData) {
            throw Object.defineProperty(new _invarianterror.InvariantError(`Got unexpected empty seed data during instant validation`), "__NEXT_ERROR_CODE", {
                value: "E992",
                enumerable: false,
                configurable: true
            });
        }
        const childRoute = childRoutes[parallelRouteKey];
        // NOTE: if this is a __PAGE__ segment, it might have search params appended.
        // Whoever reads from the cache needs to append them as well.
        const [childSegment] = childRoute;
        const childPath = createChildSegmentPath(path, parallelRouteKey, childSegment);
        traverseCacheNodeSegments(childPath, childRoute, childSeedData, processSegment);
    }
}
function createChildSegmentPath(parentPath, parallelRouteKey, segment) {
    const parallelRoutePrefix = parallelRouteKey === 'children' ? '' : `@${encodeURIComponent(parallelRouteKey)}/`;
    return `${parentPath}/${parallelRoutePrefix}${stringifySegment(segment)}`;
}
function stringifySegment(segment) {
    return typeof segment === 'string' ? encodeURIComponent(segment) : encodeURIComponent(segment[0]) + '|' + segment[1] + '|' + segment[2];
}
async function collectStagedSegmentData(prefetchKind, ComponentMod, renderFlightStream, fullPageChunks, fullPageDebugChunks, startTime, stageEndTimes, clientReferenceManifest, createDebugChannel) {
    const cache = createSegmentCache();
    let partialStages;
    switch(prefetchKind){
        case 1:
            {
                partialStages = [
                    _stagedrendering.RenderStage.ShellRuntime,
                    _stagedrendering.RenderStage.Runtime
                ];
                break;
            }
        case 3:
            {
                partialStages = [
                    _stagedrendering.RenderStage.Static,
                    _stagedrendering.RenderStage.Runtime
                ];
                break;
            }
    }
    const doStage = async (targetStage)=>{
        const endTime = targetStage !== _stagedrendering.RenderStage.Dynamic ? stageEndTimes[targetStage] : undefined;
        const firstStage = partialStages[0];
        return await collectSegmentDataForStage(ComponentMod, renderFlightStream, fullPageChunks, fullPageDebugChunks, clientReferenceManifest, createDebugChannel, cache, firstStage, targetStage, startTime, endTime);
    };
    for (const targetStage of partialStages){
        await doStage(targetStage);
    }
    const payload = await doStage(_stagedrendering.RenderStage.Dynamic);
    return {
        cache,
        payload
    };
}
async function collectSegmentDataForStage(ComponentMod, renderFlightStream, fullPageChunks, fullPageDebugChunks, clientReferenceManifest, createDebugChannel, cache, firstStage, targetStage, startTime, endTime) {
    const debugChannelAbortController = new AbortController();
    const debugStream = fullPageDebugChunks ? (0, _streamutils.createNodeStreamFromChunks)(fullPageDebugChunks, debugChannelAbortController.signal) : null;
    const { stream, controller } = createStagedStreamFromChunks(fullPageChunks);
    stream.on('end', ()=>{
        // When the stream finishes, we have to close the debug stream too,
        // but delay it to avoid "Connection closed." errors.
        setImmediate(()=>debugChannelAbortController.abort());
    });
    // Technically we're just re-encoding, so nothing new should be emitted,
    // but we add an environment name just in case.
    const environmentName = ()=>{
        const currentStage = controller.currentStage;
        switch(currentStage){
            case _stagedrendering.RenderStage.Before:
            case _stagedrendering.RenderStage.Static:
                return 'Prerender';
            case _stagedrendering.RenderStage.ShellRuntime:
            case _stagedrendering.RenderStage.Runtime:
                return 'Prefetch';
            case _stagedrendering.RenderStage.Dynamic:
                return 'Server';
            default:
                currentStage;
                throw Object.defineProperty(new _invarianterror.InvariantError(`Invalid render stage: ${currentStage}`), "__NEXT_ERROR_CODE", {
                    value: "E881",
                    enumerable: false,
                    configurable: true
                });
        }
    };
    // Deserialize the payload partially so that we can traverse the structure.
    const serverConsumerManifest = {
        moduleLoading: null,
        moduleMap: clientReferenceManifest.rscModuleMapping,
        serverModuleMap: (0, _manifestssingleton.getServerModuleMap)()
    };
    const payloadPromise = (0, _client.createFromNodeStream)(stream, serverConsumerManifest, {
        findSourceMapURL,
        debugChannel: debugStream ?? undefined,
        startTime,
        // Each stage is decoded with an `endTime` corresponding to
        // when it finished rendering, so that we can avoid pointing to
        // IO that finished after the stage is done.
        // This needs to happen during the first deserialization, because
        // when we serialize the segments afterwards, React will clamp the
        // timestamps of IO to the current time, and we will lose the ability
        // to omit info about IO that hasn't resolved in this stage.
        endTime
    });
    // We expect the outer structure of the payload to be readable in any stage,
    // even if the segments are incomplete.
    // NOTE: This must be done after the `createFromNodeStream` call but *before*
    // the result is awaited, otherwise we'll deadlock.
    controller.advanceStage(firstStage);
    const payload = await payloadPromise;
    // Deconstruct the payload into separate streams per segment.
    // We have to preserve the stage information for each of them,
    // so that we can later render each segment in any stage we need.
    const { head } = getRootDataFromPayload(payload);
    const segments = new Map();
    traverseRootSeedDataSegments(payload, (segmentPath, seedData)=>{
        segments.set(segmentPath, createSegmentData(seedData));
    });
    const pendingTasks = [];
    const renderIntoStageEntry = async (data, stageEntry)=>{
        const segmentDebugChannel = stageEntry.debugChunks ? createDebugChannel() : undefined;
        const itemStream = renderFlightStream(ComponentMod, data, clientReferenceManifest.clientModules, {
            filterStackFrame,
            debugChannel: segmentDebugChannel == null ? void 0 : segmentDebugChannel.serverSide,
            environmentName,
            startTime,
            onError: onFlightRenderError
        });
        await Promise.all([
            // accumulate Flight chunks
            (async ()=>{
                for await (const chunk of itemStream){
                    if (controller.currentStage === _stagedrendering.RenderStage.Before) {
                        throw Object.defineProperty(new _invarianterror.InvariantError('Unexpected chunk emitted in Before stage'), "__NEXT_ERROR_CODE", {
                            value: "E1462",
                            enumerable: false,
                            configurable: true
                        });
                    }
                    writeChunk(stageEntry, controller.currentStage, targetStage, chunk);
                }
            })(),
            // accumulate Debug chunks
            segmentDebugChannel && (async ()=>{
                for await (const chunk of segmentDebugChannel.clientSide.readable){
                    stageEntry.debugChunks.push(chunk);
                }
            })()
        ]);
    };
    // Each stage is rendered in a separate pass (passed in as targetStage),
    // so we only need two stages:
    // 1. the target stage
    // 2. the dynamic stage (for late-release debug info)
    await (0, _apprenderrenderutils.runInSequentialTasks)(()=>{
        if (targetStage !== _stagedrendering.RenderStage.Dynamic) {
            controller.advanceStage(targetStage);
        }
        const withDebugChunks = !!fullPageDebugChunks;
        {
            let headCacheItem = cache.head;
            if (!headCacheItem) {
                headCacheItem = createSegmentCacheItem();
                cache.head = headCacheItem;
            }
            const stageEntry = getOrCreateStageEntry(headCacheItem, targetStage, withDebugChunks);
            pendingTasks.push(renderIntoStageEntry(head, stageEntry));
        }
        for (const [segmentPath, segmentData] of segments){
            let segmentCacheItem = cache.segments.get(segmentPath);
            if (!segmentCacheItem) {
                segmentCacheItem = createSegmentCacheItem();
                cache.segments.set(segmentPath, segmentCacheItem);
            }
            const stageEntry = getOrCreateStageEntry(segmentCacheItem, targetStage, withDebugChunks);
            pendingTasks.push(renderIntoStageEntry(segmentData, stageEntry));
        }
    }, ()=>{
        controller.advanceStage(_stagedrendering.RenderStage.Dynamic);
    });
    await Promise.all(pendingTasks);
    return payload;
}
function onFlightRenderError(error) {
    const digest = (0, _createerrorhandler.getDigestForWellKnownError)(error);
    if (digest) {
        return digest;
    }
    // Forward existing digests
    if (error && typeof error === 'object' && 'digest' in error && typeof error.digest === 'string') {
        return error.digest;
    }
    // We don't need to log the errors because we would have already done that
    // when generating the original Flight stream for the whole page.
    if (process.env.NEXT_DEBUG_BUILD || process.env.__NEXT_VERBOSE_LOGGING) {
        const workStore = _workasyncstorageexternal.workAsyncStorage.getStore();
        (0, _prospectiverenderutils.printDebugThrownValueForProspectiveRender)(error, (workStore == null ? void 0 : workStore.route) ?? 'unknown route', _prospectiverenderutils.Phase.InstantValidation);
    }
}
/**
 * Turns accumulated stage chunks into a stream.
 * The stream starts out in Static stage, and can be advanced further
 * using the returned controller object.
 * Conceptually, this is similar to how we unblock more content
 * by advancing stages in a regular staged render.
 * */ function createStagedStreamFromChunks(stageChunks) {
    // The successive stages are supersets of one another,
    // so we can index into the dynamic chunks everywhere
    // and just look at the lengths of the Static/Runtime arrays
    const allChunks = stageChunks[_stagedrendering.RenderStage.Dynamic];
    let chunkIx = 0;
    let currentStage = _stagedrendering.RenderStage.Before;
    let closed = false;
    function emitNewChunks(chunks) {
        for(; chunkIx < chunks.length; chunkIx++){
            stream.push(allChunks[chunkIx]);
        }
    }
    function close() {
        closed = true;
        stream.push(null);
    }
    const stream = new _nodestream.Readable({
        read () {}
    });
    function advanceStage(stage) {
        if (closed) return true;
        // NOTE: we don't special handling for skipping stages,
        // emitNewChunks will emit anything that hasn't been emitted before.
        currentStage = stage;
        emitNewChunks(stageChunks[stage]);
        // If there's no more chunks after this stage, finish the stream.
        if (chunkIx >= allChunks.length) {
            close();
            return true;
        } else {
            return false;
        }
    }
    return {
        stream,
        controller: {
            get currentStage () {
                return currentStage;
            },
            advanceStage
        }
    };
}
function writeChunk(stageData, currentStage, targetStage, chunk) {
    if (currentStage <= targetStage) {
        stageData.chunks.push(chunk);
    }
    stageData.allChunks.push(chunk);
}
async function createCombinedPayloadStream(ComponentMod, renderFlightStream, payload, extraChunksAbortController, renderSignal, clientReferenceManifest, startTime, isDebugChannelEnabled, createDebugChannel) {
    // Collect all the chunks so that we're not dependent on timing of the render.
    let isRenderable = true;
    const renderableChunks = [];
    const allChunks = [];
    const debugChunks = isDebugChannelEnabled ? [] : null;
    const debugChannel = isDebugChannelEnabled ? createDebugChannel() : null;
    let streamFinished;
    await (0, _apprenderrenderutils.runInSequentialTasks)(()=>{
        const stream = renderFlightStream(ComponentMod, payload, clientReferenceManifest.clientModules, {
            filterStackFrame,
            debugChannel: debugChannel == null ? void 0 : debugChannel.serverSide,
            startTime,
            onError (error) {
                const digest = (0, _createerrorhandler.getDigestForWellKnownError)(error);
                if (digest) {
                    return digest;
                }
                // Forward existing digests
                if (error && typeof error === 'object' && 'digest' in error && typeof error.digest === 'string') {
                    return error.digest;
                }
                // We don't need to log the errors because we would have already done that
                // when generating the original Flight stream for the whole page.
                if (process.env.NEXT_DEBUG_BUILD || process.env.__NEXT_VERBOSE_LOGGING) {
                    const workStore = _workasyncstorageexternal.workAsyncStorage.getStore();
                    (0, _prospectiverenderutils.printDebugThrownValueForProspectiveRender)(error, (workStore == null ? void 0 : workStore.route) ?? 'unknown route', _prospectiverenderutils.Phase.InstantValidation);
                }
            }
        });
        streamFinished = Promise.all([
            // Accumulate Flight chunks
            (async ()=>{
                for await (const chunk of stream){
                    allChunks.push(chunk);
                    if (isRenderable) {
                        renderableChunks.push(chunk);
                    }
                }
            })(),
            // Accumulate debug chunks
            debugChannel && (async ()=>{
                for await (const chunk of debugChannel.clientSide.readable){
                    debugChunks.push(chunk);
                }
            })()
        ]);
    }, ()=>{
        isRenderable = false;
        extraChunksAbortController.abort();
    });
    await streamFinished;
    return {
        stream: (0, _streamutils.createNodeStreamWithLateRelease)(renderableChunks, allChunks, renderSignal),
        debugStream: debugChunks ? (0, _streamutils.createNodeStreamFromChunks)(debugChunks, renderSignal) : null
    };
}
function getRootDataFromPayload(initialRSCPayload) {
    // FlightDataPath is an unsound type, hence the additional checks. The
    // valid shapes are a single root path with no segment prefix: 4 elements
    // ([tree, seedData, head, isHeadPartial], per getRSCPayload) or 3 when
    // reconstructed without the isHeadPartial flag (see the payload literals
    // in this module).
    const flightDataPaths = initialRSCPayload.f;
    if (flightDataPaths.length !== 1 || flightDataPaths[0].length !== 3 && flightDataPaths[0].length !== 4) {
        throw Object.defineProperty(new _invarianterror.InvariantError('InitialRSCPayload does not match the expected shape during instant validation.'), "__NEXT_ERROR_CODE", {
            value: "E994",
            enumerable: false,
            configurable: true
        });
    }
    const flightRouterState = flightDataPaths[0][0];
    const seedData = flightDataPaths[0][1];
    // TODO: handle head
    const head = flightDataPaths[0][2];
    return {
        flightRouterState,
        seedData,
        head
    };
}
async function createValidationHead(cache, releaseSignal, clientReferenceManifest, stage) {
    const segmentCacheItem = cache.head;
    if (!segmentCacheItem) {
        throw Object.defineProperty(new _invarianterror.InvariantError(`Missing segment data: <head>`), "__NEXT_ERROR_CODE", {
            value: "E1072",
            enumerable: false,
            configurable: true
        });
    }
    const stageEntry = getStageEntry(segmentCacheItem, stage);
    return await deserializeFromChunks(stageEntry.chunks, stageEntry.allChunks, stageEntry.debugChunks, releaseSignal, clientReferenceManifest, // NOTE: We're not passing an endTime, because the debug info has already been
    // truncated to the appropriate `endTime` when the segment cache was filled.
    {
        startTime: undefined,
        endTime: undefined
    });
}
/**
 * Deserializes a (partial possibly partial) RSC stream, given as a chunk-array.
 * If the stream is partial, we'll wait for `releaseSignal` to fire
 * and then complete the deserialization using `allChunks`.
 *
 * This is used to obtain a partially-complete model (that might contain unresolved holes)
 * and then release any late debug info from chunks that came later before we abort the render.
 * */ function deserializeFromChunks(partialChunks, allChunks, debugChunks, releaseSignal, clientReferenceManifest, timings) {
    const debugChannelAbortController = new AbortController();
    const debugStream = debugChunks ? (0, _streamutils.createNodeStreamFromChunks)(debugChunks, debugChannelAbortController.signal) : null;
    const serverConsumerManifest = {
        moduleLoading: null,
        moduleMap: clientReferenceManifest.rscModuleMapping,
        serverModuleMap: (0, _manifestssingleton.getServerModuleMap)()
    };
    const segmentStream = partialChunks.length < allChunks.length ? (0, _streamutils.createNodeStreamWithLateRelease)(partialChunks, allChunks, releaseSignal) : (0, _streamutils.createNodeStreamFromChunks)(partialChunks);
    segmentStream.on('end', ()=>{
        // When the stream finishes, we have to close the debug stream too,
        // but delay it to avoid "Connection closed." errors.
        setImmediate(()=>debugChannelAbortController.abort());
    });
    return (0, _client.createFromNodeStream)(segmentStream, serverConsumerManifest, {
        findSourceMapURL,
        debugChannel: debugStream ?? undefined,
        startTime: timings == null ? void 0 : timings.startTime,
        endTime: timings == null ? void 0 : timings.endTime
    });
}
function createSegmentData(seedData) {
    const [node, _parallelRoutesData, _unused, isPartial, varyParams] = seedData;
    return {
        node,
        isPartial,
        varyParams
    };
}
function getCacheNodeSeedDataFromSegment(data, slots) {
    return [
        data.node,
        slots,
        /* unused (previously `loading`) */ null,
        data.isPartial,
        data.varyParams
    ];
}
function createSegmentCache() {
    return {
        head: null,
        segments: new Map()
    };
}
function createSegmentCacheItem() {
    return {
        [_stagedrendering.RenderStage.Static]: null,
        [_stagedrendering.RenderStage.ShellRuntime]: null,
        [_stagedrendering.RenderStage.Runtime]: null,
        [_stagedrendering.RenderStage.Dynamic]: null
    };
}
function createSegmentCacheItemStageEntry(withDebugChunks) {
    return {
        allChunks: [],
        chunks: [],
        debugChunks: withDebugChunks ? [] : null
    };
}
function getOrCreateStageEntry(segmentCacheItem, stage, withDebugChunks) {
    let data = segmentCacheItem[stage];
    if (!data) {
        data = createSegmentCacheItemStageEntry(withDebugChunks);
        segmentCacheItem[stage] = data;
    }
    return data;
}
function getStageEntry(segmentCacheItem, stage) {
    const data = segmentCacheItem[stage];
    if (!data) {
        // Indicates that we didn't fill the cache at this stage.
        throw Object.defineProperty(new _invarianterror.InvariantError(`Expected segment cache to have data for stage '${_stagedrendering.RenderStage[stage]}'`), "__NEXT_ERROR_CODE", {
            value: "E1461",
            enumerable: false,
            configurable: true
        });
    }
    return data;
}
/**
 * Whether this segment consumes a URL depth level. Each URL depth
 * represents a potential navigation boundary.
 *
 * The root segment ('') consumes depth 0. Regular segments like
 * 'dashboard' consume the next depth — whether or not they have a
 * layout. Route groups, __PAGE__, __DEFAULT__, and /_not-found don't
 * consume a depth — they share the boundary of their parent.
 */ function segmentConsumesURLDepth(segment) {
    // Dynamic segments (tuples) always consume a URL depth.
    if (typeof segment !== 'string') return true;
    // Route groups, pages, defaults, and not-found don't consume a depth.
    if (segment.startsWith(_segment.PAGE_SEGMENT_KEY) || (0, _segment.isGroupSegment)(segment) || segment === _segment.DEFAULT_SEGMENT_KEY || segment === _segment.NOT_FOUND_SEGMENT_KEY) {
        return false;
    }
    // Everything else consumes a depth, including the root segment ''.
    return true;
}
function discoverValidationDepths(loaderTree) {
    const groupDepthsByUrlDepth = [];
    function recordGroupDepth(urlDepth, groupDepth) {
        while(groupDepthsByUrlDepth.length <= urlDepth){
            groupDepthsByUrlDepth.push(0);
        }
        if (groupDepth > groupDepthsByUrlDepth[urlDepth]) {
            groupDepthsByUrlDepth[urlDepth] = groupDepth;
        }
    }
    // urlDepth tracks the index of the current URL-consuming segment.
    // Groups accumulate at the same index. When the next URL segment
    // is reached, it increments the index and resets the group counter.
    // We start at -1 so the root segment '' increments to 0.
    function walk(tree, urlDepth, groupDepth) {
        const segment = tree[0];
        const { parallelRoutes } = (0, _parseloadertree.parseLoaderTree)(tree);
        const consumesDepth = segmentConsumesURLDepth(segment);
        let nextUrlDepth = urlDepth;
        let nextGroupDepth = groupDepth;
        if (consumesDepth) {
            nextUrlDepth = urlDepth + 1;
            nextGroupDepth = 0;
            recordGroupDepth(nextUrlDepth, 0);
        } else if (typeof segment === 'string' && (0, _segment.isGroupSegment)(segment) && segment !== '(__SLOT__)') {
            // Count real route groups but not the synthetic '(__SLOT__)' segment
            // that Next.js inserts for parallel slots. The synthetic group
            // can't be a real navigation boundary.
            nextGroupDepth++;
            recordGroupDepth(urlDepth, nextGroupDepth);
        }
        for(const key in parallelRoutes){
            walk(parallelRoutes[key], nextUrlDepth, nextGroupDepth);
        }
    }
    walk(loaderTree, -1, 0);
    return groupDepthsByUrlDepth;
}
var ValidationPrefetchKind = /*#__PURE__*/ function(ValidationPrefetchKind) {
    /** App Shells, for `<Link>` without `prefetch={true}` */ ValidationPrefetchKind[ValidationPrefetchKind["Shell"] = 1] = "Shell";
    // TODO(app-shells): validate speculative prefetches
    // Speculative = 2,
    /** Behavior when Partial Prefetching is not enabled. */ ValidationPrefetchKind[ValidationPrefetchKind["LegacySpeculative"] = 3] = "LegacySpeculative";
    return ValidationPrefetchKind;
}({});
async function createCombinedPayloadAtDepth(prefetchKind, initialRSCPayload, cache, initialLoaderTree, getDynamicParamFromSegment, query, depth, groupDepth, releaseSignal, boundaryState, clientReferenceManifest, useRuntimeStageForPartialSegments) {
    const workStore = _workasyncstorageexternal.workAsyncStorage.getStore();
    if (!workStore) {
        throw Object.defineProperty(new _invarianterror.InvariantError('createCombinedPayloadAtDepth must run inside a WorkStore'), "__NEXT_ERROR_CODE", {
            value: "E1184",
            enumerable: false,
            configurable: true
        });
    }
    const { validationLevel, route } = workStore;
    let hasStaticSegments = false;
    let hasRuntimeSegments = false;
    // Index 0 is reserved for the root config. Slot markers start at 1.
    const slotStacks = [
        null
    ];
    /**
   * When a segment has multiple parallel routes (a fork), wrap each
   * slot's seed data with a slot marker component. The marker's index
   * in the component stack maps to `slotStacks` for per-slot error
   * attribution. Slot markers start at index 1 (index 0 is root).
   */ function wrapSlotsWithMarkers(slots, results) {
        const keys = Object.keys(slots);
        if (keys.length <= 1) return;
        for (const key of keys){
            const slotSeedData = slots[key];
            if (slotSeedData === null) continue;
            const result = results.get(key);
            const markerIndex = slotStacks.length;
            slotStacks.push((result == null ? void 0 : result.createInstantStack) ?? null);
            const markerName = `${_boundaryconstants.INSTANT_SLOT_MARKER_PREFIX}${markerIndex - 1}${_boundaryconstants.INSTANT_SLOT_MARKER_SUFFIX}`;
            const [node, parallelRoutesData, unused, isPartial, varyParams] = slotSeedData;
            slots[key] = [
                // eslint-disable-next-line @next/internal/no-ambiguous-jsx -- bundled in the server layer
                /*#__PURE__*/ (0, _jsxruntime.jsx)(_boundary.SlotMarker, {
                    name: markerName,
                    children: node
                }, "sm"),
                parallelRoutesData,
                unused,
                isPartial,
                varyParams
            ];
        }
    }
    function getSegment(loaderTree) {
        const dynamicParam = getDynamicParamFromSegment(loaderTree);
        if (dynamicParam) {
            return dynamicParam.treeSegment;
        }
        const segment = loaderTree[0];
        return query ? (0, _segment.addSearchParamsIfPageSegment)(segment, query) : segment;
    }
    async function buildSharedTreeSeedData(loaderTree, parentPath, key, urlDepthConsumed, groupDepthConsumed) {
        const { parallelRoutes } = (0, _parseloadertree.parseLoaderTree)(loaderTree);
        const segment = getSegment(loaderTree);
        const path = parentPath === null ? stringifySegment(segment) : createChildSegmentPath(parentPath, key, segment);
        debug == null ? void 0 : debug(`    ${path || '/'} - Dynamic`);
        const segmentCacheItem = cache.segments.get(path);
        if (!segmentCacheItem) {
            throw Object.defineProperty(new _invarianterror.InvariantError(`Missing segment data: ${path}`), "__NEXT_ERROR_CODE", {
                value: "E995",
                enumerable: false,
                configurable: true
            });
        }
        const stageEntry = getStageEntry(segmentCacheItem, _stagedrendering.RenderStage.Dynamic);
        const dynamicChunks = stageEntry.chunks;
        const segmentData = await deserializeFromChunks(dynamicChunks, dynamicChunks, stageEntry.debugChunks, releaseSignal, clientReferenceManifest, null);
        const consumesUrlDepth = segmentConsumesURLDepth(segment);
        const isGroup = typeof segment === 'string' && (0, _segment.isGroupSegment)(segment) && segment !== '(__SLOT__)';
        // Advance counters for this segment before the boundary check,
        // mirroring how discoverValidationDepths counts. URL segments
        // increment urlDepthConsumed, groups increment groupDepthConsumed.
        // The synthetic '(__SLOT__)' segment is excluded — it can't be a
        // real navigation boundary.
        let nextUrlDepth = urlDepthConsumed;
        let currentGroupDepth = groupDepthConsumed;
        if (consumesUrlDepth) {
            nextUrlDepth++;
            currentGroupDepth = 0;
        } else if (isGroup) {
            currentGroupDepth++;
        }
        const pastUrlBoundary = nextUrlDepth > depth;
        const isBoundary = pastUrlBoundary && currentGroupDepth >= groupDepth;
        if (isBoundary) {
            debug == null ? void 0 : debug(`    ['${path}' is the boundary (url=${nextUrlDepth}, group=${currentGroupDepth})]`);
            const finalSegmentData = {
                ...segmentData,
                node: // eslint-disable-next-line @next/internal/no-ambiguous-jsx -- bundled in the server layer
                /*#__PURE__*/ (0, _jsxruntime.jsx)(_boundary.PlaceValidationBoundaryBelowThisLevel, {
                    id: path,
                    children: segmentData.node
                }, "c")
            };
            const slots = {};
            const slotResults = new Map();
            let requiresInstantUI = false;
            let createInstantStack = null;
            let bestConfigDepth = -1;
            // Collect the first mod file path from each slot's subtree.
            // Don't include the boundary segment's own layout/page — that
            // file DID render (it wraps the boundary). What didn't render
            // is the content inside the children slots.
            const slotModFilePaths = [];
            let firstModFilePath = null;
            for(const parallelRouteKey in parallelRoutes){
                const result = await buildNewTreeSeedData(parallelRoutes[parallelRouteKey], path, parallelRouteKey, 0 /* segmentDepth */ );
                slotResults.set(parallelRouteKey, result);
                slots[parallelRouteKey] = result.seedData;
                if (result.firstModFilePath !== null) {
                    slotModFilePaths.push(result.firstModFilePath);
                    if (firstModFilePath === null) {
                        firstModFilePath = result.firstModFilePath;
                    }
                }
                if (result.requiresInstantUI) {
                    requiresInstantUI = true;
                    if (result.configDepth > bestConfigDepth || result.configDepth === bestConfigDepth && parallelRouteKey === 'children') {
                        bestConfigDepth = result.configDepth;
                        createInstantStack = result.createInstantStack;
                    }
                }
            }
            // Only require this boundary to render if the subtree has an
            // instant config. Unconfigured slot subtrees are allowed to not
            // render (e.g. conditionally excluded by a layout).
            if (requiresInstantUI) {
                boundaryState.requiredIds.set(path, slotModFilePaths);
            }
            wrapSlotsWithMarkers(slots, slotResults);
            return {
                seedData: getCacheNodeSeedDataFromSegment(finalSegmentData, slots),
                requiresInstantUI,
                createInstantStack,
                firstModFilePath,
                configDepth: bestConfigDepth
            };
        }
        // Not at the boundary yet — keep walking as shared.
        const slots = {};
        const slotResults = new Map();
        let requiresInstantUI = false;
        let createInstantStack = null;
        let bestConfigDepth = -1;
        let firstModFilePath = null;
        for(const parallelRouteKey in parallelRoutes){
            const result = await buildSharedTreeSeedData(parallelRoutes[parallelRouteKey], path, parallelRouteKey, nextUrlDepth, currentGroupDepth);
            slotResults.set(parallelRouteKey, result);
            slots[parallelRouteKey] = result.seedData;
            if (firstModFilePath === null) {
                firstModFilePath = result.firstModFilePath;
            }
            if (result.requiresInstantUI) {
                requiresInstantUI = true;
                if (result.configDepth > bestConfigDepth || result.configDepth === bestConfigDepth && parallelRouteKey === 'children') {
                    bestConfigDepth = result.configDepth;
                    createInstantStack = result.createInstantStack;
                }
            }
        }
        wrapSlotsWithMarkers(slots, slotResults);
        return {
            seedData: getCacheNodeSeedDataFromSegment(segmentData, slots),
            requiresInstantUI,
            createInstantStack,
            firstModFilePath,
            configDepth: bestConfigDepth
        };
    }
    async function buildNewTreeSeedData(lt, parentPath, key, segmentDepth) {
        const { parallelRoutes } = (0, _parseloadertree.parseLoaderTree)(lt);
        const { mod: layoutOrPageMod, filePath: layoutOrPageFilePath } = await (0, _appdirmodule.getLayoutOrPageModule)(lt);
        const localModFilePath = layoutOrPageFilePath ?? null;
        const segment = getSegment(lt);
        const path = parentPath === null ? stringifySegment(segment) : createChildSegmentPath(parentPath, key, segment);
        let instantConfig = null;
        let localCreateInstantStack = null;
        if (layoutOrPageMod !== undefined) {
            instantConfig = layoutOrPageMod.instant ?? null;
            // When the default validation level is active and this is a page or
            // default segment without an explicit config, treat it as if
            // instant = true was exported. Framework-synthesized error
            // routes are excluded — see isFrameworkErrorRoute.
            if (instantConfig === null && validationLevel !== 'manual-warning' && validationLevel !== 'experimental-manual-error' && (0, _instantconfig.isImplicitValidationSegment)(segment) && !(0, _instantconfig.isFrameworkErrorRoute)(route)) {
                instantConfig = true;
            }
            if (instantConfig === true || typeof instantConfig === 'object' && instantConfig !== null) {
                const rawFactory = layoutOrPageMod.__debugCreateInstantConfigStack;
                localCreateInstantStack = typeof rawFactory === 'function' ? rawFactory : null;
            }
        }
        const segmentCacheItem = cache.segments.get(path);
        if (!segmentCacheItem) {
            throw Object.defineProperty(new _invarianterror.InvariantError(`Missing segment data: ${path}`), "__NEXT_ERROR_CODE", {
                value: "E995",
                enumerable: false,
                configurable: true
            });
        }
        let stage;
        switch(prefetchKind){
            case 1:
                {
                    if (useRuntimeStageForPartialSegments) {
                        stage = _stagedrendering.RenderStage.Runtime;
                    } else {
                        stage = _stagedrendering.RenderStage.ShellRuntime;
                    }
                    break;
                }
            case 3:
                {
                    if (useRuntimeStageForPartialSegments) {
                        stage = _stagedrendering.RenderStage.Runtime;
                    } else {
                        // In legacy speculative prefetches, we always use static.
                        stage = _stagedrendering.RenderStage.Static;
                    }
                    break;
                }
        }
        switch(stage){
            case _stagedrendering.RenderStage.Static:
                {
                    hasStaticSegments = true;
                    break;
                }
            case _stagedrendering.RenderStage.ShellRuntime:
                {
                    break;
                }
            case _stagedrendering.RenderStage.Runtime:
                {
                    hasRuntimeSegments = true;
                    break;
                }
        }
        debug == null ? void 0 : debug(`    ${path || '/'} - ${_stagedrendering.RenderStage[stage]}`);
        const stageEntry = getStageEntry(segmentCacheItem, stage);
        const segmentData = await deserializeFromChunks(stageEntry.chunks, stageEntry.allChunks, stageEntry.debugChunks, releaseSignal, clientReferenceManifest, // NOTE: We're not passing an endTime, because the debug info has already been
        // truncated to the appropriate `endTime` when the segment cache was filled.
        {
            startTime: undefined,
            endTime: undefined
        });
        // Build children first, then determine requiresInstantUI.
        const slots = {};
        const slotResults = new Map();
        let childrenRequireInstantUI = false;
        let childCreateInstantStack = null;
        let bestChildConfigDepth = -1;
        let childFirstModFilePath = null;
        for(const parallelRouteKey in parallelRoutes){
            const childSegmentDepth = segmentConsumesURLDepth(segment) ? segmentDepth + 1 : segmentDepth;
            const result = await buildNewTreeSeedData(parallelRoutes[parallelRouteKey], path, parallelRouteKey, childSegmentDepth);
            slotResults.set(parallelRouteKey, result);
            slots[parallelRouteKey] = result.seedData;
            if (childFirstModFilePath === null) {
                childFirstModFilePath = result.firstModFilePath;
            }
            if (result.requiresInstantUI) {
                childrenRequireInstantUI = true;
                if (result.configDepth > bestChildConfigDepth || result.configDepth === bestChildConfigDepth && parallelRouteKey === 'children') {
                    bestChildConfigDepth = result.configDepth;
                    childCreateInstantStack = result.createInstantStack;
                }
            }
        }
        wrapSlotsWithMarkers(slots, slotResults);
        // Local config takes precedence over children.
        let requiresInstantUI;
        let createInstantStack;
        let configDepth;
        if (instantConfig === false) {
            requiresInstantUI = false;
            createInstantStack = null;
            configDepth = -1;
        } else if (instantConfig === true || typeof instantConfig === 'object' && instantConfig !== null) {
            requiresInstantUI = true;
            createInstantStack = localCreateInstantStack;
            configDepth = segmentDepth;
        } else {
            requiresInstantUI = childrenRequireInstantUI;
            createInstantStack = childCreateInstantStack;
            configDepth = bestChildConfigDepth;
        }
        // First mod we find in DFS order: this segment's own layout/page if
        // any, otherwise the first non-null we got from a child.
        const firstModFilePath = localModFilePath ?? childFirstModFilePath;
        return {
            seedData: getCacheNodeSeedDataFromSegment(segmentData, slots),
            requiresInstantUI,
            createInstantStack,
            firstModFilePath,
            configDepth
        };
    }
    const { seedData, requiresInstantUI, createInstantStack } = await buildSharedTreeSeedData(initialLoaderTree, null, null, 0 /* urlDepthConsumed */ , 0 /* groupDepthConsumed */ );
    if (!requiresInstantUI) {
        return null;
    }
    // Set the root config at index 0. This is the fallback for errors
    // that occur above any fork (no slot marker in the component stack).
    slotStacks[0] = createInstantStack;
    const { flightRouterState } = getRootDataFromPayload(initialRSCPayload);
    let headStage;
    switch(prefetchKind){
        case 1:
            {
                if (useRuntimeStageForPartialSegments) {
                    headStage = _stagedrendering.RenderStage.Runtime;
                } else {
                    headStage = _stagedrendering.RenderStage.ShellRuntime;
                }
                break;
            }
        case 3:
            {
                headStage = hasRuntimeSegments ? _stagedrendering.RenderStage.Runtime : _stagedrendering.RenderStage.Static;
                break;
            }
    }
    debug == null ? void 0 : debug(`    /_head - ${_stagedrendering.RenderStage[headStage]}`);
    let hasAmbiguousErrors;
    switch(prefetchKind){
        case 1:
            {
                // In a shell prefetch, holes are always ambiguous
                // (they can be either link data or dynamic data)
                // unless we're already overriding and using the runtime stage,
                // which resolves link data.
                hasAmbiguousErrors = !useRuntimeStageForPartialSegments;
                break;
            }
        case 3:
            {
                // In the old prefetching mechanism, holes in static segments are ambiguous
                // (they can be either runtime data or dynamic data).
                hasAmbiguousErrors = hasStaticSegments;
                break;
            }
    }
    const head = await createValidationHead(cache, releaseSignal, clientReferenceManifest, headStage);
    const payload = {
        ...initialRSCPayload,
        f: [
            [
                flightRouterState,
                seedData,
                head
            ]
        ]
    };
    return {
        payload,
        hasAmbiguousErrors,
        slotStacks
    };
}

//# sourceMappingURL=instant-validation.js.map