UNPKG

next

Version:

The React Framework

713 lines (712 loc) 33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); 0 && (module.exports = { 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, { 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 _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 _debugchannelserver = require("../debug-channel-server"); const _client = require("react-server-dom-webpack/client"); const _server = require("react-server-dom-webpack/server"); const _segment = require("../../../shared/lib/segment"); 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(fullPageChunks, fullPageDebugChunks, startTime, hasRuntimePrefetch, clientReferenceManifest) { 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.Static: return 'Prerender'; case _stagedrendering.RenderStage.Runtime: return hasRuntimePrefetch ? 'Prefetch' : 'Prefetchable'; 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. // NOTE: the stream will initially be in the static stage, so that's as far as we get here. // We still expect the outer structure of the payload to be readable in this state. const serverConsumerManifest = { moduleLoading: null, moduleMap: clientReferenceManifest.rscModuleMapping, serverModuleMap: (0, _manifestssingleton.getServerModuleMap)() }; const payload = await (0, _client.createFromNodeStream)(stream, serverConsumerManifest, { findSourceMapURL, debugChannel: debugStream ?? undefined, // Do not pass start/end timings - we do not want to omit any debug info. startTime: undefined, endTime: undefined }); // 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 cache = createSegmentCache(); const pendingTasks = []; /** Track when we advance stages so we can pass them as `endTime` later. */ const stageEndTimes = { [_stagedrendering.RenderStage.Static]: -1, [_stagedrendering.RenderStage.Runtime]: -1 }; const renderIntoCacheItem = async (data, cacheEntry)=>{ const segmentDebugChannel = cacheEntry.debugChunks ? (0, _debugchannelserver.createDebugChannel)() : undefined; const itemStream = (0, _server.renderToReadableStream)(data, clientReferenceManifest.clientModules, { filterStackFrame, debugChannel: segmentDebugChannel == null ? void 0 : segmentDebugChannel.serverSide, environmentName, 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); } } }); await Promise.all([ // accumulate Flight chunks (async ()=>{ for await (const chunk of itemStream.values()){ writeChunk(cacheEntry.chunks, controller.currentStage, chunk); } })(), // accumulate Debug chunks segmentDebugChannel && (async ()=>{ for await (const chunk of segmentDebugChannel.clientSide.readable.values()){ cacheEntry.debugChunks.push(chunk); } })() ]); }; await (0, _apprenderrenderutils.runInSequentialTasks)(()=>{ { const headCacheItem = createSegmentCacheItem(!!fullPageDebugChunks); cache.head = headCacheItem; pendingTasks.push(renderIntoCacheItem(head, headCacheItem)); } for (const [segmentPath, segmentData] of segments){ const segmentCacheItem = createSegmentCacheItem(!!fullPageDebugChunks); cache.segments.set(segmentPath, segmentCacheItem); pendingTasks.push(renderIntoCacheItem(segmentData, segmentCacheItem)); } }, ()=>{ stageEndTimes[_stagedrendering.RenderStage.Static] = performance.now() + performance.timeOrigin; controller.advanceStage(_stagedrendering.RenderStage.Runtime); }, ()=>{ stageEndTimes[_stagedrendering.RenderStage.Runtime] = performance.now() + performance.timeOrigin; controller.advanceStage(_stagedrendering.RenderStage.Dynamic); }); await Promise.all(pendingTasks); return { cache, payload, stageEndTimes }; } /** * 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]; const numStaticChunks = stageChunks[_stagedrendering.RenderStage.Static].length; const numRuntimeChunks = stageChunks[_stagedrendering.RenderStage.Runtime].length; const numDynamicChunks = stageChunks[_stagedrendering.RenderStage.Dynamic].length; let chunkIx = 0; let currentStage = _stagedrendering.RenderStage.Static; let closed = false; function push(chunk) { stream.push(chunk); } function close() { closed = true; stream.push(null); } const stream = new _nodestream.Readable({ read () { // Emit static chunks for(; chunkIx < numStaticChunks; chunkIx++){ push(allChunks[chunkIx]); } // If there's no more chunks after this stage, finish the stream. if (chunkIx >= allChunks.length) { close(); return; } } }); function advanceStage(stage) { if (closed) return true; switch(stage){ case _stagedrendering.RenderStage.Runtime: { currentStage = _stagedrendering.RenderStage.Runtime; for(; chunkIx < numRuntimeChunks; chunkIx++){ push(allChunks[chunkIx]); } break; } case _stagedrendering.RenderStage.Dynamic: { currentStage = _stagedrendering.RenderStage.Dynamic; for(; chunkIx < numDynamicChunks; chunkIx++){ push(allChunks[chunkIx]); } break; } default: { 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(stageChunks, stage, chunk) { switch(stage){ case _stagedrendering.RenderStage.Static: { stageChunks[_stagedrendering.RenderStage.Static].push(chunk); // fallthrough } case _stagedrendering.RenderStage.Runtime: { stageChunks[_stagedrendering.RenderStage.Runtime].push(chunk); // fallthrough } case _stagedrendering.RenderStage.Dynamic: { stageChunks[_stagedrendering.RenderStage.Dynamic].push(chunk); break; } default: { stage; } } } async function createCombinedPayloadStream(payload, extraChunksAbortController, renderSignal, clientReferenceManifest, startTime, isDebugChannelEnabled) { // 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 ? (0, _debugchannelserver.createDebugChannel)() : null; let streamFinished; await (0, _apprenderrenderutils.runInSequentialTasks)(()=>{ const stream = (0, _server.renderToReadableStream)(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.values()){ allChunks.push(chunk); if (isRenderable) { renderableChunks.push(chunk); } } })(), // Accumulate debug chunks debugChannel && (async ()=>{ for await (const chunk of debugChannel.clientSide.readable.values()){ 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. const flightDataPaths = initialRSCPayload.f; if (flightDataPaths.length !== 1 && flightDataPaths[0].length !== 3) { 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, stageEndTimes, 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 }); } return await deserializeFromChunks(segmentCacheItem.chunks[stage], segmentCacheItem.chunks[_stagedrendering.RenderStage.Dynamic], segmentCacheItem.debugChunks, releaseSignal, clientReferenceManifest, { startTime: undefined, endTime: stageEndTimes[stage] }); } /** * 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(withDebugChunks) { return { chunks: { [_stagedrendering.RenderStage.Static]: [], [_stagedrendering.RenderStage.Runtime]: [], [_stagedrendering.RenderStage.Dynamic]: [] }, debugChunks: withDebugChunks ? [] : null }; } /** * 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; } async function createCombinedPayloadAtDepth(initialRSCPayload, cache, initialLoaderTree, getDynamicParamFromSegment, query, depth, groupDepth, releaseSignal, boundaryState, clientReferenceManifest, stageEndTimes, useRuntimeStageForPartialSegments) { let hasStaticSegments = false; let hasRuntimeSegments = false; 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 segmentData = await deserializeFromChunks(segmentCacheItem.chunks[_stagedrendering.RenderStage.Dynamic], segmentCacheItem.chunks[_stagedrendering.RenderStage.Dynamic], segmentCacheItem.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})]`); boundaryState.expectedIds.add(path); 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 = {}; let requiresInstantUI = false; let createInstantStack = null; for(const parallelRouteKey in parallelRoutes){ const result = await buildNewTreeSeedData(parallelRoutes[parallelRouteKey], path, parallelRouteKey, false); slots[parallelRouteKey] = result.seedData; if (result.requiresInstantUI) { requiresInstantUI = true; if (createInstantStack === null) { createInstantStack = result.createInstantStack; } } } return { seedData: getCacheNodeSeedDataFromSegment(finalSegmentData, slots), requiresInstantUI, createInstantStack }; } // Not at the boundary yet — keep walking as shared. const slots = {}; let requiresInstantUI = false; let createInstantStack = null; for(const parallelRouteKey in parallelRoutes){ const result = await buildSharedTreeSeedData(parallelRoutes[parallelRouteKey], path, parallelRouteKey, nextUrlDepth, currentGroupDepth); slots[parallelRouteKey] = result.seedData; if (result.requiresInstantUI) { requiresInstantUI = true; if (createInstantStack === null) { createInstantStack = result.createInstantStack; } } } return { seedData: getCacheNodeSeedDataFromSegment(segmentData, slots), requiresInstantUI, createInstantStack }; } async function buildNewTreeSeedData(lt, parentPath, key, isInsideRuntimePrefetch) { const { parallelRoutes } = (0, _parseloadertree.parseLoaderTree)(lt); const { mod: layoutOrPageMod } = await (0, _appdirmodule.getLayoutOrPageModule)(lt); 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.unstable_instant ?? null; if (instantConfig && typeof instantConfig === 'object') { const rawFactory = layoutOrPageMod.__debugCreateInstantConfigStack; localCreateInstantStack = typeof rawFactory === 'function' ? rawFactory : null; } } let childIsInsideRuntimePrefetch = isInsideRuntimePrefetch; let stage; if (!isInsideRuntimePrefetch) { if (instantConfig && typeof instantConfig === 'object' && instantConfig.prefetch === 'runtime') { stage = _stagedrendering.RenderStage.Runtime; childIsInsideRuntimePrefetch = true; hasRuntimeSegments = true; } else { if (useRuntimeStageForPartialSegments) { stage = _stagedrendering.RenderStage.Runtime; hasRuntimeSegments = true; } else { stage = _stagedrendering.RenderStage.Static; hasStaticSegments = true; } } } else { stage = _stagedrendering.RenderStage.Runtime; hasRuntimeSegments = true; } debug == null ? void 0 : debug(` ${path || '/'} - ${_stagedrendering.RenderStage[stage]}`); 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 segmentData = await deserializeFromChunks(segmentCacheItem.chunks[stage], segmentCacheItem.chunks[_stagedrendering.RenderStage.Dynamic], segmentCacheItem.debugChunks, releaseSignal, clientReferenceManifest, { startTime: undefined, endTime: stageEndTimes[stage] }); // Build children first, then determine requiresInstantUI. const slots = {}; let childrenRequireInstantUI = false; let childCreateInstantStack = null; for(const parallelRouteKey in parallelRoutes){ const result = await buildNewTreeSeedData(parallelRoutes[parallelRouteKey], path, parallelRouteKey, childIsInsideRuntimePrefetch); slots[parallelRouteKey] = result.seedData; if (result.requiresInstantUI) { childrenRequireInstantUI = true; if (childCreateInstantStack === null) { childCreateInstantStack = result.createInstantStack; } } } // Local config takes precedence over children. let requiresInstantUI; let createInstantStack; if (instantConfig === false) { requiresInstantUI = false; createInstantStack = null; } else if (instantConfig && typeof instantConfig === 'object') { requiresInstantUI = true; createInstantStack = localCreateInstantStack; } else { requiresInstantUI = childrenRequireInstantUI; createInstantStack = childCreateInstantStack; } return { seedData: getCacheNodeSeedDataFromSegment(segmentData, slots), requiresInstantUI, createInstantStack }; } const { seedData, requiresInstantUI, createInstantStack } = await buildSharedTreeSeedData(initialLoaderTree, null, null, 0 /* urlDepthConsumed */ , 0 /* groupDepthConsumed */ ); if (!requiresInstantUI) { return null; } const { flightRouterState } = getRootDataFromPayload(initialRSCPayload); const headStage = hasRuntimeSegments ? _stagedrendering.RenderStage.Runtime : _stagedrendering.RenderStage.Static; const head = await createValidationHead(cache, releaseSignal, clientReferenceManifest, stageEndTimes, headStage); const payload = { ...initialRSCPayload, f: [ [ flightRouterState, seedData, head ] ] }; return { payload, hasAmbiguousErrors: hasStaticSegments, createInstantStack }; } //# sourceMappingURL=instant-validation.js.map