@qzsy/vinext 0.1.12 → 0.1.122

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 (77) hide show
  1. package/dist/check.d.ts +8 -0
  2. package/dist/check.js +20 -9
  3. package/dist/cli.js +2 -2
  4. package/dist/deploy.js +10 -11
  5. package/dist/entries/app-rsc-entry.js +37 -8
  6. package/dist/entries/app-rsc-manifest.js +8 -0
  7. package/dist/entries/pages-client-entry.js +1 -0
  8. package/dist/entries/pages-server-entry.js +1 -0
  9. package/dist/index.js +12 -8
  10. package/dist/init.js +2 -1
  11. package/dist/plugins/middleware-server-only.d.ts +8 -6
  12. package/dist/plugins/middleware-server-only.js +8 -7
  13. package/dist/routing/app-route-graph.d.ts +6 -2
  14. package/dist/routing/app-route-graph.js +60 -12
  15. package/dist/routing/app-router.d.ts +5 -0
  16. package/dist/routing/app-router.js +5 -0
  17. package/dist/routing/file-matcher.d.ts +5 -0
  18. package/dist/routing/file-matcher.js +7 -1
  19. package/dist/server/app-browser-history-controller.d.ts +2 -1
  20. package/dist/server/app-browser-history-controller.js +6 -2
  21. package/dist/server/app-fallback-renderer.d.ts +1 -1
  22. package/dist/server/app-fallback-renderer.js +2 -1
  23. package/dist/server/app-page-boundary-render.d.ts +1 -0
  24. package/dist/server/app-page-boundary-render.js +12 -3
  25. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  26. package/dist/server/app-page-cache-finalizer.js +8 -2
  27. package/dist/server/app-page-dispatch.d.ts +11 -3
  28. package/dist/server/app-page-dispatch.js +54 -15
  29. package/dist/server/app-page-element-builder.d.ts +5 -1
  30. package/dist/server/app-page-element-builder.js +55 -19
  31. package/dist/server/app-page-head.d.ts +12 -0
  32. package/dist/server/app-page-head.js +42 -19
  33. package/dist/server/app-page-params.d.ts +2 -1
  34. package/dist/server/app-page-params.js +8 -1
  35. package/dist/server/app-page-probe.d.ts +1 -0
  36. package/dist/server/app-page-probe.js +1 -1
  37. package/dist/server/app-page-render.d.ts +4 -1
  38. package/dist/server/app-page-render.js +8 -3
  39. package/dist/server/app-page-request.d.ts +8 -1
  40. package/dist/server/app-page-request.js +23 -11
  41. package/dist/server/app-page-route-wiring.d.ts +6 -1
  42. package/dist/server/app-page-route-wiring.js +30 -8
  43. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  44. package/dist/server/app-page-search-params-observation.js +11 -7
  45. package/dist/server/app-route-handler-dispatch.js +1 -0
  46. package/dist/server/app-route-handler-execution.js +2 -1
  47. package/dist/server/app-route-module-loader.d.ts +2 -0
  48. package/dist/server/app-route-module-loader.js +1 -0
  49. package/dist/server/app-router-entry.js +7 -6
  50. package/dist/server/app-rsc-errors.js +7 -1
  51. package/dist/server/app-rsc-handler.js +4 -1
  52. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  53. package/dist/server/app-rsc-route-matching.js +36 -3
  54. package/dist/server/app-segment-config.d.ts +1 -0
  55. package/dist/server/app-segment-config.js +32 -2
  56. package/dist/server/app-server-action-execution.d.ts +4 -0
  57. package/dist/server/app-server-action-execution.js +41 -10
  58. package/dist/server/app-static-generation.d.ts +1 -0
  59. package/dist/server/app-static-generation.js +1 -0
  60. package/dist/server/headers.d.ts +3 -1
  61. package/dist/server/headers.js +3 -1
  62. package/dist/server/prod-server.js +15 -6
  63. package/dist/server/worker-utils.d.ts +2 -1
  64. package/dist/server/worker-utils.js +7 -1
  65. package/dist/shims/error-boundary.d.ts +19 -1
  66. package/dist/shims/error-boundary.js +11 -1
  67. package/dist/shims/headers.d.ts +3 -1
  68. package/dist/shims/headers.js +16 -5
  69. package/dist/shims/metadata.d.ts +3 -2
  70. package/dist/shims/metadata.js +8 -4
  71. package/dist/shims/router.js +13 -2
  72. package/dist/typegen.js +6 -5
  73. package/dist/utils/path.d.ts +2 -1
  74. package/dist/utils/path.js +1 -1
  75. package/dist/utils/project.d.ts +4 -0
  76. package/dist/utils/project.js +5 -1
  77. package/package.json +1 -1
@@ -20,6 +20,8 @@ type AppPageBuildRoute<TModule extends AppPageModule = AppPageModule, TErrorModu
20
20
  type AppPageInterceptOptions<TModule extends AppPageModule = AppPageModule> = {
21
21
  interceptionContext?: string | null;
22
22
  interceptLayouts?: readonly (TModule | null | undefined)[] | null;
23
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
24
+ interceptBranchSegments?: readonly string[] | null;
23
25
  interceptPage?: TModule | null;
24
26
  interceptParams?: AppPageParams | null;
25
27
  interceptSlotId?: string | null;
@@ -33,7 +35,9 @@ type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> = {
33
35
  isRscRequest: boolean; /** The incoming HTTP request (available but unused by this module). */
34
36
  request: Request; /** Normalized x-vinext-mounted-slots header value. */
35
37
  mountedSlotsHeader: string | null; /** Semantic RSC payload mode for this page render. */
36
- renderMode?: AppRscRenderMode;
38
+ renderMode?: AppRscRenderMode; /** Observe page `searchParams` access for cache-safety classification. */
39
+ observePageSearchParamsAccess?: boolean; /** Observe page metadata `searchParams` access for cache-safety classification. */
40
+ observeMetadataSearchParamsAccess?: boolean;
37
41
  };
38
42
  type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = {
39
43
  applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
@@ -1,17 +1,27 @@
1
1
  import { matchRoutePattern } from "../routing/route-pattern.js";
2
2
  import { AppElementsWire } from "./app-elements-wire.js";
3
- import { APP_RSC_RENDER_MODE_NAVIGATION, shouldSuppressLoadingBoundaries } from "./app-rsc-render-mode.js";
3
+ import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
4
4
  import "./app-elements.js";
5
5
  import { createAppPageRenderIdentity } from "./app-page-render-identity.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;
@@ -69,40 +80,63 @@ async function buildPageElements(options) {
69
80
  layoutModules: route.layouts,
70
81
  layoutTreePositions: route.layoutTreePositions,
71
82
  metadataRoutes,
72
- pageModule: effectivePageModule ?? null,
73
- parallelRoutes: resolveActiveParallelRouteHeadInputs({
83
+ pageModule: isSiblingIntercept ? null : effectivePageModule ?? null,
84
+ parallelRoutes: [...resolveActiveParallelRouteHeadInputs({
85
+ interceptBranchSegments: opts?.interceptBranchSegments ?? null,
74
86
  interceptLayouts: opts?.interceptLayouts ?? null,
87
+ interceptLayoutSegments: opts?.interceptLayoutSegments ?? null,
75
88
  interceptPage: opts?.interceptPage ?? null,
76
89
  interceptParams: opts?.interceptParams ?? null,
77
90
  interceptSlotKey: opts?.interceptSlotKey ?? null,
91
+ layoutTreePositions: route.layoutTreePositions,
78
92
  params,
79
93
  routeSegments: route.routeSegments ?? [],
94
+ slotParams: slotParamOverrides,
80
95
  slots: route.slots ?? null
81
- }),
96
+ }), ...isSiblingIntercept ? [{
97
+ layoutModules: opts?.interceptLayouts ?? [],
98
+ layoutParams: (opts?.interceptLayoutSegments ?? []).map((segments) => resolveInterceptLayoutParams(opts?.interceptBranchSegments ?? segments, segments, effectiveParams)),
99
+ pageModule: effectivePageModule ?? null,
100
+ params: effectiveParams,
101
+ routeSegments: opts?.interceptSourcePageSegments ?? route.routeSegments ?? []
102
+ }] : []],
82
103
  params: effectiveParams,
83
104
  routePath: route.pattern,
84
105
  routeSegments: route.routeSegments ?? null,
85
- searchParams
106
+ searchParams,
107
+ searchParamsObserver: observeMetadataSearchParamsAccess ? createAppPageSearchParamsObserver() : void 0
86
108
  });
87
109
  const pageProps = { params: makeThenableParams(effectiveParams) };
88
- let pageSearchParamsThenable;
89
- if (searchParams) {
90
- pageSearchParamsThenable = !shouldSuppressLoadingBoundaries(renderMode) && Boolean(route.loading?.default) ? makeObservedAppPageSearchParamsThenable(pageSearchParams) : makeThenableParams(pageSearchParams);
91
- pageProps.searchParams = pageSearchParamsThenable;
92
- }
110
+ const hasRequestSearchParams = Object.keys(pageSearchParams).length > 0;
111
+ const createPageElement = (PageComponent, props) => {
112
+ if (isReactOwnedPageComponent(PageComponent)) {
113
+ const invocationProps = { ...props };
114
+ if (searchParams) invocationProps.searchParams = observePageSearchParamsAccess ? makeObservedAppPageSearchParamsThenable(pageSearchParams, { markDynamic: hasRequestSearchParams }) : makeThenableParams(pageSearchParams);
115
+ return createElement(PageComponent, invocationProps);
116
+ }
117
+ const ServerPageComponent = PageComponent;
118
+ const PageInvoker = () => {
119
+ const invocationProps = { ...props };
120
+ if (searchParams) invocationProps.searchParams = observePageSearchParamsAccess ? makeObservedAppPageSearchParamsThenable(pageSearchParams) : makeThenableParams(pageSearchParams);
121
+ return ServerPageComponent(invocationProps);
122
+ };
123
+ return createElement(PageInvoker);
124
+ };
125
+ const pageSearchParamsThenable = searchParams ? makeThenableParams(pageSearchParams) : void 0;
93
126
  const mountedSlotIds = mountedSlotsHeader ? new Set(mountedSlotsHeader.split(" ")) : null;
94
127
  const slotOverrides = buildSlotOverrides(route, params, routePath, opts);
95
128
  const metadataPlacement = hasDynamicMetadata && shouldServeStreamingMetadata(pageRequest.request.headers.get("user-agent") ?? "", options.htmlLimitedBots) ? "body" : "head";
96
- let siblingInterceptElement = isSiblingIntercept && EffectivePageComponent ? createElement(EffectivePageComponent, pageProps) : null;
97
- if (isSiblingIntercept && siblingInterceptElement !== null && opts?.interceptLayouts?.length) {
98
- const siblingThenableParams = makeThenableParams(effectiveParams);
99
- for (let i = opts.interceptLayouts.length - 1; i >= 0; i--) {
100
- const LayoutComponent = opts.interceptLayouts[i]?.default;
101
- if (LayoutComponent) siblingInterceptElement = createElement(LayoutComponent, { params: siblingThenableParams }, siblingInterceptElement);
129
+ let siblingInterceptElement = isSiblingIntercept && EffectivePageComponent ? createPageElement(EffectivePageComponent, pageProps) : null;
130
+ if (isSiblingIntercept && siblingInterceptElement !== null && opts?.interceptLayouts?.length) for (let i = opts.interceptLayouts.length - 1; i >= 0; i--) {
131
+ const LayoutComponent = opts.interceptLayouts[i]?.default;
132
+ if (LayoutComponent) {
133
+ const interceptLayoutSegments = opts.interceptLayoutSegments?.[i] ?? [];
134
+ siblingInterceptElement = createElement(LayoutComponent, { params: makeThenableParams(resolveInterceptLayoutParams(opts.interceptBranchSegments ?? interceptLayoutSegments, interceptLayoutSegments, effectiveParams)) }, siblingInterceptElement);
102
135
  }
103
136
  }
104
137
  return buildAppPageElements({
105
- element: isSiblingIntercept ? siblingInterceptElement : EffectivePageComponent ? createElement(EffectivePageComponent, pageProps) : null,
138
+ element: isSiblingIntercept ? siblingInterceptElement : EffectivePageComponent ? createPageElement(EffectivePageComponent, pageProps) : null,
139
+ createPageElement,
106
140
  globalErrorModule: globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE,
107
141
  isRscRequest,
108
142
  layoutParamAccess: options.layoutParamAccess,
@@ -143,7 +177,9 @@ async function buildPageElements(options) {
143
177
  function buildSlotOverrides(route, routeParams, routePath, opts) {
144
178
  const overrides = {};
145
179
  if (opts && opts.interceptSlotKey && opts.interceptPage && opts.interceptSlotKey !== "__vinext_page_intercept") overrides[opts.interceptSlotKey] = {
180
+ branchSegments: opts.interceptBranchSegments ?? null,
146
181
  layoutModules: opts.interceptLayouts || null,
182
+ layoutSegments: opts.interceptLayoutSegments ?? null,
147
183
  pageModule: opts.interceptPage,
148
184
  params: opts.interceptParams || routeParams
149
185
  };
@@ -1,5 +1,6 @@
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";
4
5
  import { applyFileBasedMetadata } from "./file-based-metadata.js";
5
6
 
@@ -8,23 +9,33 @@ type AppPageSearchParams = Record<string, string | string[]>;
8
9
  type AppPageHeadModule = Record<string, unknown>;
9
10
  type ApplyAppPageFileBasedMetadata = typeof applyFileBasedMetadata;
10
11
  type AppPageHeadParallelRoute<TModule extends AppPageHeadModule = AppPageHeadModule> = {
12
+ layoutParams?: readonly AppPageParams[] | null;
11
13
  layoutModule?: TModule | null;
12
14
  layoutModules?: readonly (TModule | null | undefined)[] | null;
15
+ layoutTreePositions?: readonly number[] | null;
13
16
  pageModule?: TModule | null;
14
17
  params?: AppPageParams | null;
15
18
  routeSegments?: readonly string[] | null;
16
19
  };
17
20
  type AppPageHeadSlot<TModule extends AppPageHeadModule = AppPageHeadModule> = {
21
+ configLayouts?: readonly (TModule | null | undefined)[] | null;
22
+ configLayoutTreePositions?: readonly number[] | null;
18
23
  layout?: TModule | null;
24
+ layoutIndex?: number;
19
25
  page?: TModule | null;
26
+ routeSegments?: readonly string[] | null;
20
27
  };
21
28
  type ResolveActiveParallelRouteHeadInputsOptions<TModule extends AppPageHeadModule = AppPageHeadModule> = {
22
29
  interceptLayouts?: readonly (TModule | null | undefined)[] | null;
30
+ interceptBranchSegments?: readonly string[] | null;
31
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
23
32
  interceptPage?: TModule | null;
24
33
  interceptParams?: AppPageParams | null;
25
34
  interceptSlotKey?: string | null;
35
+ layoutTreePositions?: readonly number[] | null;
26
36
  params: AppPageParams;
27
37
  routeSegments: readonly string[];
38
+ slotParams?: Readonly<Record<string, AppPageParams>> | null;
28
39
  slots?: Record<string, AppPageHeadSlot<TModule>> | null;
29
40
  };
30
41
  type ResolveAppPageHeadOptions<TModule extends AppPageHeadModule = AppPageHeadModule> = {
@@ -46,6 +57,7 @@ type ResolveAppPageHeadOptions<TModule extends AppPageHeadModule = AppPageHeadMo
46
57
  routePath: string;
47
58
  routeSegments?: readonly string[] | null;
48
59
  searchParams?: URLSearchParams | null;
60
+ searchParamsObserver?: ThenableParamsObserver;
49
61
  };
50
62
  type ResolveAppPageHeadResult = {
51
63
  hasDynamicMetadata: boolean;
@@ -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,
@@ -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 };
@@ -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;
@@ -252,7 +252,7 @@ async function probeAppPageBeforeRender(options) {
252
252
  layoutFlags
253
253
  };
254
254
  }
255
- if (options.hasLoadingBoundary) return {
255
+ if (options.hasLoadingBoundary || options.probePageBeforeRender === false) return {
256
256
  response: null,
257
257
  layoutFlags
258
258
  };
@@ -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: {
@@ -248,8 +248,11 @@ function wrapRscResponseForDevErrorReporting(response, consumeInvalidDynamicUsag
248
248
  });
249
249
  }
250
250
  async function renderAppPageLifecycle(options) {
251
+ const configuredProbePageBeforeRender = options.probePageBeforeRender ?? options.isRscRequest;
252
+ const probePageBeforeRender = options.isRscRequest || configuredProbePageBeforeRender && !(options.peekDynamicUsage?.() ?? false);
251
253
  const preRenderResult = await probeAppPageBeforeRender({
252
254
  hasLoadingBoundary: options.hasLoadingBoundary,
255
+ probePageBeforeRender,
253
256
  skipProbes: options.pprFallbackShellSignal !== void 0,
254
257
  layoutCount: options.layoutCount,
255
258
  probeLayoutAt(layoutIndex) {
@@ -430,7 +433,8 @@ async function renderAppPageLifecycle(options) {
430
433
  if (!options.isProduction) renderEnd = performance.now();
431
434
  },
432
435
  renderErrorBoundaryResponse(error) {
433
- return options.renderErrorBoundaryResponse(rscErrorTracker.getCapturedError() ?? error);
436
+ const capturedRscError = rscErrorTracker.getCapturedError();
437
+ return options.renderErrorBoundaryResponse(capturedRscError ?? error, capturedRscError === null ? "ssr" : "rsc");
434
438
  },
435
439
  async renderHtmlStream() {
436
440
  const ssrHandler = await options.loadSsrHandler();
@@ -462,7 +466,7 @@ async function renderAppPageLifecycle(options) {
462
466
  if (!htmlStream) throw new Error("[vinext] Expected an HTML stream when no fallback response was returned");
463
467
  const linkHeader = buildAppPageLinkHeader(htmlRender.linkHeader, fontLinkHeader, options.reactMaxHeadersLength);
464
468
  if (options.isPrerender === true) await htmlRender.metadataReady;
465
- if (options.hasLoadingBoundary) {
469
+ if (options.hasLoadingBoundary || !probePageBeforeRender) {
466
470
  const captured = rscErrorTracker.getCapturedSpecialError();
467
471
  if (captured) {
468
472
  const specialError = resolveAppPageSpecialError(captured);
@@ -480,8 +484,8 @@ async function renderAppPageLifecycle(options) {
480
484
  revalidateSeconds
481
485
  }));
482
486
  }
487
+ let dynamicUsedDuringRender = options.consumeDynamicUsage();
483
488
  const draftCookie = options.getDraftModeCookieHeader();
484
- const dynamicUsedDuringRender = options.consumeDynamicUsage();
485
489
  let dynamicUsedBeforeContextCleanup = dynamicUsedDuringRender;
486
490
  const safeHtmlStream = deferUntilStreamConsumed(htmlStream, () => {
487
491
  dynamicUsedBeforeContextCleanup = dynamicUsedBeforeContextCleanup || options.consumeDynamicUsage();
@@ -575,6 +579,7 @@ async function renderAppPageLifecycle(options) {
575
579
  isrRscKey: options.isrRscKey,
576
580
  isrSet: options.isrSet,
577
581
  interceptionContext: options.interceptionContext,
582
+ omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
578
583
  preserveClientResponseHeaders: !htmlResponsePolicy.shouldWriteToCache,
579
584
  expireSeconds,
580
585
  revalidateSeconds,
@@ -40,8 +40,11 @@ type BuildAppPageElementResult<TElement> = {
40
40
  };
41
41
  type AppPageInterceptMatch<TPage = unknown> = {
42
42
  interceptLayouts?: readonly unknown[] | null;
43
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
44
+ interceptBranchSegments?: readonly string[] | null;
43
45
  __loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
44
46
  matchedParams: AppPageParams;
47
+ sourceMatchedParams?: AppPageParams;
45
48
  page: TPage;
46
49
  __pageLoader?: (() => Promise<TPage>) | null;
47
50
  __loadState?: {
@@ -88,7 +91,10 @@ type ResolveAppPageInterceptionRerenderTargetResult<TRoute, TInterceptOpts> = {
88
91
  type ResolveAppPageActionRerenderTargetOptions<TRoute, TPage, TInterceptOpts> = ResolveAppPageInterceptionRerenderTargetOptions<TRoute, TPage, TInterceptOpts>;
89
92
  type ResolveAppPageActionRerenderTargetResult<TRoute, TInterceptOpts> = ResolveAppPageInterceptionRerenderTargetResult<TRoute, TInterceptOpts>;
90
93
  type ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement> = {
91
- buildPageElement: (route: TRoute, params: AppPageParams, interceptOpts: TInterceptOpts | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker) => Promise<TElement>;
94
+ buildPageElement: (route: TRoute, params: AppPageParams, interceptOpts: TInterceptOpts | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker, buildOptions?: {
95
+ observeMetadataSearchParamsAccess?: boolean;
96
+ observePageSearchParamsAccess?: boolean;
97
+ }) => Promise<TElement>;
92
98
  cleanPathname: string;
93
99
  currentRoute: TRoute;
94
100
  findIntercept: (pathname: string) => AppPageInterceptMatch<TPage> | null;
@@ -98,6 +104,7 @@ type ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement> = {
98
104
  layoutParamAccess?: AppLayoutParamAccessTracker;
99
105
  resolveNavigationParams: (route: TRoute, params: AppPageParams, pathname: string, interceptOpts: TInterceptOpts) => AppPageParams;
100
106
  renderInterceptResponse: (route: TRoute, element: TElement) => Promise<Response> | Response;
107
+ resolveSearchParams?: (route: TRoute, searchParams: URLSearchParams) => Awaitable<URLSearchParams>;
101
108
  searchParams: URLSearchParams;
102
109
  setNavigationContext: (context: {
103
110
  params: AppPageParams;
@@ -97,7 +97,7 @@ async function resolveAppPageInterceptMatch(options) {
97
97
  return {
98
98
  interceptOpts: options.toInterceptOpts(interceptState.intercept),
99
99
  matchedParams: interceptState.intercept.matchedParams,
100
- sourceParams: pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
100
+ sourceParams: pickRouteParams(interceptState.intercept.sourceMatchedParams ?? interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
101
101
  sourceRoute: interceptState.sourceRoute
102
102
  };
103
103
  }
@@ -145,12 +145,18 @@ async function resolveAppPageInterceptionRerenderTarget(options) {
145
145
  isRscRequest: options.isRscRequest,
146
146
  toInterceptOpts: options.toInterceptOpts
147
147
  });
148
- if (interceptState.kind === "source-route") return {
149
- interceptOpts: options.toInterceptOpts(interceptState.intercept),
150
- navigationParams: interceptState.intercept.matchedParams,
151
- params: pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
152
- route: interceptState.sourceRoute
153
- };
148
+ if (interceptState.kind === "source-route") {
149
+ const sourceMatchedParams = interceptState.intercept.sourceMatchedParams ?? interceptState.intercept.matchedParams;
150
+ return {
151
+ interceptOpts: options.toInterceptOpts(interceptState.intercept),
152
+ navigationParams: {
153
+ ...sourceMatchedParams,
154
+ ...interceptState.intercept.matchedParams
155
+ },
156
+ params: pickRouteParams(sourceMatchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
157
+ route: interceptState.sourceRoute
158
+ };
159
+ }
154
160
  return {
155
161
  interceptOpts: interceptState.kind === "current-route" ? options.toInterceptOpts(interceptState.intercept) : void 0,
156
162
  navigationParams: options.currentParams,
@@ -174,13 +180,19 @@ async function resolveAppPageIntercept(options) {
174
180
  if (interceptState.kind === "source-route") {
175
181
  const renderRoute = interceptState.sourceRoute;
176
182
  const interceptOpts = options.toInterceptOpts(interceptState.intercept);
177
- const renderParams = pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute));
183
+ const sourceMatchedParams = interceptState.intercept.sourceMatchedParams ?? interceptState.intercept.matchedParams;
184
+ const navigationParams = {
185
+ ...sourceMatchedParams,
186
+ ...interceptState.intercept.matchedParams
187
+ };
188
+ const renderSearchParams = options.resolveSearchParams ? await options.resolveSearchParams(renderRoute, options.searchParams) : options.searchParams;
189
+ const renderParams = pickRouteParams(sourceMatchedParams, options.getRouteParamNames(interceptState.sourceRoute));
178
190
  options.setNavigationContext({
179
- params: options.resolveNavigationParams(renderRoute, interceptState.intercept.matchedParams, options.cleanPathname, interceptOpts),
191
+ params: options.resolveNavigationParams(renderRoute, navigationParams, options.cleanPathname, interceptOpts),
180
192
  pathname: options.cleanPathname,
181
- searchParams: options.searchParams
193
+ searchParams: renderSearchParams
182
194
  });
183
- const interceptElement = await options.buildPageElement(renderRoute, renderParams, interceptOpts, options.searchParams, options.layoutParamAccess);
195
+ const interceptElement = await options.buildPageElement(renderRoute, renderParams, interceptOpts, renderSearchParams, options.layoutParamAccess);
184
196
  return {
185
197
  interceptOpts: void 0,
186
198
  response: await options.renderInterceptResponse(renderRoute, interceptElement)
@@ -1,8 +1,8 @@
1
1
  import { AppRouteSemanticIds } from "../routing/app-route-graph.js";
2
2
  import { AppElements, AppElementsInterception } from "./app-elements-wire.js";
3
3
  import { AppPageParams } from "./app-page-boundary.js";
4
- import { Metadata, Viewport } from "../shims/metadata.js";
5
4
  import { ThenableParamsObserver } from "../shims/thenable-params.js";
5
+ import { Metadata, Viewport } from "../shims/metadata.js";
6
6
  import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
7
7
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
8
8
  import { AppPageRenderIdentity } from "./app-page-render-identity.js";
@@ -31,6 +31,8 @@ type AppPageRouteWiringSlot<TModule extends AppPageModule = AppPageModule, TErro
31
31
  /** Graph-owned semantic slot identity. */id?: string | null; /** Slot prop name passed to the owning layout (e.g. "modal" from @modal). */
32
32
  name: string;
33
33
  default?: TModule | null;
34
+ configLayouts?: readonly (TModule | null | undefined)[] | null;
35
+ configLayoutTreePositions?: readonly number[] | null;
34
36
  error?: TErrorModule | null;
35
37
  layout?: TModule | null;
36
38
  layoutIndex: number;
@@ -83,6 +85,8 @@ type AppPageRouteWiringRoute<TModule extends AppPageModule = AppPageModule, TErr
83
85
  templates?: readonly (TModule | null | undefined)[] | null;
84
86
  };
85
87
  type AppPageSlotOverride<TModule extends AppPageModule = AppPageModule> = {
88
+ branchSegments?: readonly string[] | null;
89
+ layoutSegments?: readonly (readonly string[])[] | null;
86
90
  layoutModules?: readonly (TModule | null | undefined)[] | null;
87
91
  /**
88
92
  * The page module to render for this slot. Optional — when omitted, the
@@ -118,6 +122,7 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
118
122
  rootNotFoundModule?: TModule | null;
119
123
  rootUnauthorizedModule?: TModule | null;
120
124
  route: AppPageRouteWiringRoute<TModule, TErrorModule>;
125
+ createPageElement?: (component: AppPageComponent, props: Readonly<Record<string, unknown>>) => ReactNode;
121
126
  searchParams?: unknown;
122
127
  slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;
123
128
  };
@@ -8,7 +8,7 @@ import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
8
8
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
9
9
  import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
10
10
  import { Children as Children$1, ParallelSlot, Slot } from "../shims/slot.js";
11
- import { resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams } from "./app-page-params.js";
11
+ import { resolveAppPageBranchParams, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams } from "./app-page-params.js";
12
12
  import { probeReactServerSubtree } from "./app-page-probe.js";
13
13
  import { resolveAppPageChildSegments, resolveAppPageRouteStateKey, resolveAppPageSegmentStateKey } from "./app-page-segment-state.js";
14
14
  import { Fragment, Suspense } from "react";
@@ -16,6 +16,9 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
16
16
  //#region src/server/app-page-route-wiring.tsx
17
17
  const APP_PAGE_LAYOUT_PROBE_CHILD = /* @__PURE__ */ jsx(Fragment, {});
18
18
  const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
19
+ function resolveSlotLayoutParams(routeSegments, treePosition, params) {
20
+ return resolveAppPageBranchParams(routeSegments, treePosition, params);
21
+ }
19
22
  function getDefaultExport(module) {
20
23
  return module?.default ?? null;
21
24
  }
@@ -293,7 +296,9 @@ function buildAppPageElements(options) {
293
296
  const slotId = resolveAppPageSlotId(slot, layoutEntries[targetIndex]?.treePath ?? "/");
294
297
  const slotOverride = resolveSlotOverride(slotKey, slotName);
295
298
  const slotParams = getEffectiveSlotParams(slotKey, slotName);
296
- const slotResetKey = resolveAppPageRouteStateKey(slot.routeSegments ?? [], slotParams);
299
+ const slotRouteSegments = slot.routeSegments ?? [];
300
+ const slotOwnerParams = resolveAppPageSegmentParams(options.route.routeSegments, layoutEntries[targetIndex]?.treePosition ?? 0, options.matchedParams);
301
+ const slotResetKey = resolveAppPageRouteStateKey(slotRouteSegments, slotParams);
297
302
  const overrideOrPageComponent = getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page);
298
303
  const defaultComponent = getDefaultExport(slot.default);
299
304
  if (!overrideOrPageComponent && defaultComponent && options.isRscRequest && options.mountedSlotIds?.has(slotId)) continue;
@@ -302,23 +307,40 @@ function buildAppPageElements(options) {
302
307
  elements[slotId] = AppElementsWire.unmatchedSlotValue;
303
308
  continue;
304
309
  }
305
- const slotThenableParams = options.makeThenableParams(slotParams);
306
- const slotProps = { params: slotThenableParams };
310
+ const slotProps = { params: options.makeThenableParams(slotParams) };
307
311
  if (options.searchParams !== void 0) slotProps.searchParams = options.searchParams;
308
312
  if (slotOverride?.props) Object.assign(slotProps, slotOverride.props);
309
- let slotElement = /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
313
+ let slotElement = options.createPageElement ? options.createPageElement(slotComponent, slotProps) : (() => {
314
+ return /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
315
+ })();
316
+ const hasSlotTreeOverride = slotOverride?.pageModule != null || slotOverride?.layoutModules !== void 0;
310
317
  const interceptLayouts = slotOverride?.layoutModules ?? [];
311
318
  for (let layoutIndex = interceptLayouts.length - 1; layoutIndex >= 0; layoutIndex--) {
312
319
  const interceptLayoutComponent = getDefaultExport(interceptLayouts[layoutIndex]);
313
320
  if (!interceptLayoutComponent) continue;
314
- slotElement = /* @__PURE__ */ jsx(interceptLayoutComponent, {
315
- params: slotThenableParams,
321
+ const InterceptLayoutComponent = interceptLayoutComponent;
322
+ const interceptLayoutParams = resolveSlotLayoutParams(slotOverride?.branchSegments ?? slotRouteSegments, slotOverride?.layoutSegments?.[layoutIndex]?.length ?? slotRouteSegments.length, slotParams);
323
+ slotElement = /* @__PURE__ */ jsx(InterceptLayoutComponent, {
324
+ params: options.makeThenableParams(interceptLayoutParams),
325
+ children: slotElement
326
+ });
327
+ }
328
+ if (!hasSlotTreeOverride) for (let layoutIndex = (slot.configLayouts?.length ?? 0) - 1; layoutIndex >= 0; layoutIndex--) {
329
+ const nestedLayoutComponent = getDefaultExport(slot.configLayouts?.[layoutIndex]);
330
+ if (!nestedLayoutComponent) continue;
331
+ const NestedLayoutComponent = nestedLayoutComponent;
332
+ const nestedLayoutParams = resolveSlotLayoutParams(slotRouteSegments, slot.configLayoutTreePositions?.[layoutIndex] ?? 0, slotParams);
333
+ slotElement = /* @__PURE__ */ jsx(NestedLayoutComponent, {
334
+ params: options.makeThenableParams({
335
+ ...slotOwnerParams,
336
+ ...nestedLayoutParams
337
+ }),
316
338
  children: slotElement
317
339
  });
318
340
  }
319
341
  const slotLayoutComponent = getDefaultExport(slot.layout);
320
342
  if (slotLayoutComponent) slotElement = /* @__PURE__ */ jsx(slotLayoutComponent, {
321
- params: slotThenableParams,
343
+ params: options.makeThenableParams(slotOwnerParams),
322
344
  children: slotElement
323
345
  });
324
346
  const slotLoadingComponent = getDefaultExport(slot.loading);