vinext 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/README.md +2 -5
  2. package/dist/build/assets-ignore.d.ts +32 -0
  3. package/dist/build/assets-ignore.js +48 -0
  4. package/dist/build/client-build-config.d.ts +33 -1
  5. package/dist/build/client-build-config.js +66 -1
  6. package/dist/check.js +4 -3
  7. package/dist/cli.js +2 -0
  8. package/dist/client/navigation-runtime.d.ts +11 -2
  9. package/dist/client/navigation-runtime.js +1 -1
  10. package/dist/client/vinext-next-data.d.ts +2 -1
  11. package/dist/client/window-next.d.ts +6 -4
  12. package/dist/config/config-matchers.d.ts +31 -5
  13. package/dist/config/config-matchers.js +50 -3
  14. package/dist/config/next-config.d.ts +29 -3
  15. package/dist/config/next-config.js +32 -2
  16. package/dist/deploy.js +47 -304
  17. package/dist/entries/app-rsc-entry.d.ts +8 -2
  18. package/dist/entries/app-rsc-entry.js +61 -5
  19. package/dist/entries/app-rsc-manifest.js +20 -2
  20. package/dist/entries/pages-client-entry.js +1 -1
  21. package/dist/entries/pages-server-entry.js +16 -7
  22. package/dist/index.d.ts +0 -2
  23. package/dist/index.js +233 -280
  24. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  25. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  26. package/dist/plugins/og-assets.js +2 -2
  27. package/dist/plugins/optimize-imports.d.ts +8 -4
  28. package/dist/plugins/optimize-imports.js +16 -12
  29. package/dist/plugins/postcss.js +18 -14
  30. package/dist/plugins/require-context.d.ts +6 -0
  31. package/dist/plugins/require-context.js +184 -0
  32. package/dist/plugins/sass.d.ts +53 -24
  33. package/dist/plugins/sass.js +249 -1
  34. package/dist/plugins/wasm-module-import.d.ts +15 -0
  35. package/dist/plugins/wasm-module-import.js +50 -0
  36. package/dist/routing/app-route-graph.d.ts +35 -2
  37. package/dist/routing/app-route-graph.js +179 -8
  38. package/dist/routing/file-matcher.js +1 -1
  39. package/dist/routing/route-pattern.d.ts +2 -1
  40. package/dist/routing/route-pattern.js +16 -1
  41. package/dist/server/api-handler.js +4 -0
  42. package/dist/server/app-browser-entry.js +155 -215
  43. package/dist/server/app-browser-error.d.ts +4 -1
  44. package/dist/server/app-browser-error.js +7 -1
  45. package/dist/server/app-browser-history-controller.d.ts +104 -0
  46. package/dist/server/app-browser-history-controller.js +210 -0
  47. package/dist/server/app-browser-interception-context.d.ts +2 -1
  48. package/dist/server/app-browser-interception-context.js +15 -2
  49. package/dist/server/app-browser-navigation-controller.d.ts +13 -2
  50. package/dist/server/app-browser-navigation-controller.js +83 -4
  51. package/dist/server/app-browser-popstate.d.ts +12 -3
  52. package/dist/server/app-browser-popstate.js +19 -4
  53. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  54. package/dist/server/app-browser-rsc-redirect.js +30 -8
  55. package/dist/server/app-browser-state.d.ts +3 -0
  56. package/dist/server/app-browser-state.js +10 -10
  57. package/dist/server/app-browser-visible-commit.js +10 -8
  58. package/dist/server/app-fallback-renderer.d.ts +2 -1
  59. package/dist/server/app-fallback-renderer.js +3 -1
  60. package/dist/server/app-history-state.d.ts +45 -1
  61. package/dist/server/app-history-state.js +109 -1
  62. package/dist/server/app-middleware.js +1 -0
  63. package/dist/server/app-optimistic-routing.js +22 -1
  64. package/dist/server/app-page-boundary-render.d.ts +2 -1
  65. package/dist/server/app-page-boundary-render.js +45 -21
  66. package/dist/server/app-page-cache.js +9 -7
  67. package/dist/server/app-page-dispatch.d.ts +14 -0
  68. package/dist/server/app-page-dispatch.js +21 -6
  69. package/dist/server/app-page-element-builder.d.ts +23 -2
  70. package/dist/server/app-page-element-builder.js +58 -17
  71. package/dist/server/app-page-execution.d.ts +1 -1
  72. package/dist/server/app-page-execution.js +32 -17
  73. package/dist/server/app-page-render.d.ts +7 -1
  74. package/dist/server/app-page-render.js +11 -16
  75. package/dist/server/app-page-request.d.ts +9 -6
  76. package/dist/server/app-page-request.js +14 -10
  77. package/dist/server/app-page-response.d.ts +2 -2
  78. package/dist/server/app-page-response.js +2 -2
  79. package/dist/server/app-page-route-wiring.d.ts +3 -1
  80. package/dist/server/app-page-route-wiring.js +10 -8
  81. package/dist/server/app-page-stream.d.ts +37 -7
  82. package/dist/server/app-page-stream.js +36 -6
  83. package/dist/server/app-pages-bridge.d.ts +16 -0
  84. package/dist/server/app-pages-bridge.js +23 -3
  85. package/dist/server/app-route-handler-cache.d.ts +1 -0
  86. package/dist/server/app-route-handler-cache.js +1 -0
  87. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  88. package/dist/server/app-route-handler-dispatch.js +2 -0
  89. package/dist/server/app-route-handler-execution.d.ts +1 -0
  90. package/dist/server/app-route-handler-execution.js +1 -0
  91. package/dist/server/app-route-handler-response.js +11 -10
  92. package/dist/server/app-route-handler-runtime.d.ts +1 -0
  93. package/dist/server/app-route-handler-runtime.js +15 -3
  94. package/dist/server/app-rsc-handler.d.ts +1 -0
  95. package/dist/server/app-rsc-handler.js +5 -4
  96. package/dist/server/app-rsc-response-finalizer.js +1 -1
  97. package/dist/server/app-rsc-route-matching.d.ts +20 -1
  98. package/dist/server/app-rsc-route-matching.js +29 -4
  99. package/dist/server/app-server-action-execution.d.ts +22 -1
  100. package/dist/server/app-server-action-execution.js +73 -12
  101. package/dist/server/app-ssr-entry.d.ts +6 -0
  102. package/dist/server/app-ssr-entry.js +19 -3
  103. package/dist/server/app-ssr-stream.js +9 -1
  104. package/dist/server/dev-lockfile.js +2 -1
  105. package/dist/server/dev-server.d.ts +1 -1
  106. package/dist/server/dev-server.js +97 -43
  107. package/dist/server/headers.d.ts +8 -1
  108. package/dist/server/headers.js +8 -1
  109. package/dist/server/instrumentation-runtime.d.ts +6 -0
  110. package/dist/server/instrumentation-runtime.js +8 -0
  111. package/dist/server/isr-cache.d.ts +37 -1
  112. package/dist/server/isr-cache.js +85 -1
  113. package/dist/server/isr-decision.d.ts +79 -0
  114. package/dist/server/isr-decision.js +70 -0
  115. package/dist/server/metadata-route-response.js +5 -3
  116. package/dist/server/middleware-runtime.d.ts +13 -0
  117. package/dist/server/middleware-runtime.js +11 -7
  118. package/dist/server/middleware.js +1 -0
  119. package/dist/server/navigation-planner.d.ts +62 -1
  120. package/dist/server/navigation-planner.js +193 -3
  121. package/dist/server/navigation-trace.d.ts +12 -2
  122. package/dist/server/navigation-trace.js +11 -1
  123. package/dist/server/normalize-path.d.ts +0 -8
  124. package/dist/server/normalize-path.js +3 -1
  125. package/dist/server/otel-tracer-extension.d.ts +45 -0
  126. package/dist/server/otel-tracer-extension.js +89 -0
  127. package/dist/server/pages-api-route.d.ts +14 -3
  128. package/dist/server/pages-api-route.js +6 -1
  129. package/dist/server/pages-asset-tags.d.ts +15 -4
  130. package/dist/server/pages-asset-tags.js +18 -12
  131. package/dist/server/pages-data-route.js +5 -1
  132. package/dist/server/pages-node-compat.d.ts +5 -11
  133. package/dist/server/pages-node-compat.js +175 -118
  134. package/dist/server/pages-page-data.d.ts +38 -7
  135. package/dist/server/pages-page-data.js +64 -18
  136. package/dist/server/pages-page-handler.d.ts +10 -2
  137. package/dist/server/pages-page-handler.js +49 -20
  138. package/dist/server/pages-page-response.d.ts +55 -2
  139. package/dist/server/pages-page-response.js +74 -6
  140. package/dist/server/pages-readiness.d.ts +36 -0
  141. package/dist/server/pages-readiness.js +21 -0
  142. package/dist/server/pages-request-pipeline.d.ts +113 -0
  143. package/dist/server/pages-request-pipeline.js +230 -0
  144. package/dist/server/pages-revalidate.d.ts +15 -0
  145. package/dist/server/pages-revalidate.js +19 -0
  146. package/dist/server/prod-server.d.ts +45 -3
  147. package/dist/server/prod-server.js +182 -234
  148. package/dist/server/socket-error-backstop.d.ts +19 -1
  149. package/dist/server/socket-error-backstop.js +77 -4
  150. package/dist/shims/app-router-scroll.js +22 -4
  151. package/dist/shims/cache-runtime.js +39 -2
  152. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  153. package/dist/shims/dynamic-preload-chunks.js +77 -0
  154. package/dist/shims/dynamic.d.ts +4 -0
  155. package/dist/shims/dynamic.js +4 -2
  156. package/dist/shims/error-boundary.d.ts +17 -7
  157. package/dist/shims/error-boundary.js +8 -1
  158. package/dist/shims/error.js +37 -11
  159. package/dist/shims/fetch-cache.d.ts +22 -1
  160. package/dist/shims/fetch-cache.js +28 -1
  161. package/dist/shims/hash-scroll.d.ts +1 -0
  162. package/dist/shims/hash-scroll.js +3 -1
  163. package/dist/shims/head.js +6 -1
  164. package/dist/shims/headers.d.ts +16 -2
  165. package/dist/shims/headers.js +37 -1
  166. package/dist/shims/image-config.js +7 -1
  167. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  168. package/dist/shims/internal/app-route-detection.js +10 -6
  169. package/dist/shims/internal/app-router-context.d.ts +5 -0
  170. package/dist/shims/internal/link-status-registry.d.ts +43 -0
  171. package/dist/shims/internal/link-status-registry.js +42 -0
  172. package/dist/shims/internal/route-pattern-for-warning.d.ts +27 -0
  173. package/dist/shims/internal/route-pattern-for-warning.js +40 -0
  174. package/dist/shims/internal/utils.d.ts +1 -0
  175. package/dist/shims/link.js +20 -6
  176. package/dist/shims/metadata.d.ts +6 -2
  177. package/dist/shims/metadata.js +32 -14
  178. package/dist/shims/navigation.d.ts +9 -18
  179. package/dist/shims/navigation.js +96 -23
  180. package/dist/shims/router-state.d.ts +1 -0
  181. package/dist/shims/router-state.js +2 -0
  182. package/dist/shims/router.d.ts +6 -3
  183. package/dist/shims/router.js +156 -22
  184. package/dist/shims/script-nonce-context.d.ts +1 -1
  185. package/dist/shims/script-nonce-context.js +11 -3
  186. package/dist/shims/server.d.ts +17 -1
  187. package/dist/shims/server.js +31 -6
  188. package/dist/shims/slot.js +1 -1
  189. package/dist/shims/unified-request-context.js +1 -0
  190. package/dist/typegen.js +1 -0
  191. package/dist/utils/client-build-manifest.d.ts +8 -1
  192. package/dist/utils/client-build-manifest.js +41 -6
  193. package/dist/utils/client-entry-manifest.d.ts +11 -0
  194. package/dist/utils/client-entry-manifest.js +29 -0
  195. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  196. package/dist/utils/client-runtime-metadata.js +63 -0
  197. package/dist/utils/hash.d.ts +17 -1
  198. package/dist/utils/hash.js +36 -1
  199. package/dist/utils/lazy-chunks.d.ts +27 -1
  200. package/dist/utils/lazy-chunks.js +65 -1
  201. package/dist/utils/manifest-paths.d.ts +20 -2
  202. package/dist/utils/manifest-paths.js +38 -3
  203. package/dist/utils/path.d.ts +2 -1
  204. package/dist/utils/path.js +5 -1
  205. package/package.json +6 -2
@@ -1,10 +1,11 @@
1
1
  import { VINEXT_MOUNTED_SLOTS_HEADER } from "./headers.js";
2
2
  import { setCacheStateHeaders } from "./cache-headers.js";
3
3
  import { encodeCacheTag } from "../utils/encode-cache-tag.js";
4
+ import { applyCdnResponseHeaders } from "./cache-control.js";
5
+ import { decideIsr } from "./isr-decision.js";
4
6
  import { buildAppPageCacheValue } from "./isr-cache.js";
5
7
  import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
6
8
  import { readStreamAsText } from "../utils/text-stream.js";
7
- import { applyCdnResponseHeaders, buildCachedRevalidateCacheControl } from "./cache-control.js";
8
9
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
9
10
  import { applyEdgeRuntimeHeader } from "./app-page-response.js";
10
11
  import { hasCompleteNegativeRequestApiProof } from "./cache-proof.js";
@@ -52,9 +53,6 @@ function buildAppPageCacheTags(pathname, extraTags) {
52
53
  for (const tag of extraTags) if (!tags.includes(tag)) tags.push(tag);
53
54
  return tags.map(encodeCacheTag);
54
55
  }
55
- function buildAppPageCacheControl(cacheState, revalidateSeconds, expireSeconds) {
56
- return buildCachedRevalidateCacheControl(cacheState, revalidateSeconds, expireSeconds);
57
- }
58
56
  function buildAppPageCachedHeaders(options) {
59
57
  const headers = new Headers({
60
58
  "Content-Type": options.contentType,
@@ -87,9 +85,13 @@ function resolveAppPageCacheWritePolicy(options) {
87
85
  }
88
86
  function buildAppPageCachedResponse(cachedValue, options) {
89
87
  const status = options.middlewareStatus ?? (cachedValue.status || 200);
90
- const revalidateSeconds = options.cacheControl?.revalidate ?? options.revalidateSeconds;
91
- const expireSeconds = options.cacheControl === void 0 ? void 0 : options.cacheControl.expire ?? options.expireSeconds;
92
- const cacheControl = buildAppPageCacheControl(options.cacheState, revalidateSeconds, expireSeconds);
88
+ const { cacheControl } = decideIsr({
89
+ cacheState: options.cacheState,
90
+ kind: "app-page",
91
+ revalidateSeconds: options.revalidateSeconds,
92
+ expireSeconds: options.expireSeconds,
93
+ cacheControlMeta: options.cacheControl
94
+ });
93
95
  if (options.isRscRequest) {
94
96
  if (!cachedValue.rscData) return null;
95
97
  const rscHeaders = buildAppPageCachedHeaders({
@@ -51,6 +51,12 @@ type AppPageModule = {
51
51
  dynamic?: unknown;
52
52
  revalidate?: unknown;
53
53
  };
54
+ type AppPageDispatchSlot = {
55
+ default?: AppPageModule | null;
56
+ page?: AppPageModule | null;
57
+ slotPatternParts?: readonly string[] | null;
58
+ slotParamNames?: readonly string[] | null;
59
+ };
54
60
  type AppPageDispatchRoute = {
55
61
  __buildTimeClassifications?: LayoutClassificationOptions["buildTimeClassifications"];
56
62
  __buildTimeReasons?: LayoutClassificationOptions["buildTimeReasons"];
@@ -67,6 +73,7 @@ type AppPageDispatchRoute = {
67
73
  params: readonly string[];
68
74
  pattern: string;
69
75
  routeSegments: readonly string[];
76
+ slots?: Readonly<Record<string, AppPageDispatchSlot>>;
70
77
  unauthorized?: AppPageModule | null;
71
78
  unauthorizeds?: readonly (AppPageModule | null | undefined)[];
72
79
  };
@@ -78,9 +85,16 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
78
85
  * SSR head. Undefined or empty disables emission entirely.
79
86
  */
80
87
  clientTraceMetadata?: readonly string[];
88
+ /**
89
+ * Maximum total length (in characters) of the preload `Link` header emitted
90
+ * during SSR. `0` disables emission. From `reactMaxHeadersLength` in
91
+ * `next.config`. Undefined falls back to the React default downstream.
92
+ */
93
+ reactMaxHeadersLength?: number;
81
94
  buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker) => Promise<AppPageElement>;
82
95
  clientReuseManifest?: ClientReuseManifestParseResult;
83
96
  cleanPathname: string;
97
+ displayPathname?: string;
84
98
  clearRequestContext: () => void;
85
99
  createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;
86
100
  debugClassification?: (layoutId: string, reason: ClassificationReason) => void;
@@ -18,9 +18,10 @@ import { resolveAppPageParentHttpAccessBoundary, resolveAppPageParentHttpAccessB
18
18
  import { isAppSsrRenderResult } from "./app-page-stream.js";
19
19
  import { createAppLayoutParamAccessTracker, isAppLayoutObservationUnsafeForStaticReuse } from "./app-layout-param-observation.js";
20
20
  import { resolveAppPageMethodResponse } from "./app-page-method.js";
21
+ import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
22
+ import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
21
23
  import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
22
24
  import { renderAppPageLifecycle } from "./app-page-render.js";
23
- import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
24
25
  import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
25
26
  import { buildPageCacheTags } from "./implicit-tags.js";
26
27
  import React from "react";
@@ -124,7 +125,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
124
125
  ensureFetchPatch();
125
126
  setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], options.routeSegments));
126
127
  options.setNavigationContext({
127
- pathname: options.cleanPathname,
128
+ pathname: options.displayPathname ?? options.cleanPathname,
128
129
  searchParams: new URLSearchParams(),
129
130
  params: options.params
130
131
  });
@@ -183,10 +184,11 @@ async function dispatchAppPageInner(options) {
183
184
  routeKind: "page",
184
185
  routePattern: route.pattern
185
186
  }));
187
+ const staticNavigationParams = resolveAppPageNavigationParams(route, options.params, options.cleanPathname, null);
186
188
  options.setNavigationContext({
187
- pathname: options.cleanPathname,
189
+ pathname: options.displayPathname ?? options.cleanPathname,
188
190
  searchParams: new URLSearchParams(),
189
- params: options.params
191
+ params: staticNavigationParams
190
192
  });
191
193
  }
192
194
  if (shouldReadAppPageCache({
@@ -217,7 +219,7 @@ async function dispatchAppPageInner(options) {
217
219
  expireSeconds: options.expireSeconds,
218
220
  revalidateSeconds: currentRevalidateSeconds ?? 0,
219
221
  renderFreshPageForCache: async () => {
220
- const revalidationTarget = resolveAppPageInterceptionRerenderTarget({
222
+ const revalidationTarget = await resolveAppPageInterceptionRerenderTarget({
221
223
  cleanPathname: options.cleanPathname,
222
224
  currentParams: options.params,
223
225
  currentRoute: route,
@@ -233,9 +235,11 @@ async function dispatchAppPageInner(options) {
233
235
  return toInterceptOptions(options.interceptionContext, intercept);
234
236
  }
235
237
  });
238
+ revalidationTarget.navigationParams = resolveAppPageNavigationParams(revalidationTarget.route, revalidationTarget.navigationParams, options.cleanPathname, revalidationTarget.interceptOpts);
236
239
  await options.ensureRouteLoaded?.(revalidationTarget.route);
237
240
  return runAppPageRevalidationContext({
238
241
  cleanPathname: options.cleanPathname,
242
+ displayPathname: options.displayPathname,
239
243
  currentFetchCacheMode: options.resolveRouteFetchCacheMode?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? options.fetchCache ?? null : null),
240
244
  draftModeSecret: options.draftModeSecret,
241
245
  dynamicConfig,
@@ -256,6 +260,7 @@ async function dispatchAppPageInner(options) {
256
260
  }, {
257
261
  basePath: options.basePath,
258
262
  clientTraceMetadata: options.clientTraceMetadata,
263
+ reactMaxHeadersLength: options.reactMaxHeadersLength,
259
264
  rootParams: options.rootParams,
260
265
  waitForAllReady: true,
261
266
  ...revalidatedRscCapture.sideStream ? {
@@ -351,6 +356,9 @@ async function dispatchAppPageInner(options) {
351
356
  },
352
357
  isRscRequest: options.isRscRequest,
353
358
  layoutParamAccess,
359
+ resolveNavigationParams(sourceRoute, navigationParams, pathname, interceptOpts) {
360
+ return resolveAppPageNavigationParams(sourceRoute, navigationParams, pathname, interceptOpts);
361
+ },
354
362
  renderInterceptResponse(sourceRoute, interceptElement) {
355
363
  const interceptOnError = options.createRscOnErrorHandler(options.cleanPathname, sourceRoute.pattern);
356
364
  const interceptStream = options.renderToReadableStream(interceptElement, { onError: interceptOnError });
@@ -386,10 +394,17 @@ async function dispatchAppPageInner(options) {
386
394
  resolveSpecialError: resolveAppPageSpecialError
387
395
  });
388
396
  if (pageBuildResult.response) return pageBuildResult.response;
397
+ const navigationParams = resolveAppPageNavigationParams(route, options.params, options.cleanPathname, interceptResult.interceptOpts);
398
+ options.setNavigationContext({
399
+ pathname: options.displayPathname ?? options.cleanPathname,
400
+ searchParams: options.searchParams,
401
+ params: navigationParams
402
+ });
389
403
  const layoutClassifications = getEffectiveLayoutClassifications(route, options.debugClassification);
390
404
  return renderAppPageLifecycle({
391
405
  basePath: options.basePath,
392
406
  clientTraceMetadata: options.clientTraceMetadata,
407
+ reactMaxHeadersLength: options.reactMaxHeadersLength,
393
408
  cleanPathname: options.cleanPathname,
394
409
  clearRequestContext: options.clearRequestContext,
395
410
  consumeDynamicUsage,
@@ -440,6 +455,7 @@ async function dispatchAppPageInner(options) {
440
455
  layoutCount: route.layouts.length,
441
456
  loadSsrHandler: options.loadSsrHandler,
442
457
  middlewareContext: options.middlewareContext,
458
+ navigationParams,
443
459
  params: options.params,
444
460
  layoutParamAccess,
445
461
  rootParams: options.rootParams,
@@ -493,7 +509,6 @@ async function dispatchAppPageInner(options) {
493
509
  return renderPageSpecialError(options, specialError);
494
510
  },
495
511
  renderToReadableStream: options.renderToReadableStream,
496
- routeHasLocalBoundary: Boolean(route.error?.default || route.errors?.some((errorModule) => errorModule?.default)),
497
512
  routePattern: route.pattern,
498
513
  runWithSuppressedHookWarning(probe) {
499
514
  return options.runWithSuppressedHookWarning(probe);
@@ -37,6 +37,7 @@ type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TEr
37
37
  route: AppPageBuildRoute<TModule, TErrorModule>;
38
38
  params: AppPageParams;
39
39
  routePath: string;
40
+ displayPathname?: string;
40
41
  pageRequest: AppPagePageRequest<TModule>; /** Root-level global-error.tsx module. Present when the app defines this file. */
41
42
  globalErrorModule?: TErrorModule | null; /** Root-level not-found.tsx module. Present when the app defines this file. */
42
43
  rootNotFoundModule?: TModule | null; /** Root-level forbidden.tsx module. Present when the app defines this file. */
@@ -48,9 +49,28 @@ type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TEr
48
49
  * Configured next.config `basePath`. Threaded through `resolveAppPageHead`
49
50
  * so file-based metadata route URLs emitted in <head> are prefixed.
50
51
  */
51
- basePath?: string; /** Serialized next.config `htmlLimitedBots` regexp source. */
52
+ basePath?: string; /** Configured next.config `trailingSlash`, threaded into canonical URL rendering. */
53
+ trailingSlash?: boolean; /** Serialized next.config `htmlLimitedBots` regexp source. */
52
54
  htmlLimitedBots?: string;
53
55
  };
56
+ type AppPageNavigationParamModule = {
57
+ default?: unknown;
58
+ };
59
+ type AppPageNavigationParamSlot = {
60
+ default?: AppPageNavigationParamModule | null;
61
+ page?: AppPageNavigationParamModule | null;
62
+ slotPatternParts?: readonly string[] | null;
63
+ slotParamNames?: readonly string[] | null;
64
+ };
65
+ type AppPageNavigationParamRoute = {
66
+ params?: readonly string[] | null;
67
+ slots?: Readonly<Record<string, AppPageNavigationParamSlot>> | null;
68
+ };
69
+ type AppPageNavigationParamInterceptOptions = {
70
+ interceptPage?: unknown;
71
+ interceptParams?: AppPageParams | null;
72
+ interceptSlotKey?: string | null;
73
+ };
54
74
  /**
55
75
  * Build the App Router element tree for a matched route.
56
76
  *
@@ -68,5 +88,6 @@ type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TEr
68
88
  * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.
69
89
  */
70
90
  declare function buildPageElements<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements>;
91
+ declare function resolveAppPageNavigationParams(route: AppPageNavigationParamRoute, routeParams: AppPageParams, routePath: string, opts?: AppPageNavigationParamInterceptOptions | null): AppPageParams;
71
92
  //#endregion
72
- export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements };
93
+ export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements, resolveAppPageNavigationParams };
@@ -8,6 +8,7 @@ import { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from "./app-
8
8
  import { makeObservedAppPageSearchParamsThenable } from "./app-page-search-params-observation.js";
9
9
  import { buildAppPageElements, createAppPageTreePath } from "./app-page-route-wiring.js";
10
10
  import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
11
+ import "./app-rsc-route-matching.js";
11
12
  import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
12
13
  import { createElement } from "react";
13
14
  //#region src/server/app-page-element-builder.ts
@@ -28,18 +29,21 @@ import { createElement } from "react";
28
29
  * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.
29
30
  */
30
31
  async function buildPageElements(options) {
31
- const { route, params, routePath, pageRequest, globalErrorModule, rootNotFoundModule, rootForbiddenModule, rootUnauthorizedModule, metadataRoutes } = options;
32
+ const { route, params, routePath, displayPathname = routePath, pageRequest, globalErrorModule, rootNotFoundModule, rootForbiddenModule, rootUnauthorizedModule, metadataRoutes } = options;
32
33
  const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION } = pageRequest;
33
34
  const pageModule = route.page;
34
- const PageComponent = pageModule?.default;
35
+ const isSiblingIntercept = opts?.interceptSlotKey === "__vinext_page_intercept" && !!opts?.interceptPage;
36
+ const effectivePageModule = isSiblingIntercept ? opts.interceptPage : pageModule;
37
+ const EffectivePageComponent = effectivePageModule?.default;
38
+ const effectiveParams = isSiblingIntercept ? opts.interceptParams ?? params : params;
35
39
  const hasPageModule = !!pageModule;
36
40
  const renderIdentity = createAppPageRenderIdentity({
37
- displayPathname: routePath,
41
+ displayPathname,
38
42
  interceptionContext: opts?.interceptionContext ?? null,
39
43
  interceptSourceMatchedUrl: opts?.interceptSourceMatchedUrl ?? null,
40
- interceptSlotId: opts?.interceptSlotId ?? null
44
+ interceptSlotId: isSiblingIntercept ? null : opts?.interceptSlotId ?? null
41
45
  });
42
- if (hasPageModule && !PageComponent) {
46
+ if ((hasPageModule || isSiblingIntercept) && !EffectivePageComponent) {
43
47
  let noExportRootLayout = null;
44
48
  const noExportLayoutIds = route.ids?.layouts ?? route.layouts.map((_, index) => AppElementsWire.encodeLayoutId(createAppPageTreePath(route.routeSegments, route.layoutTreePositions?.[index] ?? 0)));
45
49
  if (route.layouts?.length > 0) {
@@ -62,7 +66,7 @@ async function buildPageElements(options) {
62
66
  layoutModules: route.layouts,
63
67
  layoutTreePositions: route.layoutTreePositions,
64
68
  metadataRoutes,
65
- pageModule: route.page ?? null,
69
+ pageModule: effectivePageModule ?? null,
66
70
  parallelRoutes: resolveActiveParallelRouteHeadInputs({
67
71
  interceptLayouts: opts?.interceptLayouts ?? null,
68
72
  interceptPage: opts?.interceptPage ?? null,
@@ -72,12 +76,12 @@ async function buildPageElements(options) {
72
76
  routeSegments: route.routeSegments ?? [],
73
77
  slots: route.slots ?? null
74
78
  }),
75
- params,
79
+ params: effectiveParams,
76
80
  routePath: route.pattern,
77
81
  routeSegments: route.routeSegments ?? null,
78
82
  searchParams
79
83
  });
80
- const pageProps = { params: makeThenableParams(params) };
84
+ const pageProps = { params: makeThenableParams(effectiveParams) };
81
85
  let pageSearchParamsThenable;
82
86
  if (searchParams) {
83
87
  pageSearchParamsThenable = !shouldSuppressLoadingBoundaries(renderMode) && Boolean(route.loading?.default) ? makeObservedAppPageSearchParamsThenable(pageSearchParams) : makeThenableParams(pageSearchParams);
@@ -86,8 +90,16 @@ async function buildPageElements(options) {
86
90
  const mountedSlotIds = mountedSlotsHeader ? new Set(mountedSlotsHeader.split(" ")) : null;
87
91
  const slotOverrides = buildSlotOverrides(route, params, routePath, opts);
88
92
  const metadataPlacement = hasDynamicMetadata && shouldServeStreamingMetadata(pageRequest.request.headers.get("user-agent") ?? "", options.htmlLimitedBots) ? "body" : "head";
93
+ let siblingInterceptElement = isSiblingIntercept && EffectivePageComponent ? createElement(EffectivePageComponent, pageProps) : null;
94
+ if (isSiblingIntercept && siblingInterceptElement !== null && opts?.interceptLayouts?.length) {
95
+ const siblingThenableParams = makeThenableParams(effectiveParams);
96
+ for (let i = opts.interceptLayouts.length - 1; i >= 0; i--) {
97
+ const LayoutComponent = opts.interceptLayouts[i]?.default;
98
+ if (LayoutComponent) siblingInterceptElement = createElement(LayoutComponent, { params: siblingThenableParams }, siblingInterceptElement);
99
+ }
100
+ }
89
101
  return buildAppPageElements({
90
- element: PageComponent ? createElement(PageComponent, pageProps) : null,
102
+ element: isSiblingIntercept ? siblingInterceptElement : EffectivePageComponent ? createElement(EffectivePageComponent, pageProps) : null,
91
103
  globalErrorModule: globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE,
92
104
  isRscRequest,
93
105
  layoutParamAccess: options.layoutParamAccess,
@@ -106,7 +118,8 @@ async function buildPageElements(options) {
106
118
  route,
107
119
  searchParams: pageSearchParamsThenable,
108
120
  slotOverrides,
109
- renderMode
121
+ renderMode,
122
+ trailingSlash: options.trailingSlash
110
123
  });
111
124
  }
112
125
  /**
@@ -125,11 +138,23 @@ async function buildPageElements(options) {
125
138
  */
126
139
  function buildSlotOverrides(route, routeParams, routePath, opts) {
127
140
  const overrides = {};
128
- if (opts && opts.interceptSlotKey && opts.interceptPage) overrides[opts.interceptSlotKey] = {
141
+ if (opts && opts.interceptSlotKey && opts.interceptPage && opts.interceptSlotKey !== "__vinext_page_intercept") overrides[opts.interceptSlotKey] = {
129
142
  layoutModules: opts.interceptLayouts || null,
130
143
  pageModule: opts.interceptPage,
131
144
  params: opts.interceptParams || routeParams
132
145
  };
146
+ const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
147
+ for (const [slotKey, params] of Object.entries(slotParamOverrides ?? {})) {
148
+ const existing = overrides[slotKey];
149
+ overrides[slotKey] = existing ? {
150
+ ...existing,
151
+ params
152
+ } : { params };
153
+ }
154
+ return Object.keys(overrides).length > 0 ? overrides : null;
155
+ }
156
+ function resolveSlotParamOverrides(route, routePath) {
157
+ const overrides = {};
133
158
  const slots = route.slots;
134
159
  if (slots) {
135
160
  let urlParts = null;
@@ -142,19 +167,35 @@ function buildSlotOverrides(route, routeParams, routePath, opts) {
142
167
  if (urlParts === null) urlParts = routePath.split("/").filter(Boolean);
143
168
  const matched = matchRoutePattern(urlParts, patternParts);
144
169
  if (!matched) continue;
145
- const existing = overrides[slotKey];
146
- overrides[slotKey] = existing ? {
147
- ...existing,
148
- params: matched
149
- } : { params: matched };
170
+ overrides[slotKey] = matched;
150
171
  }
151
172
  }
152
173
  return Object.keys(overrides).length > 0 ? overrides : null;
153
174
  }
175
+ function mergeAppPageParams(target, source) {
176
+ for (const [key, value] of Object.entries(source)) target[key] = value;
177
+ }
178
+ function isDefaultExportModule(module) {
179
+ return typeof module === "object" && module !== null;
180
+ }
181
+ function hasDefaultExport(module) {
182
+ if (!isDefaultExportModule(module)) return false;
183
+ return module?.default !== null && module?.default !== void 0;
184
+ }
185
+ function resolveAppPageNavigationParams(route, routeParams, routePath, opts) {
186
+ const navigationParams = { ...routeParams };
187
+ const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
188
+ for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {
189
+ const isInterceptedSlot = opts?.interceptSlotKey === slotKey && opts.interceptSlotKey !== "__vinext_page_intercept" && hasDefaultExport(opts.interceptPage);
190
+ if (!isInterceptedSlot && !hasDefaultExport(slot.page) && !hasDefaultExport(slot.default)) continue;
191
+ mergeAppPageParams(navigationParams, isInterceptedSlot ? opts?.interceptParams ?? routeParams : slotParamOverrides?.[slotKey] ?? routeParams);
192
+ }
193
+ return navigationParams;
194
+ }
154
195
  function collectParamNameSet(params) {
155
196
  const set = /* @__PURE__ */ new Set();
156
197
  if (params) for (const name of params) set.add(name);
157
198
  return set;
158
199
  }
159
200
  //#endregion
160
- export { buildPageElements };
201
+ export { buildPageElements, resolveAppPageNavigationParams };
@@ -103,7 +103,7 @@ type LayoutClassificationOptions = {
103
103
  * unsafe even if the older dynamic scope did not report dynamic usage.
104
104
  */
105
105
  isLayoutObservationDynamic?: (layoutId: string) => boolean; /** Runs a function with isolated dynamic usage tracking per layout. */
106
- runWithIsolatedDynamicScope: <T>(fn: () => T) => Promise<{
106
+ runWithIsolatedDynamicScope: <T>(fn: () => T | Promise<T>) => Promise<{
107
107
  result: T;
108
108
  dynamicDetected: boolean;
109
109
  }>;
@@ -1,5 +1,6 @@
1
1
  import { addBasePathToPathname } from "../utils/base-path.js";
2
2
  import { VINEXT_RSC_REDIRECT_HEADER } from "./headers.js";
3
+ import { runWithConnectionProbe } from "../shims/headers.js";
3
4
  import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, createRscRedirectLocation } from "./app-rsc-cache-busting.js";
4
5
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
5
6
  import { applyEdgeRuntimeHeader } from "./app-page-response.js";
@@ -180,10 +181,15 @@ async function buildAppPageSpecialErrorResponse(options) {
180
181
  }
181
182
  if (options.renderFallbackPage) {
182
183
  const fallbackResponse = await options.renderFallbackPage(options.specialError.statusCode);
183
- if (fallbackResponse) return mergeAppPageSpecialErrorHeaders(fallbackResponse, options.middlewareContext);
184
+ if (fallbackResponse) return mergeAppPageSpecialErrorHeaders(options.specialError.fromMetadata === true && options.serveStreamingMetadata !== false ? new Response(fallbackResponse.body, {
185
+ headers: fallbackResponse.headers,
186
+ status: 200,
187
+ statusText: fallbackResponse.statusText
188
+ }) : fallbackResponse, options.middlewareContext);
184
189
  }
185
190
  options.clearRequestContext();
186
- return mergeAppPageSpecialErrorHeaders(new Response(getAppPageStatusText(options.specialError.statusCode), { status: options.specialError.statusCode }), options.middlewareContext);
191
+ const responseStatus = options.specialError.fromMetadata === true && options.serveStreamingMetadata !== false ? 200 : options.specialError.statusCode;
192
+ return mergeAppPageSpecialErrorHeaders(new Response(getAppPageStatusText(options.specialError.statusCode), { status: responseStatus }), options.middlewareContext);
187
193
  }
188
194
  /** See `LayoutFlags` type docblock in app-elements.ts for lifecycle. */
189
195
  async function probeAppPageLayouts(options) {
@@ -210,7 +216,10 @@ async function probeAppPageLayouts(options) {
210
216
  if (cls) {
211
217
  const layoutId = cls.getLayoutId(layoutIndex);
212
218
  try {
213
- const { dynamicDetected } = await cls.runWithIsolatedDynamicScope(() => options.probeLayoutAt(layoutIndex));
219
+ const { dynamicDetected } = await cls.runWithIsolatedDynamicScope(async () => {
220
+ const outcome = await runWithConnectionProbe(() => options.probeLayoutAt(layoutIndex));
221
+ return outcome.completed ? outcome.result : null;
222
+ });
214
223
  const observationDynamic = cls.isLayoutObservationDynamic?.(layoutId) === true;
215
224
  const layoutDynamic = dynamicDetected || observationDynamic;
216
225
  layoutFlags[layoutId] = layoutDynamic ? "d" : "s";
@@ -239,25 +248,31 @@ async function probeAppPageLayouts(options) {
239
248
  };
240
249
  }
241
250
  async function probeLayoutForErrors(options, layoutIndex) {
242
- try {
243
- const layoutResult = options.probeLayoutAt(layoutIndex);
244
- if (isPromiseLike(layoutResult)) await layoutResult;
245
- } catch (error) {
246
- return options.onLayoutError(error, layoutIndex);
247
- }
248
- return null;
249
- }
250
- async function probeAppPageComponent(options) {
251
- return options.runWithSuppressedHookWarning(async () => {
251
+ const outcome = await runWithConnectionProbe(async () => {
252
252
  try {
253
- const pageResult = options.probePage();
254
- if (isPromiseLike(pageResult)) if (options.awaitAsyncResult) await pageResult;
255
- else Promise.resolve(pageResult).catch(() => {});
253
+ const layoutResult = options.probeLayoutAt(layoutIndex);
254
+ if (isPromiseLike(layoutResult)) await layoutResult;
256
255
  } catch (error) {
257
- return options.onError(error);
256
+ return options.onLayoutError(error, layoutIndex);
258
257
  }
259
258
  return null;
260
259
  });
260
+ return outcome.completed ? outcome.result : null;
261
+ }
262
+ async function probeAppPageComponent(options) {
263
+ return options.runWithSuppressedHookWarning(async () => {
264
+ const outcome = await runWithConnectionProbe(async () => {
265
+ try {
266
+ const pageResult = options.probePage();
267
+ if (isPromiseLike(pageResult)) if (options.awaitAsyncResult) await pageResult;
268
+ else Promise.resolve(pageResult).catch(() => {});
269
+ } catch (error) {
270
+ return options.onError(error);
271
+ }
272
+ return null;
273
+ });
274
+ return outcome.completed ? outcome.result : null;
275
+ });
261
276
  }
262
277
  async function readAppPageBinaryStream(stream) {
263
278
  const reader = stream.getReader();
@@ -28,6 +28,12 @@ type RenderAppPageLifecycleOptions = {
28
28
  * Undefined or empty disables emission.
29
29
  */
30
30
  clientTraceMetadata?: readonly string[];
31
+ /**
32
+ * Maximum total length (in characters) of the preload `Link` header emitted
33
+ * during SSR. `0` disables emission. From `reactMaxHeadersLength` in
34
+ * `next.config`.
35
+ */
36
+ reactMaxHeadersLength?: number;
31
37
  cleanPathname: string;
32
38
  clearRequestContext: () => void;
33
39
  consumeDynamicUsage: () => boolean;
@@ -62,6 +68,7 @@ type RenderAppPageLifecycleOptions = {
62
68
  layoutCount: number;
63
69
  loadSsrHandler: () => Promise<AppPageSsrHandler>;
64
70
  middlewareContext: AppPageMiddlewareContext;
71
+ navigationParams: Record<string, unknown>;
65
72
  params: Record<string, unknown>;
66
73
  rootParams?: RootParams;
67
74
  peekRenderObservationState?: () => AppPageRenderObservationState;
@@ -76,7 +83,6 @@ type RenderAppPageLifecycleOptions = {
76
83
  renderToReadableStream: (element: ReactNode | AppOutgoingElements, options: {
77
84
  onError: AppPageBoundaryOnError;
78
85
  }) => ReadableStream<Uint8Array>;
79
- routeHasLocalBoundary: boolean;
80
86
  routePattern: string;
81
87
  runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;
82
88
  scriptNonce?: string;
@@ -1,8 +1,8 @@
1
+ import { NO_STORE_CACHE_CONTROL } from "./cache-control.js";
1
2
  import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
2
3
  import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
3
4
  import "./app-elements.js";
4
5
  import { runWithFetchDedupe } from "../shims/fetch-cache.js";
5
- import { NO_STORE_CACHE_CONTROL } from "./cache-control.js";
6
6
  import { buildAppPageHtmlResponse, buildAppPageRscResponse, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy } from "./app-page-response.js";
7
7
  import { buildAppPageFontLinkHeader, readAppPageBinaryStream, resolveAppPageSpecialError, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
8
8
  import { probeAppPageBeforeRender } from "./app-page-probe.js";
@@ -10,7 +10,7 @@ import { DEFAULT_CACHE_VARIANT_BUDGET, buildCacheVariantWithRouteBudget, buildRe
10
10
  import { createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope, createEmptyAppPageRenderObservationState } from "./app-page-render-observation.js";
11
11
  import { finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse } from "./app-page-cache.js";
12
12
  import { createStaticLayoutClientReuseArtifactCompatibility, createStaticLayoutClientReusePayloadHash, createStaticLayoutClientReuseRouteId } from "./static-layout-client-reuse-proof.js";
13
- import { createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery, shouldRerenderAppPageWithGlobalError } from "./app-page-stream.js";
13
+ import { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery } from "./app-page-stream.js";
14
14
  import { getStaticLayoutObservationSkipRejection } from "./app-layout-param-observation.js";
15
15
  import { hasDigest } from "./app-rsc-errors.js";
16
16
  import { createClientReuseSkipTransportPlan, crossCheckClientReuseManifestEntryWithCache } from "./skip-cache-proof.js";
@@ -293,7 +293,7 @@ async function renderAppPageLifecycle(options) {
293
293
  cleanPathname: options.cleanPathname,
294
294
  completeness: "partial",
295
295
  output: rscOutputScope,
296
- params: options.params,
296
+ params: options.navigationParams,
297
297
  state: options.peekRenderObservationState?.() ?? createEmptyAppPageRenderObservationState()
298
298
  });
299
299
  const skipDisposition = options.skipDisposition ?? createRenderLifecycleSkipDisposition({
@@ -349,7 +349,7 @@ async function renderAppPageLifecycle(options) {
349
349
  isEdgeRuntime: options.isEdgeRuntime,
350
350
  middlewareContext: options.middlewareContext,
351
351
  mountedSlotsHeader: options.mountedSlotsHeader,
352
- params: options.params,
352
+ params: options.navigationParams,
353
353
  policy: rscResponsePolicy,
354
354
  timing: buildResponseTiming({
355
355
  compileEnd,
@@ -371,7 +371,7 @@ async function renderAppPageLifecycle(options) {
371
371
  cleanPathname: options.cleanPathname,
372
372
  completeness: "complete",
373
373
  output: rscOutputScope,
374
- params: options.params,
374
+ params: options.navigationParams,
375
375
  state: input.state
376
376
  });
377
377
  },
@@ -418,6 +418,7 @@ async function renderAppPageLifecycle(options) {
418
418
  navigationContext: options.getNavigationContext(),
419
419
  basePath: options.basePath,
420
420
  clientTraceMetadata: options.clientTraceMetadata,
421
+ reactMaxHeadersLength: options.reactMaxHeadersLength,
421
422
  rootParams: options.rootParams,
422
423
  formState: options.formState ?? null,
423
424
  rscStream: rscForResponse,
@@ -435,6 +436,7 @@ async function renderAppPageLifecycle(options) {
435
436
  if (htmlRender.response) return htmlRender.response;
436
437
  let htmlStream = htmlRender.htmlStream;
437
438
  if (!htmlStream) throw new Error("[vinext] Expected an HTML stream when no fallback response was returned");
439
+ const linkHeader = buildAppPageLinkHeader(htmlRender.linkHeader, fontLinkHeader, options.reactMaxHeadersLength);
438
440
  if (options.isPrerender === true) await htmlRender.metadataReady;
439
441
  if (options.hasLoadingBoundary) {
440
442
  const captured = rscErrorTracker.getCapturedSpecialError();
@@ -446,13 +448,6 @@ async function renderAppPageLifecycle(options) {
446
448
  }
447
449
  }
448
450
  }
449
- if (shouldRerenderAppPageWithGlobalError({
450
- capturedError: rscErrorTracker.getCapturedError(),
451
- hasLocalBoundary: options.routeHasLocalBoundary
452
- })) {
453
- const cleanResponse = await options.renderErrorBoundaryResponse(rscErrorTracker.getCapturedError());
454
- if (cleanResponse) return cleanResponse;
455
- }
456
451
  if (options.isPrerender === true) {
457
452
  await settleCapturedRscRenderForCacheMetadata(htmlRender.capturedRscData);
458
453
  ({expireSeconds, revalidateSeconds} = applyRequestCacheLife({
@@ -491,7 +486,7 @@ async function renderAppPageLifecycle(options) {
491
486
  if (htmlResponsePolicy.shouldWriteToCache || shouldSpeculativelyWriteCache) {
492
487
  const isrResponse = buildAppPageHtmlResponse(safeHtmlStream, {
493
488
  draftCookie,
494
- fontLinkHeader,
489
+ linkHeader,
495
490
  isEdgeRuntime: options.isEdgeRuntime,
496
491
  middlewareContext: options.middlewareContext,
497
492
  policy: htmlResponsePolicy,
@@ -514,7 +509,7 @@ async function renderAppPageLifecycle(options) {
514
509
  cleanPathname: options.cleanPathname,
515
510
  completeness: "complete",
516
511
  output: htmlOutputScope,
517
- params: options.params,
512
+ params: options.navigationParams,
518
513
  state: input.state
519
514
  });
520
515
  },
@@ -526,7 +521,7 @@ async function renderAppPageLifecycle(options) {
526
521
  cleanPathname: options.cleanPathname,
527
522
  completeness: "complete",
528
523
  output: rscOutputScope,
529
- params: options.params,
524
+ params: options.navigationParams,
530
525
  state: input.state
531
526
  });
532
527
  },
@@ -551,7 +546,7 @@ async function renderAppPageLifecycle(options) {
551
546
  }
552
547
  return buildAppPageHtmlResponse(safeHtmlStream, {
553
548
  draftCookie,
554
- fontLinkHeader,
549
+ linkHeader,
555
550
  isEdgeRuntime: options.isEdgeRuntime,
556
551
  middlewareContext: options.middlewareContext,
557
552
  policy: htmlResponsePolicy,