vinext 0.1.2 → 0.1.3

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 (199) hide show
  1. package/dist/build/prerender.d.ts +9 -1
  2. package/dist/build/prerender.js +41 -12
  3. package/dist/build/run-prerender.d.ts +10 -2
  4. package/dist/build/run-prerender.js +15 -1
  5. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  6. package/dist/client/app-nav-failure-handler.js +44 -0
  7. package/dist/client/vinext-next-data.d.ts +18 -1
  8. package/dist/client/window-next.d.ts +2 -1
  9. package/dist/client/window-next.js +12 -1
  10. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  11. package/dist/config/config-matchers.js +73 -14
  12. package/dist/config/next-config.d.ts +46 -4
  13. package/dist/config/next-config.js +147 -48
  14. package/dist/deploy.d.ts +30 -11
  15. package/dist/deploy.js +180 -99
  16. package/dist/entries/app-browser-entry.d.ts +9 -3
  17. package/dist/entries/app-browser-entry.js +21 -3
  18. package/dist/entries/app-rsc-entry.d.ts +2 -0
  19. package/dist/entries/app-rsc-entry.js +64 -5
  20. package/dist/entries/app-rsc-manifest.js +2 -0
  21. package/dist/entries/app-ssr-entry.js +1 -1
  22. package/dist/entries/pages-client-entry.js +53 -8
  23. package/dist/entries/pages-server-entry.js +41 -5
  24. package/dist/index.js +200 -62
  25. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  26. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  27. package/dist/plugins/optimize-imports.d.ts +2 -1
  28. package/dist/plugins/optimize-imports.js +11 -9
  29. package/dist/plugins/postcss.js +7 -7
  30. package/dist/plugins/typeof-window.d.ts +14 -0
  31. package/dist/plugins/typeof-window.js +150 -0
  32. package/dist/routing/app-route-graph.d.ts +2 -1
  33. package/dist/routing/app-route-graph.js +44 -14
  34. package/dist/routing/file-matcher.d.ts +10 -1
  35. package/dist/routing/file-matcher.js +22 -1
  36. package/dist/routing/pages-router.js +3 -3
  37. package/dist/routing/utils.d.ts +35 -6
  38. package/dist/routing/utils.js +59 -7
  39. package/dist/server/api-handler.d.ts +6 -1
  40. package/dist/server/api-handler.js +21 -15
  41. package/dist/server/app-browser-action-result.d.ts +19 -6
  42. package/dist/server/app-browser-action-result.js +19 -10
  43. package/dist/server/app-browser-entry.js +167 -90
  44. package/dist/server/app-browser-error.d.ts +10 -6
  45. package/dist/server/app-browser-error.js +43 -8
  46. package/dist/server/app-browser-hydration.d.ts +2 -0
  47. package/dist/server/app-browser-hydration.js +1 -0
  48. package/dist/server/app-browser-navigation-controller.d.ts +4 -2
  49. package/dist/server/app-browser-navigation-controller.js +23 -2
  50. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  51. package/dist/server/app-browser-server-action-navigation.js +9 -0
  52. package/dist/server/app-browser-stream.js +86 -43
  53. package/dist/server/app-elements-wire.d.ts +6 -1
  54. package/dist/server/app-elements-wire.js +14 -4
  55. package/dist/server/app-elements.d.ts +2 -2
  56. package/dist/server/app-elements.js +2 -2
  57. package/dist/server/app-fallback-renderer.d.ts +1 -0
  58. package/dist/server/app-fallback-renderer.js +3 -1
  59. package/dist/server/app-optimistic-routing.js +2 -2
  60. package/dist/server/app-page-boundary-render.d.ts +1 -0
  61. package/dist/server/app-page-boundary-render.js +27 -14
  62. package/dist/server/app-page-cache-render.d.ts +53 -0
  63. package/dist/server/app-page-cache-render.js +91 -0
  64. package/dist/server/app-page-cache.d.ts +16 -2
  65. package/dist/server/app-page-cache.js +62 -1
  66. package/dist/server/app-page-dispatch.d.ts +26 -0
  67. package/dist/server/app-page-dispatch.js +149 -92
  68. package/dist/server/app-page-element-builder.d.ts +1 -0
  69. package/dist/server/app-page-element-builder.js +5 -2
  70. package/dist/server/app-page-execution.d.ts +6 -1
  71. package/dist/server/app-page-execution.js +21 -1
  72. package/dist/server/app-page-probe.d.ts +1 -0
  73. package/dist/server/app-page-probe.js +4 -0
  74. package/dist/server/app-page-render-observation.d.ts +3 -1
  75. package/dist/server/app-page-render-observation.js +17 -1
  76. package/dist/server/app-page-render.d.ts +12 -1
  77. package/dist/server/app-page-render.js +42 -4
  78. package/dist/server/app-page-request.d.ts +2 -0
  79. package/dist/server/app-page-request.js +2 -1
  80. package/dist/server/app-page-route-wiring.d.ts +3 -1
  81. package/dist/server/app-page-route-wiring.js +14 -5
  82. package/dist/server/app-page-stream.d.ts +15 -3
  83. package/dist/server/app-page-stream.js +11 -5
  84. package/dist/server/app-pages-bridge.d.ts +18 -0
  85. package/dist/server/app-pages-bridge.js +22 -5
  86. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  87. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  88. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  89. package/dist/server/app-ppr-fallback-shell.js +8 -1
  90. package/dist/server/app-route-handler-dispatch.js +9 -2
  91. package/dist/server/app-route-handler-policy.d.ts +1 -0
  92. package/dist/server/app-router-entry.js +5 -0
  93. package/dist/server/app-rsc-cache-busting.js +2 -0
  94. package/dist/server/app-rsc-handler.d.ts +25 -0
  95. package/dist/server/app-rsc-handler.js +154 -54
  96. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  97. package/dist/server/app-rsc-route-matching.js +2 -0
  98. package/dist/server/app-segment-config.d.ts +9 -1
  99. package/dist/server/app-segment-config.js +12 -3
  100. package/dist/server/app-server-action-execution.d.ts +1 -0
  101. package/dist/server/app-server-action-execution.js +42 -13
  102. package/dist/server/app-ssr-entry.d.ts +2 -0
  103. package/dist/server/app-ssr-entry.js +83 -10
  104. package/dist/server/cache-control.js +4 -0
  105. package/dist/server/dev-server.d.ts +2 -2
  106. package/dist/server/dev-server.js +244 -51
  107. package/dist/server/hybrid-route-priority.d.ts +22 -0
  108. package/dist/server/hybrid-route-priority.js +33 -0
  109. package/dist/server/image-optimization.d.ts +18 -9
  110. package/dist/server/image-optimization.js +37 -23
  111. package/dist/server/implicit-tags.d.ts +2 -1
  112. package/dist/server/implicit-tags.js +4 -1
  113. package/dist/server/navigation-planner.d.ts +133 -30
  114. package/dist/server/navigation-planner.js +114 -0
  115. package/dist/server/navigation-trace.d.ts +8 -1
  116. package/dist/server/navigation-trace.js +8 -1
  117. package/dist/server/pages-api-route.d.ts +6 -0
  118. package/dist/server/pages-api-route.js +13 -2
  119. package/dist/server/pages-asset-tags.d.ts +2 -1
  120. package/dist/server/pages-asset-tags.js +6 -2
  121. package/dist/server/pages-data-route.d.ts +8 -1
  122. package/dist/server/pages-data-route.js +11 -2
  123. package/dist/server/pages-get-initial-props.d.ts +54 -4
  124. package/dist/server/pages-get-initial-props.js +43 -1
  125. package/dist/server/pages-node-compat.js +2 -2
  126. package/dist/server/pages-page-data.d.ts +11 -2
  127. package/dist/server/pages-page-data.js +204 -33
  128. package/dist/server/pages-page-handler.d.ts +4 -2
  129. package/dist/server/pages-page-handler.js +59 -22
  130. package/dist/server/pages-page-response.d.ts +2 -1
  131. package/dist/server/pages-page-response.js +7 -4
  132. package/dist/server/pages-request-pipeline.d.ts +1 -0
  133. package/dist/server/pages-request-pipeline.js +73 -36
  134. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  135. package/dist/server/pregenerated-concrete-paths.js +2 -19
  136. package/dist/server/prerender-manifest.d.ts +33 -0
  137. package/dist/server/prerender-manifest.js +54 -0
  138. package/dist/server/prerender-route-params.d.ts +1 -2
  139. package/dist/server/prod-server.js +9 -3
  140. package/dist/server/request-pipeline.d.ts +3 -15
  141. package/dist/server/request-pipeline.js +58 -47
  142. package/dist/server/rsc-stream-hints.d.ts +5 -1
  143. package/dist/server/rsc-stream-hints.js +6 -1
  144. package/dist/server/seed-cache.js +10 -18
  145. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  146. package/dist/shims/app-router-scroll-state.js +14 -2
  147. package/dist/shims/app-router-scroll.d.ts +3 -0
  148. package/dist/shims/app-router-scroll.js +28 -18
  149. package/dist/shims/cache-runtime.js +3 -2
  150. package/dist/shims/cache.d.ts +1 -0
  151. package/dist/shims/cache.js +1 -1
  152. package/dist/shims/cdn-cache.d.ts +5 -5
  153. package/dist/shims/dynamic-preload-chunks.js +6 -4
  154. package/dist/shims/error-boundary.d.ts +2 -0
  155. package/dist/shims/error-boundary.js +7 -0
  156. package/dist/shims/error.js +3 -2
  157. package/dist/shims/error.react-server.d.ts +9 -0
  158. package/dist/shims/error.react-server.js +6 -0
  159. package/dist/shims/fetch-cache.d.ts +3 -1
  160. package/dist/shims/fetch-cache.js +45 -20
  161. package/dist/shims/hash-scroll.js +6 -1
  162. package/dist/shims/headers.js +29 -4
  163. package/dist/shims/internal/als-registry.js +28 -1
  164. package/dist/shims/internal/app-route-detection.js +8 -17
  165. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  166. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  167. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  168. package/dist/shims/internal/navigation-untracked.js +55 -0
  169. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  170. package/dist/shims/internal/pages-data-target.js +17 -8
  171. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  172. package/dist/shims/internal/pages-router-accessor.js +13 -0
  173. package/dist/shims/internal/router-context.d.ts +2 -1
  174. package/dist/shims/internal/router-context.js +3 -1
  175. package/dist/shims/link.js +12 -5
  176. package/dist/shims/navigation.d.ts +8 -2
  177. package/dist/shims/navigation.js +61 -31
  178. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  179. package/dist/shims/ppr-fallback-shell.js +28 -7
  180. package/dist/shims/router.d.ts +13 -2
  181. package/dist/shims/router.js +419 -128
  182. package/dist/shims/server.d.ts +16 -1
  183. package/dist/shims/server.js +44 -12
  184. package/dist/shims/unified-request-context.js +1 -0
  185. package/dist/utils/built-asset-url.d.ts +4 -0
  186. package/dist/utils/built-asset-url.js +11 -0
  187. package/dist/utils/commonjs-loader.d.ts +16 -0
  188. package/dist/utils/commonjs-loader.js +100 -0
  189. package/dist/utils/deployment-id.d.ts +8 -0
  190. package/dist/utils/deployment-id.js +22 -0
  191. package/dist/utils/html-limited-bots.d.ts +18 -1
  192. package/dist/utils/html-limited-bots.js +23 -1
  193. package/dist/utils/parse-cookie.d.ts +13 -0
  194. package/dist/utils/parse-cookie.js +52 -0
  195. package/dist/utils/path.d.ts +7 -1
  196. package/dist/utils/path.js +9 -1
  197. package/package.json +2 -2
  198. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  199. package/dist/shims/internal/parse-cookie-header.js +0 -30
@@ -0,0 +1,26 @@
1
+ import { isPprFallbackShellAbortError, preparePprFallbackShellFinalRender, waitForPprFallbackShellCacheReady } from "../shims/ppr-fallback-shell.js";
2
+ import { readAppPageBinaryStream } from "./app-page-execution.js";
3
+ //#region src/server/app-ppr-fallback-shell-render.ts
4
+ async function warmPprFallbackShellCaches(options) {
5
+ let warmupError = null;
6
+ const warmupDrain = readAppPageBinaryStream(options.renderToReadableStream(options.element, {
7
+ signal: options.state.abortController.signal,
8
+ onError(error, requestInfo, errorContext) {
9
+ if (options.state.abortController.signal.aborted || isPprFallbackShellAbortError(error)) return;
10
+ return options.onError(error, requestInfo, errorContext);
11
+ }
12
+ })).catch((error) => {
13
+ if (options.state.abortController.signal.aborted || isPprFallbackShellAbortError(error)) return;
14
+ warmupError = error;
15
+ });
16
+ try {
17
+ await waitForPprFallbackShellCacheReady(options.state);
18
+ } finally {
19
+ options.state.abortController.abort();
20
+ await warmupDrain;
21
+ preparePprFallbackShellFinalRender(options.state);
22
+ }
23
+ if (warmupError) throw warmupError;
24
+ }
25
+ //#endregion
26
+ export { warmPprFallbackShellCaches };
@@ -9,6 +9,18 @@ type AppPprFallbackShell = {
9
9
  pathname: string;
10
10
  params: Record<string, string | string[]>;
11
11
  };
12
+ /**
13
+ * A fallback-shell cache entry as consumed by the dispatch layer.
14
+ * Produced at build time by the PPR prerender and served at request time
15
+ * when the exact cache entry for a dynamic child param is missing.
16
+ */
17
+ type AppPagePprFallbackCacheShell = {
18
+ fallbackParamNames: readonly string[];
19
+ params: Record<string, string | string[]>;
20
+ pathname: string;
21
+ };
22
+ declare function markAppPprDynamicFallbackShellHtml(html: string): string;
23
+ declare function isAppPprDynamicFallbackShellHtml(html: string): boolean;
12
24
  declare function createAppPprFallbackShell(route: AppPprFallbackShellRoute, matchedParams: Record<string, string | string[]>): AppPprFallbackShell | null;
13
25
  declare function createAppPprFallbackShells(route: AppPprFallbackShellRoute, matchedParams: Record<string, string | string[]>): AppPprFallbackShell[];
14
26
  declare function rewriteAppPprFallbackShellHtmlNavigation(options: {
@@ -18,4 +30,4 @@ declare function rewriteAppPprFallbackShellHtmlNavigation(options: {
18
30
  searchParams: URLSearchParams;
19
31
  }): string;
20
32
  //#endregion
21
- export { createAppPprFallbackShell, createAppPprFallbackShells, rewriteAppPprFallbackShellHtmlNavigation };
33
+ export { AppPagePprFallbackCacheShell, createAppPprFallbackShell, createAppPprFallbackShells, isAppPprDynamicFallbackShellHtml, markAppPprDynamicFallbackShellHtml, rewriteAppPprFallbackShellHtmlNavigation };
@@ -1,6 +1,13 @@
1
1
  import { createInlineScriptTag } from "./html.js";
2
2
  import { createNavigationRuntimeRscMetadataScript } from "./app-ssr-stream.js";
3
3
  //#region src/server/app-ppr-fallback-shell.ts
4
+ const PPR_DYNAMIC_FALLBACK_SHELL_MARKER = "<!--vinext-ppr-dynamic-fallback-shell-->";
5
+ function markAppPprDynamicFallbackShellHtml(html) {
6
+ return html + PPR_DYNAMIC_FALLBACK_SHELL_MARKER;
7
+ }
8
+ function isAppPprDynamicFallbackShellHtml(html) {
9
+ return html.includes(PPR_DYNAMIC_FALLBACK_SHELL_MARKER);
10
+ }
4
11
  function routeRootParamNames(route) {
5
12
  return new Set(route.rootParamNames ?? []);
6
13
  }
@@ -79,4 +86,4 @@ function rewriteAppPprFallbackShellHtmlNavigation(options) {
79
86
  return metadataScript + options.html;
80
87
  }
81
88
  //#endregion
82
- export { createAppPprFallbackShell, createAppPprFallbackShells, rewriteAppPprFallbackShellHtmlNavigation };
89
+ export { createAppPprFallbackShell, createAppPprFallbackShells, isAppPprDynamicFallbackShellHtml, markAppPprDynamicFallbackShellHtml, rewriteAppPprFallbackShellHtmlNavigation };
@@ -2,16 +2,17 @@ import { createRequestContext, runWithRequestContext } from "../shims/unified-re
2
2
  import { getRequestExecutionContext } from "../shims/request-context.js";
3
3
  import { reportRequestError } from "./instrumentation.js";
4
4
  import { consumeDynamicUsage, getAndClearPendingCookies, getDraftModeCookieHeader, markDynamicUsage, setHeadersAccessPhase } from "../shims/headers.js";
5
- import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
5
+ import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
6
6
  import { setNavigationContext } from "../shims/navigation.js";
7
7
  import { makeThenableParams } from "../shims/thenable-params.js";
8
+ import { buildPageCacheTags } from "./implicit-tags.js";
8
9
  import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
9
10
  import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
10
11
  import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
11
- import { buildPageCacheTags } from "./implicit-tags.js";
12
12
  import { applyRouteHandlerMiddlewareContext } from "./app-route-handler-response.js";
13
13
  import { executeAppRouteHandler } from "./app-route-handler-execution.js";
14
14
  import { readAppRouteHandlerCacheResponse } from "./app-route-handler-cache.js";
15
+ import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
15
16
  //#region src/server/app-route-handler-dispatch.ts
16
17
  function isAppRouteHandlerFunction(value) {
17
18
  return typeof value === "function";
@@ -32,6 +33,8 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
32
33
  }), async () => {
33
34
  ensureFetchPatch();
34
35
  setCurrentFetchSoftTags(buildRouteHandlerPageCacheTags(options.cleanPathname, [], options.routeSegments));
36
+ setCurrentFetchCacheMode(options.fetchCacheMode);
37
+ setCurrentForceDynamicFetchDefault(options.dynamicConfig === "force-dynamic");
35
38
  await renderFn();
36
39
  });
37
40
  }
@@ -56,6 +59,9 @@ async function dispatchAppRouteHandler(options) {
56
59
  }), options.middlewareContext);
57
60
  }
58
61
  const resolvedHandlerFn = isAppRouteHandlerFunction(handlerFn) ? handlerFn : void 0;
62
+ const fetchCacheMode = resolveAppRouteHandlerFetchCacheMode(handler);
63
+ setCurrentFetchCacheMode(fetchCacheMode);
64
+ setCurrentForceDynamicFetchDefault(handler.dynamic === "force-dynamic");
59
65
  if (revalidateSeconds !== null && shouldReadAppRouteHandlerCache({
60
66
  dynamicConfig: handler.dynamic,
61
67
  handlerFn: resolvedHandlerFn,
@@ -96,6 +102,7 @@ async function dispatchAppRouteHandler(options) {
96
102
  cleanPathname: options.cleanPathname,
97
103
  draftModeSecret: options.draftModeSecret,
98
104
  dynamicConfig: handler.dynamic,
105
+ fetchCacheMode,
99
106
  routePattern: route.pattern,
100
107
  routeSegments: route.routeSegments
101
108
  }, renderFn);
@@ -3,6 +3,7 @@ import { RouteHandlerHttpMethod, RouteHandlerModule } from "./app-route-handler-
3
3
  //#region src/server/app-route-handler-policy.d.ts
4
4
  type AppRouteHandlerModule = {
5
5
  dynamic?: string;
6
+ fetchCache?: unknown;
6
7
  revalidate?: unknown;
7
8
  } & RouteHandlerModule;
8
9
  type AppRouteHandlerFunction = (...args: unknown[]) => unknown;
@@ -1,9 +1,11 @@
1
1
  import "./server-globals.js";
2
2
  import { runWithExecutionContext } from "../shims/request-context.js";
3
+ import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER } from "./headers.js";
3
4
  import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } from "./http-error-responses.js";
4
5
  import { cloneRequestWithHeaders, filterInternalHeaders, isOpenRedirectShaped } from "./request-pipeline.js";
5
6
  import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
6
7
  import { resolveStaticAssetSignal } from "./worker-utils.js";
8
+ import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
7
9
  import rscHandler, { __assetPrefix, __basePath } from "virtual:vinext-rsc-entry";
8
10
  import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
9
11
  //#region src/server/app-router-entry.ts
@@ -23,7 +25,10 @@ async function handleRequest(request, env, ctx) {
23
25
  }
24
26
  if (isNextStaticPath(url.pathname, __workerBasePath, __workerAssetPathPrefix)) return notFoundStaticAssetResponse();
25
27
  {
28
+ const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(request);
26
29
  const filteredHeaders = filterInternalHeaders(request.headers);
30
+ const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParamsPayload);
31
+ if (prerenderRouteParamsHeader !== null) filteredHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
27
32
  request = cloneRequestWithHeaders(request, filteredHeaders);
28
33
  }
29
34
  const handleFn = () => rscHandler(request, ctx);
@@ -1,6 +1,7 @@
1
1
  import { NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER } from "./headers.js";
2
2
  import { fnv1a64 } from "../utils/hash.js";
3
3
  import { parseAppRscRenderMode } from "./app-rsc-render-mode.js";
4
+ import { applyDeploymentIdHeader } from "../utils/deployment-id.js";
4
5
  //#region src/server/app-rsc-cache-busting.ts
5
6
  /**
6
7
  * RSC cache-busting hashes cover the headers that make an RSC payload vary.
@@ -148,6 +149,7 @@ function createRscRequestHeaders(options = {}) {
148
149
  Accept: VINEXT_RSC_CONTENT_TYPE,
149
150
  ["RSC"]: "1"
150
151
  });
152
+ applyDeploymentIdHeader(headers);
151
153
  if (options.interceptionContext !== void 0 && options.interceptionContext !== null) headers.set(VINEXT_INTERCEPTION_CONTEXT_HEADER, options.interceptionContext);
152
154
  if (options.mountedSlotsHeader !== void 0 && options.mountedSlotsHeader !== null) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);
153
155
  if (options.clientReuseManifestHeader !== void 0 && options.clientReuseManifestHeader !== null) headers.set(VINEXT_CLIENT_REUSE_MANIFEST_HEADER, options.clientReuseManifestHeader);
@@ -1,4 +1,5 @@
1
1
  import { NextHeader, NextI18nConfig, NextRedirect, NextRewrite } from "../config/next-config.js";
2
+ import { ImageConfig } from "./image-optimization.js";
2
3
  import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
3
4
  import { RootParams } from "../shims/root-params.js";
4
5
  import { MiddlewareModule } from "./middleware-runtime.js";
@@ -17,6 +18,7 @@ type RootParamNamesMap = Parameters<typeof handleAppPrerenderEndpoint>[1]["rootP
17
18
  type AppRscMiddlewareContext = AppMiddlewareContext;
18
19
  type AppRscHandlerRoute = {
19
20
  isDynamic: boolean;
21
+ params?: readonly string[];
20
22
  page?: unknown;
21
23
  pattern: string;
22
24
  rootParamNames?: readonly string[];
@@ -41,6 +43,17 @@ type DispatchMatchedPageOptions<TRoute> = {
41
43
  middlewareContext: AppRscMiddlewareContext;
42
44
  mountedSlotsHeader: string | null;
43
45
  params: AppPageParams;
46
+ pprFallbackCacheShells?: readonly {
47
+ fallbackParamNames: readonly string[];
48
+ params: AppPageParams;
49
+ pathname: string;
50
+ }[] | null;
51
+ pprFallbackShell?: {
52
+ fallbackParamNames: readonly string[];
53
+ routePattern: string;
54
+ };
55
+ renderedConcreteUrlPaths?: ReadonlySet<string>;
56
+ skipStaticParamsValidation?: boolean;
44
57
  staticParamsValidationParams?: AppPageParams;
45
58
  rootParams?: RootParams;
46
59
  request: Request;
@@ -110,8 +123,17 @@ type RenderNotFoundOptions<TRoute> = {
110
123
  scriptNonce?: string;
111
124
  };
112
125
  type RenderPagesFallbackOptions = {
126
+ allowRscDocumentFallback?: boolean;
127
+ appRouteMatch?: {
128
+ route: {
129
+ isDynamic: boolean;
130
+ pattern: string;
131
+ };
132
+ } | null;
113
133
  isRscRequest: boolean;
134
+ matchKind?: "dynamic" | "static";
114
135
  middlewareContext: AppRscMiddlewareContext;
136
+ pathname?: string;
115
137
  request: Request;
116
138
  url: URL;
117
139
  };
@@ -122,6 +144,7 @@ type NavigationContextValue = {
122
144
  };
123
145
  type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
124
146
  basePath: string;
147
+ cacheComponents?: boolean;
125
148
  clearRequestContext: () => void;
126
149
  configHeaders: NextHeader[];
127
150
  configRedirects: NextRedirect[];
@@ -150,6 +173,8 @@ type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
150
173
  handleProgressiveActionRequest: (options: HandleProgressiveActionRequestOptions) => Promise<Response | ProgressiveActionFormStateResult | null>;
151
174
  handleServerActionRequest: (options: HandleServerActionRequestOptions) => Promise<Response | null>;
152
175
  i18nConfig: NextI18nConfig | null;
176
+ imageConfig?: ImageConfig;
177
+ isDev: boolean;
153
178
  isMiddlewareProxy: boolean;
154
179
  loadPrerenderPagesRoutes?: () => Promise<unknown>;
155
180
  makeThenableParams: MakeThenableParams;
@@ -4,27 +4,31 @@ import { getRequestExecutionContext } from "../shims/request-context.js";
4
4
  import { ACTION_REVALIDATED_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER } from "./headers.js";
5
5
  import { isExternalUrl, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
6
6
  import { notFoundResponse } from "./http-error-responses.js";
7
- import { applyConfigHeadersToResponse, cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute, validateImageUrl } from "./request-pipeline.js";
7
+ import { applyConfigHeadersToResponse, cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute } from "./request-pipeline.js";
8
8
  import { headersContextFromRequest } from "../shims/headers.js";
9
9
  import { ensureFetchPatch, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
10
- import { createRscRedirectLocation, hasRscCacheBustingSearchParam, resolveInvalidRscCacheBustingRequest, stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
10
+ import { mergeRewriteQuery } from "../utils/query.js";
11
+ import { VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, createRscRedirectLocation, hasRscCacheBustingSearchParam, resolveInvalidRscCacheBustingRequest, stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
11
12
  import { getScriptNonceFromHeaderSources } from "./csp.js";
12
13
  import { normalizeDefaultLocalePathname } from "./pages-i18n.js";
13
- import { isImageOptimizationPath } from "./image-optimization.js";
14
+ import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath, resolveDevImageRedirect } from "./image-optimization.js";
14
15
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
15
16
  import "./app-page-response.js";
16
- import { prerenderRouteParamsPayloadMatchesRoute, readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
17
+ import { createAppPprFallbackShells } from "./app-ppr-fallback-shell.js";
18
+ import { matchPrerenderRouteParamsPayload, readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
19
+ import { getRenderedConcreteUrlPathsForRoute } from "./pregenerated-concrete-paths.js";
20
+ import { pickRootParams, setRootParams } from "../shims/root-params.js";
21
+ import { flattenErrorCauses } from "../utils/error-cause.js";
17
22
  import { applyAppMiddleware } from "./app-middleware.js";
18
23
  import { buildPageCacheTags } from "./implicit-tags.js";
19
24
  import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
20
- import { pickRootParams, setRootParams } from "../shims/root-params.js";
21
25
  import { handleAppPrerenderEndpoint } from "./app-prerender-endpoints.js";
22
- import { flattenErrorCauses } from "../utils/error-cause.js";
23
26
  import { finalizeAppRscResponse } from "./app-rsc-response-finalizer.js";
24
27
  import { normalizeRscRequest } from "./app-rsc-request-normalization.js";
25
28
  import { handleMetadataRouteRequest } from "./metadata-route-response.js";
26
29
  import { runWithPrerenderWorkUnit } from "./prerender-work-unit-setup.js";
27
30
  //#region src/server/app-rsc-handler.ts
31
+ const STATIC_METADATA_CONFIG_HEADER_OVERRIDES = new Set(["cache-control"]);
28
32
  function applyMiddlewareContextToResponse(response, middlewareContext) {
29
33
  if (!middlewareContext.headers && middlewareContext.status == null) return response;
30
34
  const headers = new Headers(response.headers);
@@ -38,6 +42,10 @@ function applyMiddlewareContextToResponse(response, middlewareContext) {
38
42
  function hasProperty(value, key) {
39
43
  return key in value;
40
44
  }
45
+ function isEdgeRouteHandler(handler) {
46
+ if (!handler || typeof handler !== "object" || !hasProperty(handler, "runtime")) return false;
47
+ return handler.runtime === "edge" || handler.runtime === "experimental-edge";
48
+ }
41
49
  function isExecutionContextLike(value) {
42
50
  if (!value || typeof value !== "object") return false;
43
51
  return hasProperty(value, "waitUntil") && typeof value.waitUntil === "function";
@@ -56,6 +64,17 @@ async function applyRewrite(options, cleanPathname) {
56
64
  }
57
65
  return rewritten;
58
66
  }
67
+ function requestContextForResolvedUrl(requestContext, resolvedUrl, baseUrl) {
68
+ return {
69
+ cookies: requestContext.cookies,
70
+ headers: requestContext.headers,
71
+ host: requestContext.host,
72
+ query: new URL(resolvedUrl, baseUrl).searchParams
73
+ };
74
+ }
75
+ function pathnameForResolvedUrl(resolvedUrl) {
76
+ return resolvedUrl.split("#", 1)[0].split("?", 1)[0];
77
+ }
59
78
  function applyConfigHeadersToMiddlewareRedirect(response, options) {
60
79
  if (response.status < 300 || response.status >= 400) return response;
61
80
  if (!options.configHeaders.length) return response;
@@ -82,6 +101,13 @@ function requestWithoutRscCacheBustingSearchParam(request) {
82
101
  stripRscCacheBustingSearchParam(url);
83
102
  return cloneRequestWithUrl(request.body ? request.clone() : request, url.toString());
84
103
  }
104
+ function requestWithoutRscSuffix(request) {
105
+ const url = new URL(request.url);
106
+ const pathname = stripRscSuffix(url.pathname);
107
+ if (pathname === url.pathname) return request;
108
+ url.pathname = pathname;
109
+ return cloneRequestWithUrl(request.body ? request.clone() : request, url.toString());
110
+ }
85
111
  async function handleAppRscRequest(options, request, preMiddlewareRequestContext, isDataRequest) {
86
112
  const handlerStart = process.env.NODE_ENV !== "production" ? performance.now() : 0;
87
113
  if (process.env.NODE_ENV !== "production") {
@@ -92,6 +118,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
92
118
  if (normalized instanceof Response) return normalized;
93
119
  const { url, isRscRequest, interceptionContextHeader, mountedSlotsHeader, renderMode, clientReuseManifest } = normalized;
94
120
  let { pathname, cleanPathname } = normalized;
121
+ let resolvedUrl = cleanPathname + url.search;
122
+ const getResolvedSearchParams = () => new URL(resolvedUrl, url).searchParams;
95
123
  const canonicalPathname = cleanPathname;
96
124
  const basePathState = {
97
125
  basePath: options.basePath,
@@ -124,12 +152,14 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
124
152
  request
125
153
  });
126
154
  if (rscCacheBustingRedirect) return rscCacheBustingRedirect;
127
- const userlandRequest = isRscRequest ? requestWithoutRscCacheBustingSearchParam(request) : request;
155
+ const normalizedUserlandRequest = requestWithoutRscSuffix(request);
156
+ const userlandRequest = requestWithoutRscCacheBustingSearchParam(normalizedUserlandRequest);
128
157
  const middlewareContext = {
129
158
  headers: null,
130
159
  requestHeaders: null,
131
160
  status: null
132
161
  };
162
+ let didMiddlewareRewrite = false;
133
163
  if (options.middlewareModule) {
134
164
  const middlewareResult = await applyAppMiddleware({
135
165
  basePath: options.basePath,
@@ -149,30 +179,46 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
149
179
  requestContext: preMiddlewareRequestContext
150
180
  });
151
181
  cleanPathname = middlewareResult.cleanPathname;
182
+ didMiddlewareRewrite = cleanPathname !== normalized.cleanPathname;
152
183
  if (middlewareResult.search !== null) url.search = middlewareResult.search;
184
+ resolvedUrl = cleanPathname + url.search;
153
185
  }
154
186
  const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareContext.headers);
155
187
  const postMiddlewareRequestContext = buildPostMwRequestContext(userlandRequest);
156
- const beforeFilesRewrite = await applyRewrite({
157
- basePathState,
158
- clearRequestContext: options.clearRequestContext,
159
- request: userlandRequest,
160
- requestContext: postMiddlewareRequestContext,
161
- rewrites: options.configRewrites.beforeFiles
162
- }, matchPathname(cleanPathname));
163
- if (beforeFilesRewrite instanceof Response) return beforeFilesRewrite;
164
- if (beforeFilesRewrite) cleanPathname = beforeFilesRewrite;
188
+ for (const rewrite of options.configRewrites.beforeFiles) {
189
+ const beforeFilesRewrite = await applyRewrite({
190
+ basePathState,
191
+ clearRequestContext: options.clearRequestContext,
192
+ request: normalizedUserlandRequest,
193
+ requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
194
+ rewrites: [rewrite]
195
+ }, matchPathname(cleanPathname));
196
+ if (beforeFilesRewrite instanceof Response) return beforeFilesRewrite;
197
+ if (beforeFilesRewrite) {
198
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, beforeFilesRewrite);
199
+ cleanPathname = pathnameForResolvedUrl(resolvedUrl);
200
+ }
201
+ }
165
202
  if (isImageOptimizationPath(cleanPathname)) {
166
- const imageUrlResult = validateImageUrl(url.searchParams.get("url"), request.url);
167
- if (imageUrlResult instanceof Response) return imageUrlResult;
168
- return Response.redirect(new URL(imageUrlResult, url.origin).href, 302);
203
+ const imageRedirect = resolveDevImageRedirect(url, [...options.imageConfig?.deviceSizes ?? DEFAULT_DEVICE_SIZES, ...options.imageConfig?.imageSizes ?? DEFAULT_IMAGE_SIZES], options.imageConfig?.qualities, { isDev: options.isDev });
204
+ if (!imageRedirect) return new Response("Invalid image optimization parameters", { status: 400 });
205
+ return Response.redirect(new URL(imageRedirect, url.origin).href, 302);
169
206
  }
170
207
  const metadataRouteResponse = await handleMetadataRouteRequest({
171
208
  metadataRoutes: options.metadataRoutes,
172
209
  cleanPathname,
173
210
  makeThenableParams: options.makeThenableParams
174
211
  });
175
- if (metadataRouteResponse) return applyMiddlewareContextToResponse(metadataRouteResponse, middlewareContext);
212
+ if (metadataRouteResponse) {
213
+ applyConfigHeadersToResponse(metadataRouteResponse.headers, {
214
+ basePathState,
215
+ configHeaders: options.configHeaders,
216
+ overwriteExisting: STATIC_METADATA_CONFIG_HEADER_OVERRIDES,
217
+ pathname: matchPathname(cleanPathname),
218
+ requestContext: preMiddlewareRequestContext
219
+ });
220
+ return applyMiddlewareContextToResponse(metadataRouteResponse, middlewareContext);
221
+ }
176
222
  const publicFileResponse = resolvePublicFileRoute({
177
223
  cleanPathname,
178
224
  middlewareContext,
@@ -184,10 +230,13 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
184
230
  options.clearRequestContext();
185
231
  return publicFileResponse;
186
232
  }
187
- if (isRscRequest) stripRscCacheBustingSearchParam(url);
233
+ stripRscCacheBustingSearchParam(url);
234
+ const resolved = new URL(resolvedUrl, url);
235
+ stripRscCacheBustingSearchParam(resolved);
236
+ resolvedUrl = resolved.pathname + resolved.search + resolved.hash;
188
237
  options.setNavigationContext({
189
238
  pathname: canonicalPathname,
190
- searchParams: url.searchParams,
239
+ searchParams: getResolvedSearchParams(),
191
240
  params: {}
192
241
  });
193
242
  const preActionMatch = options.matchRoute(cleanPathname);
@@ -216,53 +265,85 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
216
265
  middlewareContext,
217
266
  mountedSlotsHeader,
218
267
  request,
219
- searchParams: url.searchParams
268
+ searchParams: getResolvedSearchParams()
220
269
  });
221
270
  if (serverActionResponse) return serverActionResponse;
222
271
  let match = preActionMatch;
223
- if (!match || match.route.isDynamic) {
272
+ const renderPagesForMatchKind = async (matchKind) => match === null || match.route.isDynamic ? await options.renderPagesFallback?.({
273
+ appRouteMatch: match ?? null,
274
+ allowRscDocumentFallback: didMiddlewareRewrite,
275
+ isRscRequest,
276
+ matchKind,
277
+ middlewareContext,
278
+ pathname: resolvedUrl,
279
+ request,
280
+ url
281
+ }) ?? null : null;
282
+ const staticPagesFallbackResponse = await renderPagesForMatchKind("static");
283
+ if (staticPagesFallbackResponse) {
284
+ options.clearRequestContext();
285
+ return staticPagesFallbackResponse;
286
+ }
287
+ if (!match || match.route.isDynamic) for (const rewrite of options.configRewrites.afterFiles) {
224
288
  const afterFilesRewrite = await applyRewrite({
225
289
  basePathState,
226
290
  clearRequestContext: options.clearRequestContext,
227
- request: userlandRequest,
228
- requestContext: postMiddlewareRequestContext,
229
- rewrites: options.configRewrites.afterFiles
291
+ request: normalizedUserlandRequest,
292
+ requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
293
+ rewrites: [rewrite]
230
294
  }, matchPathname(cleanPathname));
231
295
  if (afterFilesRewrite instanceof Response) return afterFilesRewrite;
232
- if (afterFilesRewrite) {
233
- cleanPathname = afterFilesRewrite;
234
- match = options.matchRoute(cleanPathname);
296
+ if (!afterFilesRewrite) continue;
297
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, afterFilesRewrite);
298
+ cleanPathname = pathnameForResolvedUrl(resolvedUrl);
299
+ match = options.matchRoute(cleanPathname);
300
+ const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
301
+ if (rewrittenStaticPagesResponse) {
302
+ options.clearRequestContext();
303
+ return rewrittenStaticPagesResponse;
304
+ }
305
+ const rewrittenDynamicPagesResponse = await renderPagesForMatchKind("dynamic");
306
+ if (rewrittenDynamicPagesResponse) {
307
+ options.clearRequestContext();
308
+ return rewrittenDynamicPagesResponse;
235
309
  }
310
+ if (match) break;
236
311
  }
237
- if (!match) {
312
+ const dynamicPagesFallbackResponse = await renderPagesForMatchKind("dynamic");
313
+ if (dynamicPagesFallbackResponse) {
314
+ options.clearRequestContext();
315
+ return dynamicPagesFallbackResponse;
316
+ }
317
+ if (!match) for (const rewrite of options.configRewrites.fallback) {
238
318
  const fallbackRewrite = await applyRewrite({
239
319
  basePathState,
240
320
  clearRequestContext: options.clearRequestContext,
241
- request: userlandRequest,
242
- requestContext: postMiddlewareRequestContext,
243
- rewrites: options.configRewrites.fallback
321
+ request: normalizedUserlandRequest,
322
+ requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
323
+ rewrites: [rewrite]
244
324
  }, matchPathname(cleanPathname));
245
325
  if (fallbackRewrite instanceof Response) return fallbackRewrite;
246
- if (fallbackRewrite) {
247
- cleanPathname = fallbackRewrite;
248
- match = options.matchRoute(cleanPathname);
326
+ if (!fallbackRewrite) continue;
327
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
328
+ cleanPathname = pathnameForResolvedUrl(resolvedUrl);
329
+ match = options.matchRoute(cleanPathname);
330
+ const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
331
+ if (rewrittenStaticPagesResponse) {
332
+ options.clearRequestContext();
333
+ return rewrittenStaticPagesResponse;
334
+ }
335
+ const rewrittenDynamicPagesResponse = await renderPagesForMatchKind("dynamic");
336
+ if (rewrittenDynamicPagesResponse) {
337
+ options.clearRequestContext();
338
+ return rewrittenDynamicPagesResponse;
249
339
  }
340
+ if (match) break;
250
341
  }
251
342
  if (!match) {
252
343
  if (process.env.NODE_ENV !== "production" && canonicalPathname === "/favicon.ico") {
253
344
  options.clearRequestContext();
254
345
  return new Response("", { status: 404 });
255
346
  }
256
- const pagesFallbackResponse = await options.renderPagesFallback?.({
257
- isRscRequest,
258
- middlewareContext,
259
- request,
260
- url
261
- });
262
- if (pagesFallbackResponse) {
263
- options.clearRequestContext();
264
- return pagesFallbackResponse;
265
- }
266
347
  const renderedNotFoundResponse = await options.renderNotFound({
267
348
  isRscRequest,
268
349
  middlewareContext,
@@ -278,25 +359,37 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
278
359
  }
279
360
  const { route, params } = match;
280
361
  if (options.ensureRouteLoaded) await options.ensureRouteLoaded(route);
281
- const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(request);
282
- const prerenderRouteParams = prerenderRouteParamsPayloadMatchesRoute(prerenderRouteParamsPayload, route.pattern, params) ? prerenderRouteParamsPayload.params : null;
362
+ const prerenderRouteParamsMatch = matchPrerenderRouteParamsPayload(readTrustedPrerenderRouteParams(request), route.pattern, params);
363
+ const prerenderRouteParams = prerenderRouteParamsMatch?.params ?? null;
364
+ const isPrerenderFallbackShell = prerenderRouteParamsMatch?.kind === "fallback-shell";
283
365
  const renderParams = prerenderRouteParams ?? params;
366
+ const resolvedSearchParams = getResolvedSearchParams();
367
+ const runtimeFallbackShells = options.cacheComponents === true && request.method === "GET" && !isRscRequest && !isPrerenderFallbackShell && route.params ? createAppPprFallbackShells({
368
+ params: route.params,
369
+ pattern: route.pattern,
370
+ rootParamNames: route.rootParamNames
371
+ }, params) : [];
284
372
  options.setNavigationContext({
285
373
  pathname: canonicalPathname,
286
- searchParams: url.searchParams,
374
+ searchParams: resolvedSearchParams,
287
375
  params: renderParams
288
376
  });
289
377
  const rootParams = pickRootParams(renderParams, route.rootParamNames);
290
378
  setRootParams(rootParams);
291
379
  if (route.routeHandler) {
292
380
  setCurrentFetchSoftTags(buildPageCacheTags(cleanPathname, [], [...route.routeSegments], "route"));
381
+ const routeHandlerRequest = isEdgeRouteHandler(route.routeHandler) ? userlandRequest : normalizedUserlandRequest;
382
+ const routeHandlerUrl = new URL(routeHandlerRequest.url);
383
+ const internalRscValues = isEdgeRouteHandler(route.routeHandler) ? [] : routeHandlerUrl.searchParams.getAll(VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM);
384
+ routeHandlerUrl.search = resolvedSearchParams.toString();
385
+ for (const internalRscValue of internalRscValues) routeHandlerUrl.searchParams.append(VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, internalRscValue);
293
386
  return options.dispatchMatchedRouteHandler({
294
387
  cleanPathname,
295
388
  middlewareContext,
296
389
  params: route.isDynamic ? renderParams : null,
297
- request,
390
+ request: new Request(routeHandlerUrl, routeHandlerRequest),
298
391
  route,
299
- searchParams: url.searchParams
392
+ searchParams: resolvedSearchParams
300
393
  });
301
394
  }
302
395
  const pageResponse = await options.dispatchMatchedPage({
@@ -313,12 +406,19 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
313
406
  middlewareContext,
314
407
  mountedSlotsHeader,
315
408
  params: renderParams,
316
- staticParamsValidationParams: prerenderRouteParams === null ? void 0 : params,
409
+ pprFallbackCacheShells: runtimeFallbackShells,
410
+ pprFallbackShell: isPrerenderFallbackShell ? {
411
+ fallbackParamNames: prerenderRouteParamsMatch.fallbackParamNames,
412
+ routePattern: route.pattern
413
+ } : void 0,
414
+ renderedConcreteUrlPaths: getRenderedConcreteUrlPathsForRoute(route.pattern),
415
+ skipStaticParamsValidation: isPrerenderFallbackShell,
416
+ staticParamsValidationParams: prerenderRouteParams === null || isPrerenderFallbackShell ? void 0 : params,
317
417
  rootParams,
318
418
  request,
319
419
  route,
320
420
  scriptNonce,
321
- searchParams: url.searchParams,
421
+ searchParams: resolvedSearchParams,
322
422
  renderMode
323
423
  });
324
424
  if (isProgressiveActionRender) return applyProgressiveActionSideEffects(pageResponse, progressiveActionResult);
@@ -29,6 +29,7 @@ type AppRscInterceptForMatching = {
29
29
  * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/lib/generate-interception-routes-rewrites.ts
30
30
  */
31
31
  sourceMatchPattern?: string;
32
+ sourcePageSegments?: readonly string[];
32
33
  interceptLayouts: readonly unknown[];
33
34
  page: unknown;
34
35
  __pageLoader?: (() => Promise<unknown>) | null;
@@ -41,6 +42,7 @@ type AppRscSlotForMatching = {
41
42
  type AppRscSiblingInterceptForMatching = {
42
43
  targetPattern: string;
43
44
  sourceMatchPattern: string | null;
45
+ sourcePageSegments?: readonly string[];
44
46
  slotId: string | null;
45
47
  interceptLayouts: readonly unknown[];
46
48
  page: unknown;
@@ -63,6 +65,7 @@ type AppRscInterceptLookupEntry = {
63
65
  targetPatternParts: string[];
64
66
  sourceMatchPattern: string | null;
65
67
  sourceMatchPatternParts: string[] | null;
68
+ sourcePageSegments: readonly string[] | null;
66
69
  interceptLayouts: readonly unknown[];
67
70
  page: unknown;
68
71
  __pageLoader?: (() => Promise<unknown>) | null;
@@ -78,6 +78,7 @@ function createInterceptLookup(routes) {
78
78
  targetPatternParts: intercept.targetPattern.split("/").filter(Boolean),
79
79
  sourceMatchPattern,
80
80
  sourceMatchPatternParts,
81
+ sourcePageSegments: intercept.sourcePageSegments ?? null,
81
82
  interceptLayouts: intercept.interceptLayouts,
82
83
  page: intercept.page,
83
84
  __pageLoader: intercept.__pageLoader,
@@ -96,6 +97,7 @@ function createInterceptLookup(routes) {
96
97
  targetPatternParts: intercept.targetPattern.split("/").filter(Boolean),
97
98
  sourceMatchPattern,
98
99
  sourceMatchPatternParts,
100
+ sourcePageSegments: intercept.sourcePageSegments ?? null,
99
101
  interceptLayouts: intercept.interceptLayouts,
100
102
  page: intercept.page,
101
103
  __pageLoader: intercept.__pageLoader,
@@ -33,6 +33,14 @@ type ResolveAppPageSegmentConfigOptions = {
33
33
  */
34
34
  declare function resolveAppPageSegmentConfig(options: ResolveAppPageSegmentConfigOptions): EffectiveAppPageSegmentConfig;
35
35
  declare function resolveAppPageFetchCacheMode(options: ResolveAppPageSegmentConfigOptions): FetchCacheMode | null;
36
+ /**
37
+ * Resolve the `fetchCache` segment config exported by a route handler module.
38
+ *
39
+ * Route handlers have no layout chain, so the module's own export applies
40
+ * directly. Mirrors upstream's app-route module, which copies
41
+ * `userland.fetchCache` into the work store before invoking the handler.
42
+ */
43
+ declare function resolveAppRouteHandlerFetchCacheMode(handler: Pick<AppRouteSegmentConfigModule, "fetchCache">): FetchCacheMode | null;
36
44
  declare function isEdgeRuntime(runtime: string | undefined): boolean;
37
45
  //#endregion
38
- export { isEdgeRuntime, resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig };
46
+ export { isEdgeRuntime, resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig, resolveAppRouteHandlerFetchCacheMode };