vinext 0.1.7 → 0.2.0

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 (279) hide show
  1. package/README.md +51 -30
  2. package/dist/build/inject-pregenerated-paths.d.ts +4 -0
  3. package/dist/build/inject-pregenerated-paths.js +18 -0
  4. package/dist/build/layout-classification.js +1 -1
  5. package/dist/build/nitro-route-rules.js +1 -1
  6. package/dist/build/pages-client-assets-module.d.ts +11 -0
  7. package/dist/build/pages-client-assets-module.js +27 -0
  8. package/dist/build/prerender.d.ts +2 -1
  9. package/dist/build/prerender.js +13 -6
  10. package/dist/build/report.d.ts +13 -2
  11. package/dist/build/report.js +99 -2
  12. package/dist/build/run-prerender.d.ts +7 -0
  13. package/dist/build/run-prerender.js +10 -1
  14. package/dist/build/standalone.js +2 -0
  15. package/dist/cache/cache-adapters-virtual.js +3 -3
  16. package/dist/check.d.ts +18 -0
  17. package/dist/check.js +77 -19
  18. package/dist/cli-args.d.ts +1 -2
  19. package/dist/cli-args.js +1 -1
  20. package/dist/cli-dev-config.d.ts +12 -0
  21. package/dist/cli-dev-config.js +23 -0
  22. package/dist/cli.js +113 -97
  23. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  24. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  25. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  26. package/dist/{server → client}/dev-error-overlay.js +2 -2
  27. package/dist/client/navigation-runtime.d.ts +2 -0
  28. package/dist/client/navigation-runtime.js +3 -1
  29. package/dist/client/window-next.d.ts +2 -1
  30. package/dist/cloudflare/index.d.ts +2 -2
  31. package/dist/cloudflare/index.js +2 -2
  32. package/dist/config/config-matchers.js +14 -10
  33. package/dist/config/next-config.d.ts +6 -3
  34. package/dist/config/next-config.js +47 -1
  35. package/dist/config/prerender.d.ts +34 -0
  36. package/dist/config/prerender.js +55 -0
  37. package/dist/config/server-external-packages.d.ts +4 -0
  38. package/dist/config/server-external-packages.js +91 -0
  39. package/dist/entries/app-rsc-entry.d.ts +2 -1
  40. package/dist/entries/app-rsc-entry.js +89 -15
  41. package/dist/entries/app-rsc-manifest.js +10 -0
  42. package/dist/entries/pages-client-entry.d.ts +3 -0
  43. package/dist/entries/pages-client-entry.js +16 -1
  44. package/dist/entries/pages-server-entry.js +6 -2
  45. package/dist/image/image-adapters-virtual.d.ts +59 -0
  46. package/dist/image/image-adapters-virtual.js +59 -0
  47. package/dist/index.d.ts +33 -0
  48. package/dist/index.js +211 -118
  49. package/dist/init-cloudflare.d.ts +43 -0
  50. package/dist/init-cloudflare.js +839 -0
  51. package/dist/init-platform.d.ts +40 -0
  52. package/dist/init-platform.js +195 -0
  53. package/dist/init.d.ts +16 -38
  54. package/dist/init.js +208 -97
  55. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  56. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  57. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  58. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  59. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
  60. package/dist/packages/cloudflare/src/deploy-config.js +150 -0
  61. package/dist/packages/cloudflare/src/deploy-help.js +55 -0
  62. package/dist/packages/cloudflare/src/deploy.js +276 -0
  63. package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
  64. package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +18 -15
  65. package/dist/plugins/ast-scope.d.ts +16 -0
  66. package/dist/plugins/ast-scope.js +62 -0
  67. package/dist/plugins/ast-utils.d.ts +27 -1
  68. package/dist/plugins/ast-utils.js +32 -1
  69. package/dist/plugins/css-module-imports.d.ts +14 -0
  70. package/dist/plugins/css-module-imports.js +59 -0
  71. package/dist/plugins/extensionless-dynamic-import.js +2 -2
  72. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  73. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  74. package/dist/plugins/middleware-server-only.d.ts +8 -6
  75. package/dist/plugins/middleware-server-only.js +8 -7
  76. package/dist/plugins/optimize-imports.js +1 -1
  77. package/dist/plugins/typeof-window.d.ts +1 -1
  78. package/dist/plugins/typeof-window.js +28 -56
  79. package/dist/routing/app-route-graph.d.ts +29 -4
  80. package/dist/routing/app-route-graph.js +182 -40
  81. package/dist/routing/app-router.d.ts +5 -0
  82. package/dist/routing/app-router.js +5 -0
  83. package/dist/routing/file-matcher.d.ts +8 -0
  84. package/dist/routing/file-matcher.js +10 -1
  85. package/dist/routing/pages-router.js +2 -2
  86. package/dist/server/api-handler.js +9 -14
  87. package/dist/server/app-browser-action-result.d.ts +4 -1
  88. package/dist/server/app-browser-action-result.js +8 -1
  89. package/dist/server/app-browser-entry.js +194 -190
  90. package/dist/server/app-browser-history-controller.d.ts +2 -1
  91. package/dist/server/app-browser-history-controller.js +6 -2
  92. package/dist/server/app-browser-interception-context.d.ts +1 -0
  93. package/dist/server/app-browser-interception-context.js +4 -2
  94. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  95. package/dist/server/app-browser-navigation-controller.js +60 -31
  96. package/dist/server/app-browser-server-action-client.d.ts +32 -0
  97. package/dist/server/app-browser-server-action-client.js +127 -0
  98. package/dist/server/app-browser-state.d.ts +11 -1
  99. package/dist/server/app-browser-state.js +25 -8
  100. package/dist/server/app-browser-visible-commit.d.ts +6 -1
  101. package/dist/server/app-browser-visible-commit.js +43 -25
  102. package/dist/server/app-elements-wire.d.ts +9 -2
  103. package/dist/server/app-elements-wire.js +8 -1
  104. package/dist/server/app-elements.d.ts +2 -2
  105. package/dist/server/app-elements.js +4 -3
  106. package/dist/server/app-fallback-renderer.d.ts +5 -2
  107. package/dist/server/app-fallback-renderer.js +15 -7
  108. package/dist/server/app-hydration-cache-publication.d.ts +11 -0
  109. package/dist/server/app-hydration-cache-publication.js +43 -0
  110. package/dist/server/app-middleware.d.ts +4 -3
  111. package/dist/server/app-middleware.js +8 -3
  112. package/dist/server/app-optimistic-routing.js +11 -4
  113. package/dist/server/app-page-boundary-render.d.ts +3 -0
  114. package/dist/server/app-page-boundary-render.js +14 -3
  115. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  116. package/dist/server/app-page-cache-finalizer.js +10 -3
  117. package/dist/server/app-page-cache-render.d.ts +1 -0
  118. package/dist/server/app-page-cache-render.js +8 -4
  119. package/dist/server/app-page-cache.d.ts +1 -0
  120. package/dist/server/app-page-cache.js +5 -2
  121. package/dist/server/app-page-dispatch.d.ts +33 -4
  122. package/dist/server/app-page-dispatch.js +63 -90
  123. package/dist/server/app-page-element-builder.d.ts +9 -2
  124. package/dist/server/app-page-element-builder.js +114 -23
  125. package/dist/server/app-page-head.d.ts +16 -1
  126. package/dist/server/app-page-head.js +44 -22
  127. package/dist/server/app-page-params.d.ts +2 -1
  128. package/dist/server/app-page-params.js +8 -1
  129. package/dist/server/app-page-ppr-runtime.d.ts +7 -0
  130. package/dist/server/app-page-ppr-runtime.js +70 -0
  131. package/dist/server/app-page-probe.d.ts +1 -0
  132. package/dist/server/app-page-probe.js +6 -1
  133. package/dist/server/app-page-render-identity.d.ts +1 -0
  134. package/dist/server/app-page-render-identity.js +1 -1
  135. package/dist/server/app-page-render.d.ts +4 -1
  136. package/dist/server/app-page-render.js +26 -3
  137. package/dist/server/app-page-request.d.ts +22 -1
  138. package/dist/server/app-page-request.js +92 -15
  139. package/dist/server/app-page-route-wiring.d.ts +14 -2
  140. package/dist/server/app-page-route-wiring.js +61 -25
  141. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  142. package/dist/server/app-page-search-params-observation.js +11 -7
  143. package/dist/server/app-page-segment-state.d.ts +2 -1
  144. package/dist/server/app-page-segment-state.js +3 -1
  145. package/dist/server/app-page-stream.d.ts +5 -0
  146. package/dist/server/app-page-stream.js +3 -1
  147. package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
  148. package/dist/server/app-route-handler-dispatch.js +1 -0
  149. package/dist/server/app-route-handler-execution.js +7 -2
  150. package/dist/server/app-route-handler-response.js +1 -0
  151. package/dist/server/app-route-handler-runtime.js +1 -1
  152. package/dist/server/app-route-module-loader.d.ts +2 -0
  153. package/dist/server/app-route-module-loader.js +1 -0
  154. package/dist/server/app-router-entry.js +16 -8
  155. package/dist/server/app-rsc-errors.js +7 -1
  156. package/dist/server/app-rsc-handler.d.ts +3 -1
  157. package/dist/server/app-rsc-handler.js +67 -39
  158. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  159. package/dist/server/app-rsc-request-normalization.js +6 -3
  160. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  161. package/dist/server/app-rsc-route-matching.js +36 -3
  162. package/dist/server/app-segment-config.d.ts +12 -0
  163. package/dist/server/app-segment-config.js +91 -5
  164. package/dist/server/app-server-action-execution.d.ts +5 -0
  165. package/dist/server/app-server-action-execution.js +94 -33
  166. package/dist/server/app-ssr-entry.d.ts +3 -0
  167. package/dist/server/app-ssr-entry.js +19 -8
  168. package/dist/server/app-ssr-stream.d.ts +7 -3
  169. package/dist/server/app-ssr-stream.js +10 -6
  170. package/dist/server/app-static-generation.d.ts +1 -0
  171. package/dist/server/app-static-generation.js +1 -0
  172. package/dist/server/app-visited-response-cache.d.ts +6 -0
  173. package/dist/server/app-visited-response-cache.js +3 -1
  174. package/dist/server/client-trace-metadata.js +26 -0
  175. package/dist/server/default-global-not-found-module.d.ts +14 -0
  176. package/dist/server/default-global-not-found-module.js +14 -0
  177. package/dist/server/dev-route-files.js +4 -0
  178. package/dist/server/dev-server.js +19 -18
  179. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  180. package/dist/server/dev-stack-sourcemap.js +1 -1
  181. package/dist/server/fetch-handler.d.ts +2 -0
  182. package/dist/server/fetch-handler.js +18 -0
  183. package/dist/server/headers.d.ts +5 -15
  184. package/dist/server/headers.js +4 -15
  185. package/dist/server/image-optimization.d.ts +51 -1
  186. package/dist/server/image-optimization.js +52 -2
  187. package/dist/server/implicit-tags.js +1 -1
  188. package/dist/server/isr-cache.d.ts +1 -1
  189. package/dist/server/isr-cache.js +2 -2
  190. package/dist/server/metadata-routes.d.ts +3 -1
  191. package/dist/server/metadata-routes.js +12 -2
  192. package/dist/server/middleware-runtime.js +6 -1
  193. package/dist/server/navigation-planner.d.ts +1 -0
  194. package/dist/server/navigation-planner.js +14 -3
  195. package/dist/server/pages-api-route.js +2 -2
  196. package/dist/server/pages-asset-tags.d.ts +4 -6
  197. package/dist/server/pages-asset-tags.js +12 -12
  198. package/dist/server/pages-client-assets.d.ts +12 -0
  199. package/dist/server/pages-client-assets.js +10 -0
  200. package/dist/server/pages-node-compat.d.ts +8 -1
  201. package/dist/server/pages-node-compat.js +32 -4
  202. package/dist/server/pages-page-data.d.ts +24 -1
  203. package/dist/server/pages-page-data.js +45 -24
  204. package/dist/server/pages-page-handler.d.ts +2 -1
  205. package/dist/server/pages-page-handler.js +19 -12
  206. package/dist/server/pages-page-response.d.ts +7 -0
  207. package/dist/server/pages-page-response.js +4 -1
  208. package/dist/server/pages-request-pipeline.d.ts +2 -0
  209. package/dist/server/pages-request-pipeline.js +25 -1
  210. package/dist/server/pages-router-entry.d.ts +30 -0
  211. package/dist/server/pages-router-entry.js +108 -0
  212. package/dist/server/prerender-manifest.d.ts +3 -1
  213. package/dist/server/prerender-route-params.js +1 -1
  214. package/dist/server/prod-server.d.ts +1 -1
  215. package/dist/server/prod-server.js +48 -26
  216. package/dist/server/request-pipeline.js +1 -0
  217. package/dist/server/seed-cache.js +4 -4
  218. package/dist/server/worker-utils.d.ts +2 -1
  219. package/dist/server/worker-utils.js +7 -1
  220. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  221. package/dist/shims/app-router-scroll-state.js +1 -0
  222. package/dist/shims/app-router-scroll.js +2 -1
  223. package/dist/shims/cache.js +19 -15
  224. package/dist/shims/cdn-cache.js +1 -1
  225. package/dist/shims/dynamic-preload-chunks.js +2 -1
  226. package/dist/shims/error-boundary.d.ts +19 -1
  227. package/dist/shims/error-boundary.js +11 -1
  228. package/dist/shims/form.d.ts +3 -1
  229. package/dist/shims/form.js +37 -43
  230. package/dist/shims/headers.d.ts +9 -1
  231. package/dist/shims/headers.js +31 -6
  232. package/dist/shims/image.js +75 -14
  233. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  234. package/dist/shims/internal/app-route-detection.js +4 -17
  235. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  236. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  237. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -15
  238. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  239. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +9 -5
  240. package/dist/shims/internal/pages-data-fetch-dedup.js +73 -14
  241. package/dist/shims/internal/pages-data-target.d.ts +10 -9
  242. package/dist/shims/internal/pages-data-target.js +91 -12
  243. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  244. package/dist/shims/internal/pages-router-components.js +13 -0
  245. package/dist/shims/layout-segment-context.d.ts +4 -1
  246. package/dist/shims/layout-segment-context.js +18 -4
  247. package/dist/shims/link.js +70 -37
  248. package/dist/shims/metadata.d.ts +3 -2
  249. package/dist/shims/metadata.js +8 -4
  250. package/dist/shims/navigation.d.ts +5 -1
  251. package/dist/shims/navigation.js +45 -10
  252. package/dist/shims/navigation.react-server.js +1 -1
  253. package/dist/shims/root-params.d.ts +15 -1
  254. package/dist/shims/root-params.js +21 -1
  255. package/dist/shims/router.d.ts +5 -7
  256. package/dist/shims/router.js +374 -94
  257. package/dist/shims/server.js +3 -2
  258. package/dist/shims/slot.js +3 -6
  259. package/dist/typegen.js +6 -5
  260. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  261. package/dist/utils/client-runtime-metadata.js +31 -22
  262. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  263. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  264. package/dist/utils/domain-locale.d.ts +6 -3
  265. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  266. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  267. package/dist/utils/path.d.ts +2 -1
  268. package/dist/utils/path.js +1 -1
  269. package/dist/utils/project.d.ts +52 -2
  270. package/dist/utils/project.js +230 -5
  271. package/dist/utils/protocol-headers.d.ts +17 -0
  272. package/dist/utils/protocol-headers.js +17 -0
  273. package/dist/utils/react-version.d.ts +4 -0
  274. package/dist/utils/react-version.js +44 -0
  275. package/package.json +53 -4
  276. package/dist/deploy.d.ts +0 -190
  277. package/dist/deploy.js +0 -1033
  278. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  279. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -1,17 +1,27 @@
1
- import { matchRoutePattern } from "../routing/route-pattern.js";
2
1
  import { AppElementsWire } from "./app-elements-wire.js";
3
- import { APP_RSC_RENDER_MODE_NAVIGATION, shouldSuppressLoadingBoundaries } from "./app-rsc-render-mode.js";
2
+ import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
4
3
  import "./app-elements.js";
5
4
  import { createAppPageRenderIdentity } from "./app-page-render-identity.js";
5
+ import { matchRoutePattern } from "../routing/route-pattern.js";
6
6
  import { makeThenableParams } from "../shims/thenable-params.js";
7
+ import { resolveAppPageBranchParams } from "./app-page-params.js";
7
8
  import { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from "./app-page-head.js";
8
- import { makeObservedAppPageSearchParamsThenable } from "./app-page-search-params-observation.js";
9
+ import { createAppPageSearchParamsObserver, makeObservedAppPageSearchParamsThenable } from "./app-page-search-params-observation.js";
9
10
  import { buildAppPageElements, createAppPageSourcePage, createAppPageTreePath } from "./app-page-route-wiring.js";
10
11
  import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
11
12
  import "./app-rsc-route-matching.js";
12
13
  import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
13
14
  import { createElement } from "react";
14
15
  //#region src/server/app-page-element-builder.ts
16
+ function resolveInterceptLayoutParams(branchSegments, layoutSegments, params) {
17
+ return resolveAppPageBranchParams(branchSegments, layoutSegments.length, params, layoutSegments);
18
+ }
19
+ const REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference");
20
+ function isReactOwnedPageComponent(component) {
21
+ if (typeof component !== "function") return true;
22
+ const candidate = component;
23
+ return candidate.$$typeof === REACT_CLIENT_REFERENCE || candidate.prototype?.isReactComponent != null;
24
+ }
15
25
  /**
16
26
  * Build the App Router element tree for a matched route.
17
27
  *
@@ -30,7 +40,8 @@ import { createElement } from "react";
30
40
  */
31
41
  async function buildPageElements(options) {
32
42
  const { route, params, routePath, displayPathname = routePath, pageRequest, globalErrorModule, rootNotFoundModule, rootForbiddenModule, rootUnauthorizedModule, metadataRoutes } = options;
33
- const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION } = pageRequest;
43
+ const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
44
+ const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION, observeMetadataSearchParamsAccess = false, observePageSearchParamsAccess = false } = pageRequest;
34
45
  const pageModule = route.page;
35
46
  const isSiblingIntercept = opts?.interceptSlotKey === "__vinext_page_intercept" && !!opts?.interceptPage;
36
47
  const effectivePageModule = isSiblingIntercept ? opts.interceptPage : pageModule;
@@ -40,6 +51,7 @@ async function buildPageElements(options) {
40
51
  const hasPageModule = !!pageModule;
41
52
  const renderIdentity = createAppPageRenderIdentity({
42
53
  displayPathname,
54
+ targetMatchedPathname: routePath,
43
55
  interceptionContext: opts?.interceptionContext ?? null,
44
56
  interceptSourceMatchedUrl: opts?.interceptSourceMatchedUrl ?? null,
45
57
  interceptSlotId: isSiblingIntercept ? null : opts?.interceptSlotId ?? null
@@ -64,44 +76,68 @@ async function buildPageElements(options) {
64
76
  };
65
77
  }
66
78
  const { hasDynamicMetadata, metadata: resolvedMetadata, pageSearchParams, viewport: resolvedViewport } = await resolveAppPageHead({
79
+ applyFileBasedMetadata: options.applyFileBasedMetadata,
67
80
  basePath: options.basePath ?? "",
68
81
  layoutModules: route.layouts,
69
82
  layoutTreePositions: route.layoutTreePositions,
70
83
  metadataRoutes,
71
- pageModule: effectivePageModule ?? null,
72
- parallelRoutes: resolveActiveParallelRouteHeadInputs({
84
+ pageModule: isSiblingIntercept ? null : effectivePageModule ?? null,
85
+ parallelRoutes: [...resolveActiveParallelRouteHeadInputs({
86
+ interceptBranchSegments: opts?.interceptBranchSegments ?? null,
73
87
  interceptLayouts: opts?.interceptLayouts ?? null,
88
+ interceptLayoutSegments: opts?.interceptLayoutSegments ?? null,
74
89
  interceptPage: opts?.interceptPage ?? null,
75
90
  interceptParams: opts?.interceptParams ?? null,
76
91
  interceptSlotKey: opts?.interceptSlotKey ?? null,
92
+ layoutTreePositions: route.layoutTreePositions,
77
93
  params,
78
94
  routeSegments: route.routeSegments ?? [],
95
+ slotParams: slotParamOverrides,
79
96
  slots: route.slots ?? null
80
- }),
97
+ }), ...isSiblingIntercept ? [{
98
+ layoutModules: opts?.interceptLayouts ?? [],
99
+ layoutParams: (opts?.interceptLayoutSegments ?? []).map((segments) => resolveInterceptLayoutParams(opts?.interceptBranchSegments ?? segments, segments, effectiveParams)),
100
+ pageModule: effectivePageModule ?? null,
101
+ params: effectiveParams,
102
+ routeSegments: opts?.interceptSourcePageSegments ?? route.routeSegments ?? []
103
+ }] : []],
81
104
  params: effectiveParams,
82
105
  routePath: route.pattern,
83
106
  routeSegments: route.routeSegments ?? null,
84
- searchParams
107
+ searchParams,
108
+ searchParamsObserver: observeMetadataSearchParamsAccess ? createAppPageSearchParamsObserver() : void 0
85
109
  });
86
110
  const pageProps = { params: makeThenableParams(effectiveParams) };
87
- let pageSearchParamsThenable;
88
- if (searchParams) {
89
- pageSearchParamsThenable = !shouldSuppressLoadingBoundaries(renderMode) && Boolean(route.loading?.default) ? makeObservedAppPageSearchParamsThenable(pageSearchParams) : makeThenableParams(pageSearchParams);
90
- pageProps.searchParams = pageSearchParamsThenable;
91
- }
111
+ const hasRequestSearchParams = Object.keys(pageSearchParams).length > 0;
112
+ const createPageElement = (PageComponent, props) => {
113
+ if (isReactOwnedPageComponent(PageComponent)) {
114
+ const invocationProps = { ...props };
115
+ if (searchParams) invocationProps.searchParams = observePageSearchParamsAccess ? makeObservedAppPageSearchParamsThenable(pageSearchParams, { markDynamic: hasRequestSearchParams }) : makeThenableParams(pageSearchParams);
116
+ return createElement(PageComponent, invocationProps);
117
+ }
118
+ const ServerPageComponent = PageComponent;
119
+ const PageInvoker = () => {
120
+ const invocationProps = { ...props };
121
+ if (searchParams) invocationProps.searchParams = observePageSearchParamsAccess ? makeObservedAppPageSearchParamsThenable(pageSearchParams) : makeThenableParams(pageSearchParams);
122
+ return ServerPageComponent(invocationProps);
123
+ };
124
+ return createElement(PageInvoker);
125
+ };
126
+ const pageSearchParamsThenable = searchParams ? makeThenableParams(pageSearchParams) : void 0;
92
127
  const mountedSlotIds = mountedSlotsHeader ? new Set(mountedSlotsHeader.split(" ")) : null;
93
128
  const slotOverrides = buildSlotOverrides(route, params, routePath, opts);
94
129
  const metadataPlacement = hasDynamicMetadata && shouldServeStreamingMetadata(pageRequest.request.headers.get("user-agent") ?? "", options.htmlLimitedBots) ? "body" : "head";
95
- let siblingInterceptElement = isSiblingIntercept && EffectivePageComponent ? createElement(EffectivePageComponent, pageProps) : null;
96
- if (isSiblingIntercept && siblingInterceptElement !== null && opts?.interceptLayouts?.length) {
97
- const siblingThenableParams = makeThenableParams(effectiveParams);
98
- for (let i = opts.interceptLayouts.length - 1; i >= 0; i--) {
99
- const LayoutComponent = opts.interceptLayouts[i]?.default;
100
- if (LayoutComponent) siblingInterceptElement = createElement(LayoutComponent, { params: siblingThenableParams }, siblingInterceptElement);
130
+ let siblingInterceptElement = isSiblingIntercept && EffectivePageComponent ? createPageElement(EffectivePageComponent, pageProps) : null;
131
+ if (isSiblingIntercept && siblingInterceptElement !== null && opts?.interceptLayouts?.length) for (let i = opts.interceptLayouts.length - 1; i >= 0; i--) {
132
+ const LayoutComponent = opts.interceptLayouts[i]?.default;
133
+ if (LayoutComponent) {
134
+ const interceptLayoutSegments = opts.interceptLayoutSegments?.[i] ?? [];
135
+ siblingInterceptElement = createElement(LayoutComponent, { params: makeThenableParams(resolveInterceptLayoutParams(opts.interceptBranchSegments ?? interceptLayoutSegments, interceptLayoutSegments, effectiveParams)) }, siblingInterceptElement);
101
136
  }
102
137
  }
103
138
  return buildAppPageElements({
104
- element: isSiblingIntercept ? siblingInterceptElement : EffectivePageComponent ? createElement(EffectivePageComponent, pageProps) : null,
139
+ element: isSiblingIntercept ? siblingInterceptElement : EffectivePageComponent ? createPageElement(EffectivePageComponent, pageProps) : null,
140
+ createPageElement,
105
141
  globalErrorModule: globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE,
106
142
  isRscRequest,
107
143
  layoutParamAccess: options.layoutParamAccess,
@@ -142,20 +178,75 @@ async function buildPageElements(options) {
142
178
  function buildSlotOverrides(route, routeParams, routePath, opts) {
143
179
  const overrides = {};
144
180
  if (opts && opts.interceptSlotKey && opts.interceptPage && opts.interceptSlotKey !== "__vinext_page_intercept") overrides[opts.interceptSlotKey] = {
181
+ branchSegments: opts.interceptBranchSegments ?? null,
145
182
  layoutModules: opts.interceptLayouts || null,
183
+ layoutSegments: opts.interceptLayoutSegments ?? null,
146
184
  pageModule: opts.interceptPage,
147
- params: opts.interceptParams || routeParams
185
+ params: opts.interceptParams || routeParams,
186
+ routeSegments: resolveInterceptedSlotSegments(opts.interceptSourcePageSegments, opts.interceptSlotKey)
148
187
  };
149
188
  const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
150
189
  for (const [slotKey, params] of Object.entries(slotParamOverrides ?? {})) {
151
190
  const existing = overrides[slotKey];
152
191
  overrides[slotKey] = existing ? {
153
192
  ...existing,
154
- params
193
+ params: existing.params ?? params
155
194
  } : { params };
156
195
  }
157
196
  return Object.keys(overrides).length > 0 ? overrides : null;
158
197
  }
198
+ function resolveInterceptedSlotSegments(sourcePageSegments, slotKey) {
199
+ if (!sourcePageSegments) return null;
200
+ const markerTraversals = [
201
+ {
202
+ prefix: "(...)",
203
+ levels: Number.POSITIVE_INFINITY
204
+ },
205
+ {
206
+ prefix: "(..)(..)",
207
+ levels: 2
208
+ },
209
+ {
210
+ prefix: "(..)",
211
+ levels: 1
212
+ },
213
+ {
214
+ prefix: "(.)",
215
+ levels: 0
216
+ }
217
+ ];
218
+ const markerIndex = sourcePageSegments.findIndex((segment) => markerTraversals.some(({ prefix }) => segment.startsWith(prefix)));
219
+ if (markerIndex < 0) return null;
220
+ const slotPathSeparator = slotKey.indexOf("@");
221
+ const ownerSegments = (slotPathSeparator >= 0 ? slotKey.slice(slotPathSeparator + 1) : "").split("/").filter(Boolean);
222
+ let segmentStart = ownerSegments.length;
223
+ if (segmentStart === 0 || segmentStart > markerIndex || !ownerSegments.every((segment, index) => sourcePageSegments[index] === segment)) {
224
+ let slotName = null;
225
+ for (let index = ownerSegments.length - 1; index >= 0; index--) if (ownerSegments[index].startsWith("@")) {
226
+ slotName = ownerSegments[index];
227
+ break;
228
+ }
229
+ let slotIndex = -1;
230
+ if (slotName) {
231
+ for (let index = markerIndex - 1; index >= 0; index--) if (sourcePageSegments[index] === slotName) {
232
+ slotIndex = index;
233
+ break;
234
+ }
235
+ }
236
+ if (slotIndex < 0) return null;
237
+ segmentStart = slotIndex + 1;
238
+ }
239
+ const routeSegments = sourcePageSegments.slice(segmentStart, markerIndex).filter((segment) => !segment.startsWith("@") && !(segment.startsWith("(") && segment.endsWith(")")));
240
+ const markerSegment = sourcePageSegments[markerIndex];
241
+ const marker = markerTraversals.find(({ prefix }) => markerSegment.startsWith(prefix));
242
+ if (!marker) return null;
243
+ if (Number.isFinite(marker.levels)) routeSegments.splice(Math.max(0, routeSegments.length - marker.levels), marker.levels);
244
+ else routeSegments.length = 0;
245
+ const targetSegment = markerSegment.slice(marker.prefix.length);
246
+ if (targetSegment) routeSegments.push(targetSegment);
247
+ routeSegments.push(...sourcePageSegments.slice(markerIndex + 1).filter((segment) => !segment.startsWith("@") && !(segment.startsWith("(") && segment.endsWith(")"))));
248
+ return routeSegments;
249
+ }
159
250
  function resolveSlotParamOverrides(route, routePath) {
160
251
  const overrides = {};
161
252
  const slots = route.slots;
@@ -201,4 +292,4 @@ function collectParamNameSet(params) {
201
292
  return set;
202
293
  }
203
294
  //#endregion
204
- export { buildPageElements, resolveAppPageNavigationParams };
295
+ export { buildPageElements, resolveAppPageNavigationParams, resolveInterceptedSlotSegments };
@@ -1,31 +1,45 @@
1
1
  import { MetadataFileRoute } from "./metadata-routes.js";
2
2
  import { AppPageParams } from "./app-page-boundary.js";
3
+ import { ThenableParamsObserver } from "../shims/thenable-params.js";
3
4
  import { Metadata, Viewport } from "../shims/metadata.js";
5
+ import { applyFileBasedMetadata } from "./file-based-metadata.js";
4
6
 
5
7
  //#region src/server/app-page-head.d.ts
6
8
  type AppPageSearchParams = Record<string, string | string[]>;
7
9
  type AppPageHeadModule = Record<string, unknown>;
10
+ type ApplyAppPageFileBasedMetadata = typeof applyFileBasedMetadata;
8
11
  type AppPageHeadParallelRoute<TModule extends AppPageHeadModule = AppPageHeadModule> = {
12
+ layoutParams?: readonly AppPageParams[] | null;
9
13
  layoutModule?: TModule | null;
10
14
  layoutModules?: readonly (TModule | null | undefined)[] | null;
15
+ layoutTreePositions?: readonly number[] | null;
11
16
  pageModule?: TModule | null;
12
17
  params?: AppPageParams | null;
13
18
  routeSegments?: readonly string[] | null;
14
19
  };
15
20
  type AppPageHeadSlot<TModule extends AppPageHeadModule = AppPageHeadModule> = {
21
+ configLayouts?: readonly (TModule | null | undefined)[] | null;
22
+ configLayoutTreePositions?: readonly number[] | null;
16
23
  layout?: TModule | null;
24
+ layoutIndex?: number;
17
25
  page?: TModule | null;
26
+ routeSegments?: readonly string[] | null;
18
27
  };
19
28
  type ResolveActiveParallelRouteHeadInputsOptions<TModule extends AppPageHeadModule = AppPageHeadModule> = {
20
29
  interceptLayouts?: readonly (TModule | null | undefined)[] | null;
30
+ interceptBranchSegments?: readonly string[] | null;
31
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
21
32
  interceptPage?: TModule | null;
22
33
  interceptParams?: AppPageParams | null;
23
34
  interceptSlotKey?: string | null;
35
+ layoutTreePositions?: readonly number[] | null;
24
36
  params: AppPageParams;
25
37
  routeSegments: readonly string[];
38
+ slotParams?: Readonly<Record<string, AppPageParams>> | null;
26
39
  slots?: Record<string, AppPageHeadSlot<TModule>> | null;
27
40
  };
28
41
  type ResolveAppPageHeadOptions<TModule extends AppPageHeadModule = AppPageHeadModule> = {
42
+ applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
29
43
  /**
30
44
  * Configured next.config `basePath`. Threaded into `applyFileBasedMetadata`
31
45
  * so file-based metadata route URLs (icon, opengraph-image, manifest, ...)
@@ -43,6 +57,7 @@ type ResolveAppPageHeadOptions<TModule extends AppPageHeadModule = AppPageHeadMo
43
57
  routePath: string;
44
58
  routeSegments?: readonly string[] | null;
45
59
  searchParams?: URLSearchParams | null;
60
+ searchParamsObserver?: ThenableParamsObserver;
46
61
  };
47
62
  type ResolveAppPageHeadResult = {
48
63
  hasDynamicMetadata: boolean;
@@ -59,4 +74,4 @@ declare function resolveActiveParallelRouteHeadInputs<TModule extends AppPageHea
59
74
  declare function collectAppPageSearchParams(searchParams: URLSearchParams | null | undefined): AppPageSearchParamsCollection;
60
75
  declare function resolveAppPageHead<TModule extends AppPageHeadModule>(options: ResolveAppPageHeadOptions<TModule>): Promise<ResolveAppPageHeadResult>;
61
76
  //#endregion
62
- export { AppPageSearchParams, collectAppPageSearchParams, resolveActiveParallelRouteHeadInputs, resolveAppPageHead };
77
+ export { AppPageSearchParams, ApplyAppPageFileBasedMetadata, collectAppPageSearchParams, resolveActiveParallelRouteHeadInputs, resolveAppPageHead };
@@ -1,6 +1,6 @@
1
1
  import { runWithFetchDedupe } from "../shims/fetch-cache.js";
2
2
  import { mergeMetadataEntries, mergeViewport, postProcessMetadata, resolveModuleMetadata as resolveModuleMetadata$1, resolveModuleViewport } from "../shims/metadata.js";
3
- import { resolveAppPageSegmentParams } from "./app-page-params.js";
3
+ import { resolveAppPageBranchParams, resolveAppPageSegmentParams } from "./app-page-params.js";
4
4
  import { tagAppPageMetadataError } from "./app-page-execution.js";
5
5
  //#region src/server/app-page-head.ts
6
6
  /**
@@ -24,23 +24,44 @@ async function resolveModuleMetadata(...args) {
24
24
  }
25
25
  function resolveActiveParallelRouteHeadInputs(options) {
26
26
  return Object.entries(options.slots ?? {}).map(([slotKey, slot]) => {
27
- if (options.interceptSlotKey === slotKey && options.interceptPage) return {
28
- layoutModules: options.interceptLayouts ?? [],
29
- pageModule: options.interceptPage,
30
- params: options.interceptParams ?? options.params,
31
- routeSegments: options.routeSegments
32
- };
27
+ const ownerTreePosition = options.layoutTreePositions?.[slot.layoutIndex ?? 0] ?? 0;
28
+ const ownerParams = resolveAppPageSegmentParams(options.routeSegments, ownerTreePosition, options.params);
29
+ if (options.interceptSlotKey === slotKey && options.interceptPage) {
30
+ const interceptLayouts = options.interceptLayouts ?? [];
31
+ return {
32
+ layoutModules: [slot.layout, ...interceptLayouts].filter(isPresent),
33
+ layoutParams: [...slot.layout ? [ownerParams] : [], ...interceptLayouts.filter(isPresent).map((_, index) => {
34
+ const segments = options.interceptLayoutSegments?.[index] ?? [];
35
+ return {
36
+ ...ownerParams,
37
+ ...resolveParallelLayoutParams(options.interceptBranchSegments ?? segments, segments.length, options.interceptParams ?? options.params)
38
+ };
39
+ })],
40
+ layoutTreePositions: [...slot.layout ? [0] : [], ...interceptLayouts.filter(isPresent).map(() => options.routeSegments.length)],
41
+ pageModule: options.interceptPage,
42
+ params: options.interceptParams ?? options.params,
43
+ routeSegments: options.routeSegments
44
+ };
45
+ }
33
46
  return {
34
- layoutModules: slot.layout ? [slot.layout] : [],
47
+ layoutModules: [slot.layout, ...slot.configLayouts ?? []].filter(isPresent),
48
+ layoutParams: [...slot.layout ? [ownerParams] : [], ...(slot.configLayoutTreePositions ?? []).map((treePosition) => ({
49
+ ...ownerParams,
50
+ ...resolveParallelLayoutParams(slot.routeSegments ?? options.routeSegments, treePosition, options.slotParams?.[slotKey] ?? options.params)
51
+ }))],
52
+ layoutTreePositions: [...slot.layout ? [0] : [], ...slot.configLayoutTreePositions ?? []],
35
53
  pageModule: slot.page,
36
- params: options.params,
37
- routeSegments: options.routeSegments
54
+ params: options.slotParams?.[slotKey] ?? options.params,
55
+ routeSegments: slot.routeSegments ?? options.routeSegments
38
56
  };
39
57
  });
40
58
  }
41
59
  function isPresent(value) {
42
60
  return value !== null && value !== void 0;
43
61
  }
62
+ function resolveParallelLayoutParams(routeSegments, treePosition, params) {
63
+ return resolveAppPageBranchParams(routeSegments, treePosition, params);
64
+ }
44
65
  function hasGenerateMetadata(module) {
45
66
  return typeof module?.generateMetadata === "function";
46
67
  }
@@ -111,7 +132,7 @@ async function resolveLayoutViewport(layoutInputs, params, routeSegments) {
111
132
  return resolveModuleViewport(layoutInput.module, layoutParams);
112
133
  }));
113
134
  }
114
- async function resolveParallelRouteHead(parallelRoute, fallbackParams, fallbackRouteSegments, pageSearchParams, parent) {
135
+ async function resolveParallelRouteHead(parallelRoute, fallbackParams, fallbackRouteSegments, pageSearchParams, parent, searchParamsObserver) {
115
136
  const params = parallelRoute.params ?? fallbackParams;
116
137
  const routeSegments = parallelRoute.routeSegments ?? fallbackRouteSegments;
117
138
  const metadataResults = [];
@@ -119,13 +140,15 @@ async function resolveParallelRouteHead(parallelRoute, fallbackParams, fallbackR
119
140
  const metadataSources = [];
120
141
  let accumulatedMetadata = parent;
121
142
  const layoutModules = [...parallelRoute.layoutModules ?? [], parallelRoute.layoutModule].filter(isPresent);
143
+ const layoutTreePositions = parallelRoute.layoutTreePositions ?? [];
144
+ const layoutParams = parallelRoute.layoutParams ?? [];
122
145
  const hasDynamicMetadata = layoutModules.some(hasGenerateMetadata) || hasGenerateMetadata(parallelRoute.pageModule);
123
- const layoutViewportPromises = layoutModules.map((layoutModule) => resolveModuleViewport(layoutModule, params));
124
- const pageViewportPromise = parallelRoute.pageModule ? resolveModuleViewport(parallelRoute.pageModule, params) : Promise.resolve(null);
146
+ const layoutViewportPromises = layoutModules.map((layoutModule, index) => resolveModuleViewport(layoutModule, layoutParams[index] ?? resolveParallelLayoutParams(routeSegments, layoutTreePositions[index] ?? 0, params)));
147
+ const pageViewportPromise = parallelRoute.pageModule ? resolveModuleViewport(parallelRoute.pageModule, params, pageSearchParams, searchParamsObserver) : Promise.resolve(null);
125
148
  for (const layoutViewportPromise of layoutViewportPromises) layoutViewportPromise.catch(() => null);
126
149
  pageViewportPromise.catch(() => null);
127
- for (const layoutModule of layoutModules) {
128
- const layoutMetadata = await resolveModuleMetadata(layoutModule, params, void 0, accumulatedMetadata);
150
+ for (const [index, layoutModule] of layoutModules.entries()) {
151
+ const layoutMetadata = await resolveModuleMetadata(layoutModule, layoutParams[index] ?? resolveParallelLayoutParams(routeSegments, layoutTreePositions[index] ?? 0, params), void 0, accumulatedMetadata);
129
152
  metadataResults.push(layoutMetadata);
130
153
  metadataSources.push({
131
154
  metadata: layoutMetadata,
@@ -137,7 +160,7 @@ async function resolveParallelRouteHead(parallelRoute, fallbackParams, fallbackR
137
160
  }
138
161
  }
139
162
  if (parallelRoute.pageModule) {
140
- const pageMetadata = await resolveModuleMetadata(parallelRoute.pageModule, params, pageSearchParams, accumulatedMetadata);
163
+ const pageMetadata = await resolveModuleMetadata(parallelRoute.pageModule, params, pageSearchParams, accumulatedMetadata, searchParamsObserver);
141
164
  metadataResults.push(pageMetadata);
142
165
  metadataSources.push({
143
166
  metadata: pageMetadata,
@@ -170,9 +193,9 @@ async function resolveAppPageHeadInner(options) {
170
193
  layoutMetadataResultsForParent.catch(() => null);
171
194
  const pageParentPromise = layoutMetadataResultsForParent.then((metadataResults) => metadataResults.length > 0 ? mergeMetadataEntries(metadataResults.map((metadata) => ({ metadata }))) : {});
172
195
  pageParentPromise.catch(() => null);
173
- const pageMetadataPromise = options.pageModule ? resolveModuleMetadata(options.pageModule, options.params, pageSearchParams, pageParentPromise) : Promise.resolve(null);
174
- const pageViewportPromise = options.pageModule ? resolveModuleViewport(options.pageModule, options.params) : Promise.resolve(null);
175
- const parallelRouteHeadPromise = Promise.all((options.parallelRoutes ?? []).map((parallelRoute) => resolveParallelRouteHead(parallelRoute, options.params, routeSegments, pageSearchParams, pageParentPromise)));
196
+ const pageMetadataPromise = options.pageModule ? resolveModuleMetadata(options.pageModule, options.params, pageSearchParams, pageParentPromise, options.searchParamsObserver) : Promise.resolve(null);
197
+ const pageViewportPromise = options.pageModule ? resolveModuleViewport(options.pageModule, options.params, pageSearchParams, options.searchParamsObserver) : Promise.resolve(null);
198
+ const parallelRouteHeadPromise = Promise.all((options.parallelRoutes ?? []).map((parallelRoute) => resolveParallelRouteHead(parallelRoute, options.params, routeSegments, pageSearchParams, pageParentPromise, options.searchParamsObserver)));
176
199
  const [layoutMetadataResults, layoutViewportResults, pageMetadata, pageViewport, parallelRouteHeads] = await Promise.all([
177
200
  layoutMetadataPromise,
178
201
  layoutViewportPromise,
@@ -205,9 +228,8 @@ async function resolveAppPageHeadInner(options) {
205
228
  const metadataSources = createMetadataSources(layoutMetadataResults, routeSegments, layoutSourcePositions, pageMetadata, Boolean(options.pageModule));
206
229
  metadataSources.push(...parallelMetadataSources);
207
230
  let metadata = resolvedMetadataBase;
208
- if (options.metadataRoutes.length > 0) try {
209
- const { applyFileBasedMetadata } = await import("./file-based-metadata.js");
210
- metadata = await applyFileBasedMetadata(resolvedMetadataBase, options.routePath, options.params, options.metadataRoutes, {
231
+ if (options.applyFileBasedMetadata && options.metadataRoutes.length > 0) try {
232
+ metadata = await options.applyFileBasedMetadata(resolvedMetadataBase, options.routePath, options.params, options.metadataRoutes, {
211
233
  routeSegments,
212
234
  metadataSources,
213
235
  basePath: options.basePath ?? ""
@@ -4,5 +4,6 @@ import { AppPageParams } from "./app-page-boundary.js";
4
4
  declare function getAppPageSegmentParamName(segment: string): string | null;
5
5
  declare function resolveAppPageSegmentParamScopeKeys(routeSegments: readonly string[] | null | undefined, treePosition: number): readonly string[];
6
6
  declare function resolveAppPageSegmentParams(routeSegments: readonly string[] | null | undefined, treePosition: number, matchedParams: AppPageParams): AppPageParams;
7
+ declare function resolveAppPageBranchParams(branchSegments: readonly string[], treePosition: number, matchedParams: AppPageParams, scopedSegments?: readonly string[]): AppPageParams;
7
8
  //#endregion
8
- export { getAppPageSegmentParamName, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams };
9
+ export { getAppPageSegmentParamName, resolveAppPageBranchParams, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams };
@@ -35,5 +35,12 @@ function resolveAppPageSegmentParams(routeSegments, treePosition, matchedParams)
35
35
  }
36
36
  return segmentParams;
37
37
  }
38
+ function resolveAppPageBranchParams(branchSegments, treePosition, matchedParams, scopedSegments = branchSegments) {
39
+ const branchParamNames = new Set(branchSegments.map(getAppPageSegmentParamName).filter((name) => name !== null));
40
+ const scopedParams = {};
41
+ for (const [name, value] of Object.entries(matchedParams)) if (!branchParamNames.has(name)) scopedParams[name] = value;
42
+ Object.assign(scopedParams, resolveAppPageSegmentParams(scopedSegments, treePosition, matchedParams));
43
+ return scopedParams;
44
+ }
38
45
  //#endregion
39
- export { getAppPageSegmentParamName, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams };
46
+ export { getAppPageSegmentParamName, resolveAppPageBranchParams, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams };
@@ -0,0 +1,7 @@
1
+ import { createAppPprFallbackShells } from "./app-ppr-fallback-shell.js";
2
+ import { AppPageDispatchRoute, AppPagePprRuntime } from "./app-page-dispatch.js";
3
+
4
+ //#region src/server/app-page-ppr-runtime.d.ts
5
+ declare const appPagePprRuntime: AppPagePprRuntime<AppPageDispatchRoute>;
6
+ //#endregion
7
+ export { appPagePprRuntime, createAppPprFallbackShells };
@@ -0,0 +1,70 @@
1
+ import { beginPprFallbackShellFinalRender, createPprFallbackShellState, getPprFallbackShellState, runWithPprFallbackShellState } from "../shims/ppr-fallback-shell.js";
2
+ import { createAppPprFallbackShells } from "./app-ppr-fallback-shell.js";
3
+ import { hasSearchParams, shouldReadAppPageCache } from "./app-page-dispatch.js";
4
+ //#region src/server/app-page-ppr-runtime.ts
5
+ function classifyPprFallbackShellEligibility(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) {
6
+ if (options.renderedConcreteUrlPaths?.has(options.cleanPathname) === true) return { kind: "skip-known-pregenerated-route" };
7
+ const fallbackShells = options.pprFallbackCacheShells;
8
+ if (!fallbackShells || fallbackShells.length === 0) return { kind: "skip-no-fallback-shells" };
9
+ if (options.isRscRequest) return { kind: "skip-rsc-request" };
10
+ if (options.request.method !== "GET") return { kind: "skip-non-get" };
11
+ if (!isForceStatic && hasSearchParams(options.searchParams)) return { kind: "skip-search-params" };
12
+ if (!shouldReadAppPageCache({
13
+ isDraftMode,
14
+ isForceDynamic,
15
+ isProgressiveActionRender: options.isProgressiveActionRender === true,
16
+ isProduction: options.isProduction,
17
+ isRscRequest: false,
18
+ revalidateSeconds: currentRevalidateSeconds,
19
+ scriptNonce: options.scriptNonce
20
+ })) return { kind: "skip-cache-disabled" };
21
+ return {
22
+ kind: "probe-fallback-shells",
23
+ fallbackShells
24
+ };
25
+ }
26
+ async function probePprFallbackShellCache(options, fallbackShells, currentRevalidateSeconds) {
27
+ const { readAppPageFallbackShellCacheResponse } = await import("./app-page-cache.js");
28
+ const { rewriteAppPprFallbackShellHtmlNavigation } = await import("./app-ppr-fallback-shell.js");
29
+ for (const fallbackShell of fallbackShells) {
30
+ const fallbackShellResponse = await readAppPageFallbackShellCacheResponse({
31
+ clearRequestContext: options.clearRequestContext,
32
+ expireSeconds: options.expireSeconds,
33
+ fallbackPathname: fallbackShell.pathname,
34
+ isEdgeRuntime: options.isEdgeRuntime,
35
+ isrDebug: options.isrDebug,
36
+ isrGet: options.isrGet,
37
+ isrHtmlKey: options.isrHtmlKey,
38
+ middlewareHeaders: options.middlewareContext.headers,
39
+ middlewareStatus: options.middlewareContext.status,
40
+ revalidateSeconds: currentRevalidateSeconds ?? 0,
41
+ rewriteHtml(html) {
42
+ return rewriteAppPprFallbackShellHtmlNavigation({
43
+ html,
44
+ params: options.params,
45
+ pathname: options.cleanPathname,
46
+ searchParams: options.searchParams
47
+ });
48
+ }
49
+ });
50
+ if (fallbackShellResponse) return fallbackShellResponse;
51
+ }
52
+ return null;
53
+ }
54
+ const appPagePprRuntime = {
55
+ beginFinalRender: beginPprFallbackShellFinalRender,
56
+ getState: getPprFallbackShellState,
57
+ run(shell, fn) {
58
+ return runWithPprFallbackShellState(createPprFallbackShellState(shell), fn);
59
+ },
60
+ async tryServe(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) {
61
+ const decision = classifyPprFallbackShellEligibility(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic);
62
+ return decision.kind === "probe-fallback-shells" ? probePprFallbackShellCache(options, decision.fallbackShells, currentRevalidateSeconds) : null;
63
+ },
64
+ async warm(options) {
65
+ const { warmPprFallbackShellCaches } = await import("./app-ppr-fallback-shell-render.js");
66
+ await warmPprFallbackShellCaches(options);
67
+ }
68
+ };
69
+ //#endregion
70
+ export { appPagePprRuntime, createAppPprFallbackShells };
@@ -119,6 +119,7 @@ type ProbeAppPageBeforeRenderResult = {
119
119
  };
120
120
  type ProbeAppPageBeforeRenderOptions = {
121
121
  hasLoadingBoundary: boolean;
122
+ probePageBeforeRender?: boolean;
122
123
  skipProbes?: boolean;
123
124
  layoutCount: number;
124
125
  probeLayoutAt: (layoutIndex: number) => unknown;
@@ -12,6 +12,7 @@ const DEFAULT_SUBTREE_PROBE_MAX_NODES = 1e3;
12
12
  const REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref");
13
13
  const REACT_LAZY_TYPE = Symbol.for("react.lazy");
14
14
  const REACT_MEMO_TYPE = Symbol.for("react.memo");
15
+ const REACT_CLIENT_REFERENCE_TYPE = Symbol.for("react.client.reference");
15
16
  var AppPageSubtreeProbeLimitError = class extends Error {
16
17
  constructor(message) {
17
18
  super(message);
@@ -36,6 +37,9 @@ function isObjectLike(value) {
36
37
  function isUnknownFunction(value) {
37
38
  return typeof value === "function";
38
39
  }
40
+ function isReactClientReference(value) {
41
+ return isObjectLike(value) && Reflect.get(value, "$$typeof") === REACT_CLIENT_REFERENCE_TYPE;
42
+ }
39
43
  function readReactMemoType(value) {
40
44
  if (!isObjectLike(value) || Reflect.get(value, "$$typeof") !== REACT_MEMO_TYPE) return null;
41
45
  return { innerType: Reflect.get(value, "type") };
@@ -80,6 +84,7 @@ async function probeReactServerSubtree(node, options = {}) {
80
84
  };
81
85
  const renderElementType = async (type, props, depth, wrapperDepth = 0) => {
82
86
  if (wrapperDepth > maxDepth) throw new AppPageSubtreeProbeLimitError("App page layout subtree probe exceeded max depth");
87
+ if (isReactClientReference(type)) return false;
83
88
  if (isUnknownFunction(type)) {
84
89
  await visit(type(props), depth + 1);
85
90
  return true;
@@ -252,7 +257,7 @@ async function probeAppPageBeforeRender(options) {
252
257
  layoutFlags
253
258
  };
254
259
  }
255
- if (options.hasLoadingBoundary) return {
260
+ if (options.hasLoadingBoundary || options.probePageBeforeRender === false) return {
256
261
  response: null,
257
262
  layoutFlags
258
263
  };
@@ -2,6 +2,7 @@ import { AppElementsInterception } from "./app-elements-wire.js";
2
2
  //#region src/server/app-page-render-identity.d.ts
3
3
  type AppPageRenderIdentityInput = {
4
4
  displayPathname: string;
5
+ targetMatchedPathname?: string;
5
6
  interceptionContext?: string | null;
6
7
  interceptSourceMatchedUrl?: string | null;
7
8
  interceptSlotId?: string | null;
@@ -13,7 +13,7 @@ function normalizeAppPageInterceptionProofPathname(pathname) {
13
13
  }
14
14
  function createAppPageRenderIdentity(input) {
15
15
  const interceptionContext = input.interceptionContext ?? null;
16
- const targetMatchedPathname = normalizeAppPageRenderMatchedPathname(input.displayPathname);
16
+ const targetMatchedPathname = normalizeAppPageRenderMatchedPathname(input.targetMatchedPathname ?? input.displayPathname);
17
17
  const sourceMatchedPathname = normalizeAppPageInterceptionProofPathname(input.interceptSourceMatchedUrl ?? null);
18
18
  const slotId = input.interceptSlotId ?? null;
19
19
  const matchedRoutePathname = sourceMatchedPathname ?? targetMatchedPathname;
@@ -37,6 +37,7 @@ type RenderAppPageLifecycleOptions = {
37
37
  cleanPathname: string;
38
38
  clearRequestContext: () => void;
39
39
  consumeDynamicUsage: () => boolean;
40
+ peekDynamicUsage?: () => boolean;
40
41
  consumeRenderObservationState?: () => AppPageRenderObservationState; /** Read and clear any invalid dynamic usage error recorded during render (dev-only). */
41
42
  consumeInvalidDynamicUsageError?: () => unknown;
42
43
  createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;
@@ -60,6 +61,8 @@ type RenderAppPageLifecycleOptions = {
60
61
  isProgressiveActionRender?: boolean;
61
62
  isPrerender?: boolean;
62
63
  isProduction: boolean;
64
+ probePageBeforeRender?: boolean;
65
+ omitPendingDynamicCacheState?: boolean;
63
66
  isRscRequest: boolean;
64
67
  isrDebug?: AppPageDebugLogger;
65
68
  isrHtmlKey: (pathname: string) => string;
@@ -81,7 +84,7 @@ type RenderAppPageLifecycleOptions = {
81
84
  expireSeconds?: number;
82
85
  formState?: ReactFormState | null;
83
86
  revalidateSeconds: number | null;
84
- renderErrorBoundaryResponse: (error: unknown) => Promise<Response | null>;
87
+ renderErrorBoundaryResponse: (error: unknown, errorOrigin: "rsc" | "ssr") => Promise<Response | null>;
85
88
  renderLayoutSpecialError: (specialError: AppPageSpecialError, layoutIndex: number) => Promise<Response>;
86
89
  renderPageSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;
87
90
  renderToReadableStream: (element: ReactNode | AppOutgoingElements, options: {