Conversation
fcdac58 to
c5d86cc
Compare
e07682c to
af86527
Compare
Stats in progressCommit: af86527 |
Stats from current PR🔴 3 regressions, 1 improvement
📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
Build Cache
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📝 Changed Files (9 files)Files with changes:
View diffsapp-page-exp..ntime.dev.jsfailed to diffapp-page-exp..time.prod.jsDiff too large to display app-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsDiff too large to display app-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsDiff too large to display app-page.runtime.dev.jsfailed to diffapp-page.runtime.prod.jsDiff too large to display server.runtime.prod.jsDiff too large to display 📎 Tarball URLCommit: 37cb5dd |
Tests in progressCommit: af86527 |
a376314 to
ed49b3f
Compare
ed49b3f to
aef873b
Compare
37cb5dd to
1aca829
Compare
Failing test suitesCommit: 9dd593a | About building and testing Next.js
Expand output● param-matching-routing › serves an admitted path through its real handler: /es/docs/space%20here/100%25 ● param-matching-routing › serves an admitted path through its real handler: /open/docs/space%20here/100%25 ● param-matching-routing › handles an expected matcher miss without a cache-generation invariant error ● param-matching-routing › revalidation › revalidates a seeded output without changing route admission: /en/closed/known
Expand output● param-matching-routing › serves an admitted path through its real handler: /es/docs/space%20here/100%25 ● param-matching-routing › serves an admitted path through its real handler: /open/docs/space%20here/100%25 ● param-matching-routing › handles an expected matcher miss without a cache-generation invariant error ● param-matching-routing › revalidation › revalidates a seeded output without changing route admission: /en/closed/known
Expand output● param-matching-routing › serves an admitted path through its real handler: /es/docs/space%20here/100%25 ● param-matching-routing › serves an admitted path through its real handler: /open/docs/space%20here/100%25 ● param-matching-routing › client route discovery › does not poison an admitted open suffix after prefetching a 404: /en/catalog/nav-top/items/nav-bottom ● param-matching-routing › client route discovery › does not reuse an admitted prefix when navigation must be a routing 404
Expand output● param-matching-root-params › keeps unknown roots out of a fallback shell regenerated after invalidation
Expand output● param-matching-routing › serves an admitted path through its real handler: /es/docs/space%20here/100%25 ● param-matching-routing › serves an admitted path through its real handler: /open/docs/space%20here/100%25 ● param-matching-routing › client route discovery › does not poison an admitted open suffix after prefetching a 404: /en/catalog/nav-top/items/nav-bottom ● param-matching-routing › client route discovery › does not reuse an admitted prefix when navigation must be a routing 404
Expand output● param-matching-root-params › keeps unknown roots out of a fallback shell regenerated after invalidation
Expand output● param-matching-routing › serves an admitted path through its real handler: /es/docs/space%20here/100%25 ● param-matching-routing › serves an admitted path through its real handler: /open/docs/space%20here/100%25 ● param-matching-routing › handles an expected matcher miss without a cache-generation invariant error ● param-matching-routing › revalidation › revalidates a seeded output without changing route admission: /en/closed/known
Expand output● param-matching-routing › serves an admitted path through its real handler: /es/docs/space%20here/100%25 ● param-matching-routing › serves an admitted path through its real handler: /open/docs/space%20here/100%25 ● param-matching-routing › handles an expected matcher miss without a cache-generation invariant error ● param-matching-routing › revalidation › revalidates a seeded output without changing route admission: /en/closed/known |
Stats from current PRWarning No stats were collected for Webpack because its stats job did not complete (it failed, was cancelled, or timed out). The results below only cover the bundlers that finished. 🔴 1 regression
📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📝 Changed Files (9 files)Files with changes:
View diffsapp-page-exp..ntime.dev.jsfailed to diffapp-page-exp..time.prod.jsDiff too large to display app-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsDiff too large to display app-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsDiff too large to display app-page.runtime.dev.jsfailed to diffapp-page.runtime.prod.jsDiff too large to display server.runtime.prod.jsDiff too large to display 📎 Tarball URLCommit: 1cad2ab |
1aca829 to
73146ab
Compare
73146ab to
c3175eb
Compare
## Summary
This is the behavior-preserving base of a four-PR stack that introduces
explicit prerender matching policy without coupling the foundational
refactor to the proposed API.
The build currently uses `PrerenderedRoute` values for two related but
distinct concepts:
- a logical request matcher that says which parameterized URL shapes the
route can handle
- a build-time render candidate that may or may not become a persisted
prerender artifact
A candidate is not guaranteed to be an output. It can be rendered only
to validate a shell, discarded, and still leave behind a matcher that
tells future requests to block.
The new relationship is:
```text
logical pathname matcher
-> zero or more render candidates
-> zero or more persisted artifacts
```
## Concrete example
Consider `/[top]/items/[bottom]`:
```ts
export function generateStaticParams() {
return [{ top: 't1', bottom: 'b1' }]
}
```
Static-path generation may consider three shapes:
| Shape | Purpose |
| --- | --- |
| `/[top]/items/[bottom]` | A generic shell candidate and logical
matcher |
| `/t1/items/[bottom]` | A shell after resolving `top` |
| `/t1/items/b1` | A concrete build-time prerender |
Suppose the generic candidate renders an allowed empty shell. The build
should discard that candidate artifact and use blocking behavior for the
generic matcher. It should not remove `/[top]/items/[bottom]` from the
valid matcher set, and it should not discard the concrete `/t1/items/b1`
artifact.
This is why the build needs two sets:
- route matchers, which describe valid request shapes
- prerender candidates, whose render results determine whether an
artifact is retained and can refine inferred fallback behavior
## Variants compatibility
Variants will make pathname-only candidate maps insufficient. Several
variant combinations can share `/t1/items/b1` as their logical pathname
while writing distinct artifacts under variant-specific output paths.
This PR keeps the route matcher keyed by logical pathname but retains
every candidate associated with it. Candidate finalization can therefore
evaluate each variant artifact independently without changing the route
tree's matcher set.
## Behavior preservation
This PR does not add a user-facing API or change `generateStaticParams`
semantics:
- a usable static shell remains a fallback prerender
- an allowed empty shell is discarded and represented by a blocking
matcher
- a route that requires a non-empty shell still fails validation
- unresolved matchers remain gated by route-level PPR support
- the most-specific shell continues to supply first-writer-wins metadata
such as prefetch hints
Render results can decide whether a candidate artifact is published and
can refine inferred matcher behavior, but they do not remove the logical
route matcher itself.
## Stack plan
1. **#97431 — model prerenders as render candidates:** land the
behavior-preserving matcher/candidate separation and post-render
finalization first.
2. **#97393 — add the experimental matcher API:** add `unstable_matcher`
and `unstable_generateMatcher`, policy aggregation, validation, and
local diagnostics.
3. **#97426 — test complex route shapes:** add test-only coverage for
catch-alls, optional catch-alls, root parameters, and parallel slots.
4. **#97427 — test foreground policy behavior:** add test-only coverage
showing blocking misses generate before responding while fallback misses
return the shared shell immediately.
This layering lets the internal model be reviewed and landed
independently of the API design. The upper test PRs validate the final
behavior without increasing the implementation diff.
## Verification
- `pnpm --filter=next types`
- `pnpm test-start-turbo
test/e2e/app-dir/sub-shell-generation/sub-shell-generation.test.ts`
- `pnpm test-start-turbo
test/e2e/app-dir/segment-cache/prefetch-inlining/prefetch-inlining.test.ts`
<!-- NEXT_JS_LLM -->
14a439e to
86f73ed
Compare
A generic fallback shell can have an unresolved root parameter. Reading that root directly already suspends, but reading it inside `use cache` returned the opaque placeholder and could persist placeholder-derived UI in the resume cache. For example, a cached `lang().toUpperCase()` could render `%%DRP:LANG:...%%` for a later French request. Propagate the fallback mask into public caches and abort the cache fill when an unresolved root value is consumed. Share cancellation through nested caches so an outer cache cannot retain the inner placeholder read. Preserve tracked root dependencies while cancellation completes. Add a real Cache Components fixture without paramMatching. Cold fallback debug renders exercise direct and nested cached reads, followed by concrete requests that must not reuse placeholder-derived content. All three tests fail without this fix. Existing concrete-root cache coverage also passes.
Adapter routing forwards a root parameter such as lang as nxtPlang. The servable-fallback branch used the unprefixed name in config.allowQuery, unlike the existing blocking branch. That mismatch can discard the value before the request reaches the function or partitions its cache entry. Prefix the root names consistently. Add a production fixture that runs the real emitter against real build artifacts and a servable-root-fallback manifest input. Current inference emits blocking root entries, so the test supplies that one input explicitly rather than depending on the new paramMatching API. Its expected nxtPlang fails against the old lang output. This changes only Next.js output and requires no adapter implementation change. The contract test is not a live deployment/function-grouping test.
Integrate the updated build-time-generator prerequisite and initialize the matching generator's functionName as experimental_generateParamMatching. This keeps diagnostics tied to the exported API rather than reporting generateStaticParams whenever a generator uses an unavailable operation. For example, calling headers() in experimental_generateParamMatching now reports that function's build-time scope. Root-param errors no longer suggest that matching generators receive concrete values from parent gSP calls, and private-cache and revalidation errors retain the same scope. Add real build-error fixtures covering cookies, headers, connection, draft mode, prefetch, navigation, private caching, revalidation, and root params. The generic store support remains in the prerequisite PR; this layer only supplies the matching API's name and its integration coverage. Quick formatting and lint checks pass. The prerequisite's existing ten gSP integration tests passed. Pushing before the new fixture verification finishes so CI and the remaining local checks can run concurrently.
Correct the two new prefetch/navigation fixtures to use the public module that actually exports unstable_prefetch and unstable_navigation. Importing them from next/server stopped the fixture's TypeScript check before any generator diagnostics could be exercised. This changes only test imports; the framework implementation is unchanged.
Adapter routing forwards a root parameter such as lang as nxtPlang. The servable-fallback branch used the unprefixed name in config.allowQuery, unlike the existing blocking branch. That mismatch can discard the value before the request reaches the function or partitions its cache entry. Prefix the root names consistently. Add a production fixture that runs the real emitter against real build artifacts and a servable-root-fallback manifest input. Current inference emits blocking root entries, so the test supplies that one input explicitly rather than depending on the new paramMatching API. Its expected nxtPlang fails against the old lang output. This changes only Next.js output and requires no adapter implementation change. The contract test is not a live deployment/function-grouping test.
59f762e to
114db84
Compare
Integrate #98950 and the rebased query-key prerequisite into the existing parameter-matching history. Replace shared cache cancellation with independently cancellable fallback-root fills and remove seeded entries only when they depend on roots that are unknown in the target shell. Keep the API patch unchanged relative to its prerequisite branch and preserve its separately removable diagnostic commit. The resulting source tree is byte-identical to the already verified replay: 19 production Webpack checks pass across cached root matching, root-fallback behavior, and adapter query-key output. The new prerequisite separately passes its six production and four development regression cases.
114db84 to
a321933
Compare
…uisite Inherit the root-cache fixture cleanup without changing this layer's query-key behavior. Fresh unknown-root cache fills will be exercised through supported paramMatching requests, not shell-debugging overrides.
Inherit the prerequisite's ordinary-build assertions and remove debug-forced root fallback requests. This preserves the existing API history while separating build-cache reuse from runtime root-fallback revalidation coverage.
Expire tagged shell data through a Route Handler, then request a novel language. A new cached version proves the generic shell was regenerated; nested root reads and a cached component with its own Suspense boundary must remain dynamic holes and resume with the requested language. A second language reuses the regenerated language-independent shell. The fixture uses normal paramMatching configuration, revalidateTag, and document requests, with no shell-debugging settings or forced render overrides. Removing only the fresh-fill handling while retaining RDC pruning makes the regression render an opaque root placeholder instead of the requested language. The complete implementation passes the production fixture.
Keep the nxtP root-query correction in the API layer that makes servable root fallbacks reachable. For a [lang] layout configured as fallback, the adapter output must allow nxtPlang, exactly as the routing rule forwards it. Remove the synthetic manifest-editing fixture and its direct internal-emitter invocation. Strengthen the real paramMatching build fixture to require a servable root fallback and the exact non-empty query key list on its HTML, RSC, and segment outputs. Removing the prefix fix fails this assertion with lang instead of nxtPlang; restoring it passes all eight fixture tests. Merge the latest root-cache prerequisite so the API PR can sit directly on it without rewriting existing history. The separate interception-query investigation is not part of this change. Verification: 11 production Webpack tests, full bootstrap, repository TypeScript checking, and changed-file lint pass.
Specialized prerender matchers execute their original page module. Remove the generated alias page files and deployment-only app-path-routes manifest; function grouping already filters the launcher manifest to the real page entrypoints included in the function. Keep the parentFallbackMode correction: lang=not-found with an open catalog suffix must admit /en/catalog/t2/items/b2 even when only t1/b1 was built. Fully closed pages still retain their build-time allowlist. Extend the existing adapter-output fixture to verify the original manifest is packaged, specialized matcher aliases are absent, and partially closed versus fully closed pages preserve their different parent fallback metadata. Verification: focused production Webpack inheritance, matcher-output, and adapter-contract checks (3 passed); repository TypeScript and targeted lint checks. The preceding comparison also exercised the unchanged Vercel grouper and launcher with grouped and singleton functions, including fallback resume and RSC requests.
Remove the parameter-policy resolver check for combining dynamicParams with experimental parameter matching. Parameter matching requires Cache Components, whose existing segment-config validation already rejects dynamicParams, so there is no supported configuration that reaches this extra check. Remove the unit case that bypassed module validation to exercise the redundant error. The existing cache-components-segment-configs fixture still verifies the real user-facing rejection. Verification: 98 static-paths unit tests and the production Webpack unsupported-config fixture pass.
Derive whether a route configures parameter matching from the optional policy itself instead of carrying a second boolean. An empty policy object remains distinct from an absent export, so opting in without overriding any parameter keeps its existing behavior. Represent the dev-only not-found decision as devParamMatchingRejected. Preserve the reset before each matching attempt and the debug-prerender bypass; normal dev requests still render dynamically, regardless of blocking or fallback policies. Verified with the existing routing and dev shell-validation fixtures (10 tests), a Next.js build, and the repository TypeScript check.
Rename the policy dictionary, resolver, validation helpers, and worker-result fields to paramMatching terminology. For example, resolveParamMatching merges a layout policy of lang: not-found with a page policy of top: blocking; it does not compile the emitted URL matchers. Keep PrerenderRouteMatcher and the matcher diagnostics named for the actual route patterns they describe. The policy module becomes param-matching.ts, and its existing tracing snapshot follows that filename. This is a naming-only cleanup: policy resolution, validation, inference, and runtime behavior are unchanged. Verified 108 unit tests, the existing production parameter-matching fixture (26 tests), dev export and generator fixtures (16 tests), repository typechecking, and six Turbopack tracing tests with five snapshots after a fresh native build.
Give the type fixture an explicit TypeScript project that excludes the test harness while checking generated development and production validators. This keeps ordinary export and invalid-key coverage from failing on missing Jest and harness dependencies in an isolated app. Fix the routing README language warnings, clarify that generator results are shared per route evaluation rather than across the build, and describe closure identity as a normalized URL prefix. Explain which regressions the build-artifact assertions protect without changing matching or shell-validation behavior. Verified with fresh native Turbopack: six type-fixture tests across dev and production, 28 production build-contract tests, 98 matching unit tests, repository TypeScript, and changed-file formatting, ESLint, and language checks.
The new routing fixture incorrectly expected decoded server params. A fresh canary build returns URI-encoded values for both single and catch-all params, and the existing prerender-encoding test explicitly asserts that behavior. Parameter matching does not change the encoding contract. Correct the four expected values and document the baseline, retaining the encoded request URLs, unconfigured controls, repeated requests, and HTTP 200 assertions. All 25 runnable development routing cases now pass. Production passes 27 cases; two percent-sign requests still return 500, and the existing expected-404 logging and fully closed revalidation failures remain visible. No runtime implementation changes or test gates are added.
Summary
Add per-parameter matching directives behind
experimental.paramMatching, with Cache Components enabled.generateStaticParamsremains responsible for concrete build-time prerenders; matching configuration controls how requests with novel parameter values are handled.This lets an application close a prefix to its build-time values, require blocking generation for the next parameter, and serve immediate fallback UI for another. Unconfigured parameters retain inference from the generated shells, and an unconfigured tail without examples remains dynamic.
Stack
The prerequisites are ordered bottom to top:
build-time-generatorand retain the originating function name for diagnostics, without changing existing gSP behavior.The prerequisites can land without committing to this API. The closed-parameter prediction fix #98889 and the earlier dev-validation prerequisites #98511 and #98512 have already merged. Opt-in diagnostic logging remains separately committed and can be removed independently.
The prerequisites remain independently reviewable above #98944. This PR preserves its existing history through integration merges; generic generator diagnostics live in #98891, while this layer supplies the matching API's name and integration coverage. The superseded catch-all array conversion is not reintroduced.
Example
The build prerenders
/en/catalog/t1/items/b1. A novellangreturns 404;/en/catalog/t2/items/b2blocks on generation;/en/catalog/t1/items/b2can receive fallback UI immediately.The generated form,
export async function experimental_generateParamMatching(), returns the same partial object and takes no arguments. It can load matching policy from an external configuration system and runs independently of gSP's per-parent-value enumeration. Each unique module is evaluated once per route evaluation, not once globally per build: a shared layout can run again for another page. Repeated occurrences of the same module within one route's parallel tree share the result. It uses the same build-time work-unit context as gSP: publicuse cachehelpers work, while request-only/private caching reports the normal unsupported-context error. The context explicitly identifiesexperimental_generateParamMatching, so an invalidheaders()call names that export rather than gSP. The same applies to private caching, revalidation, and unavailable root parameters; matching generators are not told to obtain concrete params from parent gSP calls.Ordinary TypeScript object literals work without
as const. For optional strict mode checking, usesatisfies ParamMatchingimported fromnext.ParamMatching<'lang' | 'top'>additionally constrains keys when writing an explicit annotation. Generated types still reject keys outside the module's visible parameters; runtime validation rejects invalid modes and malformed JavaScript or generated exports.Layering and validation
Fragments are assignment-merged from layouts toward each page. Descendants replace only supplied keys. A module may configure only parameters at or above its own segment:
[lang]/layout.tsxcannot configure a latertopparameter.The merged explicit policy must follow
not-found → blocking → fallback → dynamic. Every parameter preceding an explicitnot-foundmust also be explicitlynot-found, directly or through inheritance. Next.js never silently closes an unconfigured prefix or rewrites inherited intent:Omitting
langentirely is also invalid in that example. A configuration on the[lang]layout can supply it to all descendants.Parallel branches sharing a matcher must agree and produce a coherent combined policy in URL-parameter order, independent of route groups. Routes sharing a parameter definition must all explicitly configure/inherit its
not-foundpolicy if any of them does. Explicitly dynamic parameters cannot appear in gSP output or have prerendered parameters beneath them.Only after explicit configuration is validated are holes filled by inference, constrained by the explicit boundaries.
Static shells, hints, and development
An inferred empty shell may result in blocking behavior instead of a servable fallback. Explicit
fallbackrequires a nonempty shell and cannot silently become blocking. Blocking also validates a reachable useful shell; when no example reaches the boundary, the generic shell provides that validation.instant = falseopts out of shell validation, not best-effort hint collection.An explicit fallback moves the required validation to that more generic shell. For example,
top: 'fallback'requires useful UI with bothtopandbottomunknown, even if gSP also suppliest1/b1. Once that shell passes, descendant prerenders do not repeat the empty-shell requirement; making more params known does not add a new unknown-data boundary.Redundant blocking renders are skipped only for API-configured routes when a descendant covers them. Unconfigured routes retain their existing build renders and hint collection. A blocking boundary without an example still gets a best-effort generic render; this does not make that result a servable fallback.
Dev preserves required-or-completed shell selection and adds explicit fallback boundaries to the unknown parameter set. For example, with a
t1/b1prerender andtop: 'fallback', validation treats both parameters as unknown even for/t1/b1. Ordinary dev requests remain dynamic renders. Dev supplies exact closed-parameter names from the effective policy, while production persists them in renderer manifest metadata. The shared transport-tree builder marks only those dynamic nodes. For{ lang: 'not-found', slug: 'fallback' }, only[lang]is marked, even though the generic matcher hasfallback: false;[slug]remains open. Successful document loads, live navigations, and prefetched trees therefore disable optimistic prediction consistently. No dev prerender-manifest entry or new adapter routing directive is needed.Deployment and diagnostics
Closed-prefix output uses the existing fallback-false adapter contract, with specialized matchers admitting the open suffix beneath each generated prefix. The function output keeps its original source-page entrypoint. Synthetic alias entrypoints and the alternate app-path-routes manifest have been removed; no new adapter/proxy contract is introduced. Local output/launcher checks do not replace a real grouped-function deployment check.
Explicit root fallback matching makes a previously unreachable adapter case possible: a servable fallback whose root parameter is still unknown. For
app/[lang]/layout.tsxwithlang: 'fallback', the fallback's query allowlist must containnxtPlang, matching the routing destination, rather than the logical namelang. This correction now lives with the API instead of in #98893. The realparam-matching-root-paramsfixture checks the exact route and non-empty key list for HTML, RSC, and segment outputs, and confirms the HTML output has a servable fallback. The synthetic manifest-editing fixture and direct internal-emitter invocation have been removed.Initially,
output: exportrequires every parameter to be explicitlynot-found. This avoids silently changing matching semantics and leaves room for future client-only fallback support.Diagnostics print effective matching decisions and deployment patterns only when both
experimental.paramMatchingandNEXT_PRIVATE_DEBUG_PARAM_MATCHING=1are enabled.Verification and remaining work
Latest review follow-up is included in
19d60ae82c0and9dd593abb6d. The explicit type-fixture project passes all three checks in both Turbopack dev and production, including rejection of invalid parameter keys. The three build-contract suites pass all 28 production tests; matching unit coverage passes all 98 tests. Repository TypeScript, changed-file ESLint/formatting, and the routing README language check pass. Verification used a full bootstrap with a fresh native Turbopack build. Comments now describe normalized-prefix identity, per-route generator evaluation, and the purpose of build-artifact assertions. Explicit fallback shell validation and removal of synthetic adapter aliases are documented above.Root fallback query-key follow-up: the genuine API fixture now requires a servable
/[lang]fallback, matches its exact routing rule, and requires['nxtPlang']on HTML, RSC, and segment outputs. Temporarily removing only the prefix conversion fails that assertion with['lang']while the seven behavior tests still pass. Restoring it passes all eight fixture tests; the existing blocking-query fixture also passes (11 production Webpack tests combined). Development Webpack also passes (six tests, two production-only skips). Full bootstrap, repository TypeScript checking, and changed-file lint pass. This checks the real build's adapter contract, not a live deployment; the separate intercepted-parameter (nxtI) investigation is deferred.Root-cache coverage now uses ordinary builds and requests only. The prerequisite fixture no longer exposes shell-debugging APIs. A real
revalidateTagrequest in this layer forces a root-fallback shell to regenerate, and checks that cached root-dependent UI remains deferred while independent cached content is refreshed. Both fixtures pass together in production Webpack (11 tests) and development Webpack (seven tests, four build/ISR-only skips). Removing just the fresh-fill handling, while retaining RDC pruning, makes normal root-fallback requests and the revalidation regression return opaque placeholder content; restoring it makes them pass.Generator-name follow-up: all nine new production Webpack diagnostic fixtures pass. The existing matching-generator and gSP-error suites also pass (13 production tests), and the existing matching-generator suite passes in dev (seven tests, one prefetch-only skip). Full bootstrap, repository types, and changed-file lint pass. An initial fixture-only import error was corrected before the successful diagnostic run.
Restack verification on the combined Use structural React keys during server rendering #98944-based stack: full build and repository type check pass, along with 222 focused unit tests (four snapshots), 43 production Webpack tests, and 26 development Webpack tests (nine snapshots). Existing mode-specific skips are unchanged. That run used the native build available at the time. Subsequent simplification verification rebuilt native Turbopack locally and passed the production file-tracing suite (six tests, five snapshots).
Node-local hint coverage passes with both bundlers: eight generator-fixture tests in production, and seven in dev with the prefetch-only case skipped. The mixed closed-prefix/open-suffix fixture verifies only
[lang]is marked, novel slugs still render, novel languages return 404, and the renderer manifest identifies the exact closed subset. With inlining disabled, a prefetched navigation uses no additional requests and still marks only[lang], proving the existing response merge preserves the transport-tree hints. Closed-parameter bits are not duplicated in the build-measuredprefetch-hints.jsontree;createUniformHintTreeremains unchanged from the stack's base. The legacy fixture covers the inlined path and passes all eight production tests with both bundlers. Both fixtures also pass together in dev (12 passed, four prefetch-dependent cases skipped per bundler). The three unchanged Cache Components prediction regressions passed with both production bundlers in the preceding node-local-hint verification.Regression fixtures demonstrate before/after failures for missing closed prefixes, public cached generators, successful dev closure hints, and widened object-literal types. Runtime invalid-mode/key checks and private-cache rejection remain covered.
The six focused production Webpack suites pass (29 tests), covering generators, types, prefix validation, blocking/partial-prefetch behavior, cached root parameters, and parallel route groups. The main production Turbopack API suite passes (26 tests).
The main API and existing
cache-components-dev-fallback-validationsuites pass together in Turbopack development (26 tests, 9 snapshots).Full bootstrap build and repository TypeScript checks pass. Both touched unit suites pass in the broad unit run; that run has three unrelated macOS
/varversus/private/varpath-comparison failures inrunTypeScriptCli.test.ts.The four decoded-value expectations in this PR's new fixture were incorrect. Freshly built canary
34433fd12eereproduces encoded server values without matching configuration, and its existingprerender-encodingtest explicitly expects them. The follow-up corrects those expectations while retaining encoded spaces, literal percent signs, unconfigured controls, and repeated requests; no routing implementation is changed. All 25 runnable dev routing cases pass (six existing production-only skips). Production passes 27 cases and still fails four: the two percent-sign URLs return 500 before the value assertion, expected routing 404s log an internal error, and fully closed-route revalidation fails. Those HTTP/error assertions are unchanged. These remain open issues, not a claim that the API is ready to merge.Actual grouped-function deployment verification is blocked locally because
VERCEL_ADAPTER_TEST_TOKENandVERCEL_ADAPTER_TEST_TEAMare not configured.