mirror of
https://github.com/hanzoai/next.js.git
synced 2026-10-30 14:46:38 +00:00
When a validation boundary spans multiple parallel slots, errors were previously attributed to whichever unstable_instant config was found first during tree iteration — which varied between turbopack and webpack. This made the "Caused by: Instant Validation" source non-deterministic and sometimes pointed to the wrong slot's config. This adds a SlotMarker client component that wraps each slot's content at fork points (where parallel routes > 1). The marker's dynamically-named inner function appears in the SSR component stack, allowing resolveInstantStack to identify which slot an error belongs to and look up that slot's config. When a slot has no config, it falls back to slotStacks[0] (the root config). The root config is now selected by config depth preference rather than first-found. configDepth tracks how many URL-consuming segments deep a config was found, with deeper configs preferred as more specific. At equal depth, the children slot is preferred over named slots. This ensures deterministic attribution regardless of bundler iteration order. Key changes: - SlotMarker component in boundary-impl.tsx takes a name prop and lazily creates named inner functions cached by name - slotStacks array replaces the singleton createInstantStack on InstantValidationState (index 0 = root config, 1+ = per-slot) - configDepth on TreeResult only counts URL-consuming segments — synthetic segments like (__SLOT__), __PAGE__, and route groups don't contribute - resolveInstantStack parses component stacks for slot markers and maps to the correct config - wrapSlotsWithMarkers called at every fork in both buildSharedTreeSeedData and buildNewTreeSeedData
23 lines
702 B
TypeScript
23 lines
702 B
TypeScript
import { cookies } from 'next/headers'
|
|
import { ReactNode } from 'react'
|
|
|
|
// This layout calls cookies() without Suspense and has no instant
|
|
// config. It sits above a deeper layout with runtime prefetch config.
|
|
// From the developer's perspective, they configured runtime prefetching
|
|
// deeper in the tree, so cookies() should be fine. But this layout
|
|
// gets static prefetching by default (since the config is below it),
|
|
// making the cookies() call a blocking violation.
|
|
export default async function StaticLayout({
|
|
children,
|
|
}: {
|
|
children: ReactNode
|
|
}) {
|
|
await cookies()
|
|
return (
|
|
<div>
|
|
<em>Static layout above runtime config (calls cookies)</em>
|
|
{children}
|
|
</div>
|
|
)
|
|
}
|