vinext 1.0.0-beta.2 → 1.0.0-beta.4

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 (174) hide show
  1. package/README.md +6 -9
  2. package/dist/build/client-build-config.js +7 -1
  3. package/dist/build/precompress.js +1 -1
  4. package/dist/build/prerender.d.ts +2 -1
  5. package/dist/build/prerender.js +12 -2
  6. package/dist/check.js +4 -0
  7. package/dist/cli-args.d.ts +2 -1
  8. package/dist/cli-args.js +10 -0
  9. package/dist/cli.js +14 -8
  10. package/dist/client/navigation-runtime.d.ts +6 -0
  11. package/dist/client/navigation-runtime.js +1 -1
  12. package/dist/config/config-matchers.js +4 -1
  13. package/dist/config/dotenv.d.ts +3 -4
  14. package/dist/config/dotenv.js +30 -22
  15. package/dist/config/next-config.d.ts +16 -5
  16. package/dist/config/next-config.js +7 -0
  17. package/dist/entries/app-browser-entry.d.ts +4 -10
  18. package/dist/entries/app-browser-entry.js +20 -4
  19. package/dist/entries/app-rsc-entry.js +21 -3
  20. package/dist/entries/app-rsc-manifest.js +19 -0
  21. package/dist/entries/pages-client-entry.js +0 -1
  22. package/dist/entries/pages-server-entry.js +13 -3
  23. package/dist/index.js +122 -49
  24. package/dist/init-cloudflare.d.ts +3 -1
  25. package/dist/init-cloudflare.js +59 -5
  26. package/dist/plugins/client-reference-dedup.js +7 -5
  27. package/dist/plugins/extensionless-dynamic-import.js +23 -18
  28. package/dist/plugins/ignore-dynamic-requests.js +3 -1
  29. package/dist/plugins/import-meta-url.js +17 -6
  30. package/dist/plugins/require-context.js +20 -15
  31. package/dist/plugins/sass.js +3 -4
  32. package/dist/plugins/transform-cache.d.ts +19 -0
  33. package/dist/plugins/transform-cache.js +36 -0
  34. package/dist/routing/app-route-graph.d.ts +14 -6
  35. package/dist/routing/app-route-graph.js +106 -16
  36. package/dist/server/api-handler.d.ts +2 -0
  37. package/dist/server/api-handler.js +7 -6
  38. package/dist/server/app-bfcache-identity.js +28 -2
  39. package/dist/server/app-browser-entry.js +175 -75
  40. package/dist/server/app-browser-navigation-controller.d.ts +23 -21
  41. package/dist/server/app-browser-navigation-controller.js +30 -5
  42. package/dist/server/app-browser-prefetch-response.d.ts +9 -0
  43. package/dist/server/app-browser-prefetch-response.js +32 -0
  44. package/dist/server/app-browser-state.d.ts +8 -3
  45. package/dist/server/app-browser-state.js +9 -3
  46. package/dist/server/app-page-cache-finalizer.js +1 -1
  47. package/dist/server/app-page-cache.d.ts +1 -1
  48. package/dist/server/app-page-cache.js +16 -2
  49. package/dist/server/app-page-dispatch.d.ts +9 -1
  50. package/dist/server/app-page-dispatch.js +37 -8
  51. package/dist/server/app-page-element-builder.d.ts +4 -1
  52. package/dist/server/app-page-element-builder.js +34 -7
  53. package/dist/server/app-page-head.d.ts +3 -3
  54. package/dist/server/app-page-head.js +58 -13
  55. package/dist/server/app-page-http-access-fallback-metadata.d.ts +2 -2
  56. package/dist/server/app-page-http-access-fallback-metadata.js +9 -1
  57. package/dist/server/app-page-probe.d.ts +4 -0
  58. package/dist/server/app-page-probe.js +6 -2
  59. package/dist/server/app-page-render.d.ts +1 -1
  60. package/dist/server/app-page-render.js +13 -3
  61. package/dist/server/app-page-request.d.ts +3 -1
  62. package/dist/server/app-page-request.js +4 -13
  63. package/dist/server/app-page-response.d.ts +2 -0
  64. package/dist/server/app-page-response.js +7 -2
  65. package/dist/server/app-page-route-wiring.d.ts +10 -2
  66. package/dist/server/app-page-route-wiring.js +269 -59
  67. package/dist/server/app-pages-bridge.d.ts +2 -1
  68. package/dist/server/app-pages-bridge.js +3 -1
  69. package/dist/server/app-route-handler-cache.js +4 -0
  70. package/dist/server/app-route-handler-dispatch.js +9 -3
  71. package/dist/server/app-route-handler-response.js +1 -1
  72. package/dist/server/app-route-module-loader.d.ts +6 -0
  73. package/dist/server/app-route-module-loader.js +3 -0
  74. package/dist/server/app-router-entry.js +6 -3
  75. package/dist/server/app-rsc-cache-busting.d.ts +7 -0
  76. package/dist/server/app-rsc-cache-busting.js +6 -0
  77. package/dist/server/app-rsc-errors.js +10 -0
  78. package/dist/server/app-rsc-handler.d.ts +2 -0
  79. package/dist/server/app-rsc-handler.js +30 -13
  80. package/dist/server/app-rsc-render-mode.d.ts +3 -2
  81. package/dist/server/app-rsc-render-mode.js +4 -1
  82. package/dist/server/app-rsc-request-normalization.js +65 -4
  83. package/dist/server/app-rsc-route-matching.d.ts +9 -0
  84. package/dist/server/app-rsc-route-matching.js +6 -0
  85. package/dist/server/app-server-action-execution.d.ts +1 -1
  86. package/dist/server/app-ssr-entry.js +4 -4
  87. package/dist/server/app-visited-response-cache.d.ts +6 -1
  88. package/dist/server/app-visited-response-cache.js +49 -1
  89. package/dist/server/cache-control.d.ts +2 -2
  90. package/dist/server/cache-control.js +2 -1
  91. package/dist/server/dev-server.d.ts +3 -1
  92. package/dist/server/dev-server.js +204 -348
  93. package/dist/server/edge-api-runtime.d.ts +10 -1
  94. package/dist/server/edge-api-runtime.js +29 -1
  95. package/dist/server/headers.d.ts +4 -2
  96. package/dist/server/headers.js +6 -3
  97. package/dist/server/isr-cache.d.ts +10 -33
  98. package/dist/server/isr-cache.js +33 -43
  99. package/dist/server/isr-decision.d.ts +2 -2
  100. package/dist/server/pages-api-route.d.ts +4 -0
  101. package/dist/server/pages-api-route.js +6 -3
  102. package/dist/server/pages-asset-tags.d.ts +1 -0
  103. package/dist/server/pages-asset-tags.js +6 -4
  104. package/dist/server/pages-dev-hydration.js +0 -1
  105. package/dist/server/pages-document-asset-props.d.ts +26 -0
  106. package/dist/server/pages-document-asset-props.js +69 -0
  107. package/dist/server/pages-get-initial-props.d.ts +1 -1
  108. package/dist/server/pages-get-initial-props.js +1 -4
  109. package/dist/server/pages-i18n.js +64 -16
  110. package/dist/server/pages-node-compat.d.ts +2 -0
  111. package/dist/server/pages-node-compat.js +10 -6
  112. package/dist/server/pages-page-data.d.ts +61 -9
  113. package/dist/server/pages-page-data.js +334 -74
  114. package/dist/server/pages-page-handler.d.ts +6 -1
  115. package/dist/server/pages-page-handler.js +119 -20
  116. package/dist/server/pages-page-response.d.ts +7 -3
  117. package/dist/server/pages-page-response.js +41 -33
  118. package/dist/server/pages-request-pipeline.d.ts +7 -0
  119. package/dist/server/pages-request-pipeline.js +5 -1
  120. package/dist/server/pages-revalidate.d.ts +1 -1
  121. package/dist/server/pages-revalidate.js +54 -8
  122. package/dist/server/pages-router-entry.d.ts +1 -0
  123. package/dist/server/pages-router-entry.js +10 -4
  124. package/dist/server/prerender-manifest.d.ts +1 -0
  125. package/dist/server/prod-server.d.ts +2 -1
  126. package/dist/server/prod-server.js +38 -13
  127. package/dist/server/revalidation-host.d.ts +11 -0
  128. package/dist/server/revalidation-host.js +19 -0
  129. package/dist/server/seed-cache.js +1 -1
  130. package/dist/server/worker-revalidation-context.d.ts +13 -0
  131. package/dist/server/worker-revalidation-context.js +30 -0
  132. package/dist/shims/app-router-scroll-state.d.ts +2 -1
  133. package/dist/shims/app-router-scroll-state.js +7 -2
  134. package/dist/shims/cache-handler.d.ts +1 -1
  135. package/dist/shims/cache-handler.js +10 -7
  136. package/dist/shims/cache-runtime.d.ts +6 -0
  137. package/dist/shims/cache-runtime.js +4 -1
  138. package/dist/shims/cache.js +1 -1
  139. package/dist/shims/document.js +15 -2
  140. package/dist/shims/error.js +1 -1
  141. package/dist/shims/fetch-cache.js +1 -1
  142. package/dist/shims/font-google-base.js +17 -8
  143. package/dist/shims/font-local.js +41 -10
  144. package/dist/shims/hash-scroll.d.ts +1 -1
  145. package/dist/shims/hash-scroll.js +2 -1
  146. package/dist/shims/headers.d.ts +10 -13
  147. package/dist/shims/headers.js +85 -36
  148. package/dist/shims/internal/cookie-serialize.d.ts +10 -9
  149. package/dist/shims/internal/cookie-serialize.js +9 -8
  150. package/dist/shims/internal/interpolate-as.d.ts +15 -1
  151. package/dist/shims/internal/interpolate-as.js +27 -2
  152. package/dist/shims/link.d.ts +2 -0
  153. package/dist/shims/link.js +77 -24
  154. package/dist/shims/metadata.d.ts +18 -34
  155. package/dist/shims/metadata.js +98 -56
  156. package/dist/shims/navigation.d.ts +18 -2
  157. package/dist/shims/navigation.js +70 -21
  158. package/dist/shims/request-context.d.ts +6 -2
  159. package/dist/shims/router.js +18 -7
  160. package/dist/shims/script.js +1 -1
  161. package/dist/shims/server.d.ts +7 -6
  162. package/dist/shims/server.js +156 -57
  163. package/dist/shims/slot.d.ts +2 -1
  164. package/dist/shims/slot.js +6 -2
  165. package/dist/shims/streamed-icons.d.ts +9 -0
  166. package/dist/shims/streamed-icons.js +33 -0
  167. package/dist/shims/unified-request-context.d.ts +21 -2
  168. package/dist/shims/unified-request-context.js +82 -1
  169. package/dist/utils/cache-control-metadata.d.ts +2 -1
  170. package/dist/utils/cache-control-metadata.js +5 -1
  171. package/dist/utils/html-limited-bots.js +1 -1
  172. package/dist/utils/protocol-headers.d.ts +7 -1
  173. package/dist/utils/protocol-headers.js +7 -1
  174. package/package.json +1 -1
@@ -1,13 +1,16 @@
1
1
  import { createAppRenderDependency, registerAppElementRenderDependencies, renderAfterAppDependencies, renderWithAppDependencyBarrier } from "./app-render-dependency.js";
2
- import { APP_STATIC_SIBLINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
3
- import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "./app-rsc-render-mode.js";
2
+ import { APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_STATIC_SIBLINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
3
+ import { APP_RSC_RENDER_MODE_PREFETCH_EMPTY, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "./app-rsc-render-mode.js";
4
4
  import { APP_PREFETCH_LOADING_SHELL_MARKER_KEY } from "./app-elements.js";
5
+ import { createInlineScriptTag, escapeHtmlAttr } from "./html.js";
5
6
  import DefaultGlobalError from "../shims/default-global-error.js";
6
7
  import { ErrorBoundary, ForbiddenBoundary, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
7
8
  import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
9
+ import DefaultNotFound from "../shims/default-not-found.js";
8
10
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
9
11
  import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
10
12
  import { Children as Children$1, ParallelSlot, Slot } from "../shims/slot.js";
13
+ import { StreamedIconsInsertion } from "../shims/streamed-icons.js";
11
14
  import { resolveAppPageBranchParams, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams } from "./app-page-params.js";
12
15
  import { probeReactServerSubtree } from "./app-page-probe.js";
13
16
  import { APP_PAGE_SEGMENT_KEY, resolveAppPageChildSegments, resolveAppPageRouteStateKey, resolveAppPageSegmentStateKey } from "./app-page-segment-state.js";
@@ -16,6 +19,7 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
16
19
  //#region src/server/app-page-route-wiring.tsx
17
20
  const APP_PAGE_LAYOUT_PROBE_CHILD = /* @__PURE__ */ jsx(Fragment, {});
18
21
  const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
22
+ const DEFAULT_NOT_FOUND_COMPONENT = DefaultNotFound;
19
23
  function resolveSlotLayoutParams(routeSegments, treePosition, params) {
20
24
  return resolveAppPageBranchParams(routeSegments, treePosition, params);
21
25
  }
@@ -108,6 +112,66 @@ function createAppPageErrorEntries(route) {
108
112
  }];
109
113
  });
110
114
  }
115
+ function createAppPageLoadingEntries(route) {
116
+ return (route.loadings ?? []).flatMap((loadingModule, index) => {
117
+ if (!loadingModule) return [];
118
+ const treePosition = route.loadingTreePositions?.[index];
119
+ if (treePosition === void 0) return [];
120
+ return [{
121
+ loadingModule,
122
+ treePosition
123
+ }];
124
+ });
125
+ }
126
+ function getPrefetchLoadingEntry(route) {
127
+ let rootEntry = null;
128
+ let firstNestedEntry = null;
129
+ for (const [index, loadingModule] of (route.loadings ?? []).entries()) {
130
+ if (!getDefaultExport(loadingModule)) continue;
131
+ const treePosition = route.loadingTreePositions?.[index];
132
+ if (treePosition === void 0) continue;
133
+ if (treePosition === 0) rootEntry ??= {
134
+ loadingModule,
135
+ treePosition
136
+ };
137
+ else if (firstNestedEntry === null || treePosition < firstNestedEntry.treePosition) firstNestedEntry = {
138
+ loadingModule,
139
+ treePosition
140
+ };
141
+ }
142
+ if (firstNestedEntry) return firstNestedEntry;
143
+ if (rootEntry) return rootEntry;
144
+ return getDefaultExport(route.loading) ? {
145
+ loadingModule: route.loading,
146
+ treePosition: route.routeSegments?.length ?? 0
147
+ } : null;
148
+ }
149
+ function createAppPageSlotLoadingEntries(slot, override) {
150
+ const entries = [];
151
+ const slotLoadingModules = (slot.loadings?.length ?? 0) > 0 ? slot.loadings : slot.loading ? [slot.loading] : [];
152
+ const slotLoadingTreePositions = (slot.loadingTreePositions?.length ?? 0) > 0 ? slot.loadingTreePositions : [0];
153
+ for (const [index, loadingModule] of slotLoadingModules.entries()) {
154
+ const treePosition = slotLoadingTreePositions[index];
155
+ if (!getDefaultExport(loadingModule) || treePosition === void 0) continue;
156
+ if (override && treePosition !== 0) continue;
157
+ entries.push({
158
+ loadingModule,
159
+ treePosition
160
+ });
161
+ }
162
+ for (const [index, loadingModule] of (override?.loadingModules ?? []).entries()) {
163
+ const treePosition = override?.loadingTreePositions?.[index];
164
+ if (!getDefaultExport(loadingModule) || treePosition === void 0) continue;
165
+ entries.push({
166
+ loadingModule,
167
+ treePosition
168
+ });
169
+ }
170
+ return entries;
171
+ }
172
+ function getFirstLoadingEntry(entries) {
173
+ return entries.reduce((first, entry) => first === null || entry.treePosition < first.treePosition ? entry : first, null);
174
+ }
111
175
  function createAppPageParallelSlotEntries(layoutIndex, layoutEntries, route, getEffectiveSlotParams, resolveSlotOverride) {
112
176
  const parallelSlots = {};
113
177
  for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {
@@ -140,6 +204,7 @@ function createAppPageSlotBindings(route, layoutEntries, resolveSlotOverride, op
140
204
  if (route.childrenSlot) {
141
205
  const ownerLayoutId = layoutEntries.find((layoutEntry) => layoutEntry.treePath === route.childrenSlot?.ownerTreePath)?.id;
142
206
  bindings.push({
207
+ ...route.childrenSlot.state === "active" ? { activeRouteId: options.routeId } : {},
143
208
  ownerLayoutId: ownerLayoutId ?? null,
144
209
  slotId: route.childrenSlot.id,
145
210
  state: route.childrenSlot.state
@@ -172,16 +237,40 @@ function createAppPageRouteHead(metadata, viewport, pathname, metadataPlacement,
172
237
  /* @__PURE__ */ jsx(ViewportHead, { viewport })
173
238
  ] });
174
239
  }
175
- function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement, trailingSlash) {
240
+ function hasStreamedIcons(metadata) {
241
+ const icons = metadata.icons;
242
+ if (!icons) return false;
243
+ if (typeof icons === "string" || icons instanceof URL || Array.isArray(icons)) return !Array.isArray(icons) || icons.length > 0;
244
+ if ("url" in icons) return true;
245
+ return Boolean(icons.shortcut || icons.icon || icons.apple || icons.other);
246
+ }
247
+ function createStreamedIconKey(pathname, metadataHtml) {
248
+ let hash = 2166136261;
249
+ for (let index = 0; index < metadataHtml.length; index++) {
250
+ hash ^= metadataHtml.charCodeAt(index);
251
+ hash = Math.imul(hash, 16777619);
252
+ }
253
+ return `${pathname}:${(hash >>> 0).toString(36)}`;
254
+ }
255
+ const STREAMED_ICON_KEY_PLACEHOLDER = "vinext-pending-streamed-icon-key";
256
+ const REINSERT_STREAMED_ICONS_SCRIPT = `document.querySelectorAll('body link[rel="icon"], body link[rel="apple-touch-icon"]').forEach(el => document.head.appendChild(el));const a='data-vinext-streamed-icon',o=el=>{const m=el.getAttribute(a),i=m.lastIndexOf(':');return Number(m.slice(i+1))};[...document.querySelectorAll('link['+a+']')].sort((l,r)=>o(l)-o(r)).forEach(el=>document.head.appendChild(el))`;
257
+ function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement, trailingSlash, scriptNonce) {
176
258
  if (!metadata || metadataPlacement !== "body") return null;
177
- return /* @__PURE__ */ jsx("div", {
178
- hidden: true,
179
- dangerouslySetInnerHTML: { __html: renderMetadataToHtml(metadata, pathname, { trailingSlash }) }
259
+ const streamedIconKey = hasStreamedIcons(metadata) ? STREAMED_ICON_KEY_PLACEHOLDER : void 0;
260
+ const renderedMetadataHtml = renderMetadataToHtml(metadata, pathname, {
261
+ trailingSlash,
262
+ streamedIconKey
180
263
  });
264
+ const metadataKey = streamedIconKey ? createStreamedIconKey(pathname, renderedMetadataHtml) : "";
265
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
266
+ hidden: true,
267
+ suppressHydrationWarning: true,
268
+ dangerouslySetInnerHTML: { __html: (streamedIconKey ? renderedMetadataHtml.replaceAll(`<link data-vinext-streamed-icon="${STREAMED_ICON_KEY_PLACEHOLDER}:`, `<link data-vinext-streamed-icon="${escapeHtmlAttr(metadataKey)}:`) : renderedMetadataHtml) + createInlineScriptTag(REINSERT_STREAMED_ICONS_SCRIPT, scriptNonce) }
269
+ }), /* @__PURE__ */ jsx(StreamedIconsInsertion, { metadataKey })] });
181
270
  }
182
271
  async function AppPageStreamingMetadata(props) {
183
272
  try {
184
- return createAppPageRouteBodyMetadata(await props.metadata, props.pathname, "body", props.trailingSlash);
273
+ return createAppPageRouteBodyMetadata(await props.metadata, props.pathname, "body", props.trailingSlash, props.scriptNonce);
185
274
  } catch {
186
275
  return null;
187
276
  }
@@ -223,13 +312,27 @@ function buildAppPageElements(options) {
223
312
  const streamingMetadataOutletId = options.streamingMetadataOutlet ? `__vinext_streaming_metadata_outlet:${routeId}` : null;
224
313
  const layoutEntries = createAppPageLayoutEntries(options.route);
225
314
  const templateEntries = createAppPageTemplateEntries(options.route);
315
+ const loadingEntries = createAppPageLoadingEntries(options.route);
226
316
  const errorEntries = createAppPageErrorEntries(options.route);
317
+ const findNearestAncestorLoadingEntry = (treePosition) => {
318
+ for (let index = loadingEntries.length - 1; index >= 0; index--) if (loadingEntries[index].treePosition < treePosition) return loadingEntries[index];
319
+ };
320
+ const findNearestLoadingEntryAtOrAbove = (treePosition) => {
321
+ let nearest;
322
+ for (const entry of loadingEntries) if (entry.treePosition <= treePosition && (!nearest || entry.treePosition > nearest.treePosition)) nearest = entry;
323
+ return nearest;
324
+ };
325
+ const isPrefetchEmpty = renderMode === APP_RSC_RENDER_MODE_PREFETCH_EMPTY;
326
+ const isPrefetchLoadingShell = renderMode === APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL;
327
+ const prefetchLoadingEntry = isPrefetchLoadingShell ? getPrefetchLoadingEntry(options.route) : null;
227
328
  const metadataPlacement = options.metadataPlacement ?? "head";
228
329
  const layoutEntriesByTreePosition = /* @__PURE__ */ new Map();
229
330
  const templateEntriesByTreePosition = /* @__PURE__ */ new Map();
331
+ const loadingEntriesByTreePosition = /* @__PURE__ */ new Map();
230
332
  const errorEntriesByTreePosition = /* @__PURE__ */ new Map();
231
333
  for (const layoutEntry of layoutEntries) layoutEntriesByTreePosition.set(layoutEntry.treePosition, layoutEntry);
232
334
  for (const templateEntry of templateEntries) templateEntriesByTreePosition.set(templateEntry.treePosition, templateEntry);
335
+ for (const loadingEntry of loadingEntries) loadingEntriesByTreePosition.set(loadingEntry.treePosition, loadingEntry);
233
336
  for (const errorEntry of errorEntries) errorEntriesByTreePosition.set(errorEntry.treePosition, errorEntry);
234
337
  const layoutIndicesByTreePosition = /* @__PURE__ */ new Map();
235
338
  for (let index = 0; index < layoutEntries.length; index++) layoutIndicesByTreePosition.set(layoutEntries[index].treePosition, index);
@@ -249,6 +352,7 @@ function buildAppPageElements(options) {
249
352
  const orderedTreePositions = Array.from(/* @__PURE__ */ new Set([
250
353
  ...layoutEntries.map((entry) => entry.treePosition),
251
354
  ...templateEntries.map((entry) => entry.treePosition),
355
+ ...loadingEntries.map((entry) => entry.treePosition),
252
356
  ...errorEntries.map((entry) => entry.treePosition)
253
357
  ])).sort((left, right) => left - right);
254
358
  const resolveSlotOverride = (slotKey, slotName) => {
@@ -256,6 +360,11 @@ function buildAppPageElements(options) {
256
360
  if (overrideByKey) return overrideByKey;
257
361
  if (slotKey === slotName || (slotNameCounts.get(slotName) ?? 0) === 1) return options.slotOverrides?.[slotName];
258
362
  };
363
+ const prefetchSlotLoadingEntries = isPrefetchLoadingShell ? Object.entries(options.route.slots ?? {}).flatMap(([slotKey, slot]) => {
364
+ return getFirstLoadingEntry(createAppPageSlotLoadingEntries(slot, resolveSlotOverride(slotKey, slot.name) ?? null)) ? [{ ownerTreePosition: slot.ownerTreePosition ?? 0 }] : [];
365
+ }) : [];
366
+ const prefetchCutoffTreePosition = isPrefetchLoadingShell ? prefetchLoadingEntry?.treePosition ?? prefetchSlotLoadingEntries.reduce((deepest, entry) => Math.max(deepest, entry.ownerTreePosition), 0) : null;
367
+ const includesPrefetchTreePosition = (treePosition) => prefetchCutoffTreePosition === null || treePosition <= prefetchCutoffTreePosition;
259
368
  const elements = { ...AppElementsWire.createMetadataEntries({
260
369
  interception: renderIdentity?.interception ?? options.interception ?? null,
261
370
  interceptionContext,
@@ -266,18 +375,28 @@ function buildAppPageElements(options) {
266
375
  slotBindings: createAppPageSlotBindings(options.route, layoutEntries, resolveSlotOverride, {
267
376
  interception: renderIdentity?.interception ?? options.interception ?? null,
268
377
  interceptionContext,
378
+ routeId,
269
379
  routePath: options.routePath
270
380
  })
271
381
  }) };
382
+ if (isPrefetchEmpty) {
383
+ elements[APP_LAYOUT_IDS_KEY] = [];
384
+ elements[APP_ROOT_LAYOUT_KEY] = null;
385
+ elements[pageElementId] = null;
386
+ elements[routeId] = null;
387
+ return elements;
388
+ }
272
389
  if (options.route.staticSiblings && options.route.staticSiblings.length > 0) elements[APP_STATIC_SIBLINGS_KEY] = options.route.staticSiblings;
273
390
  if (options.streamingMetadata && streamingMetadataBodyId) elements[streamingMetadataBodyId] = /* @__PURE__ */ jsx(AppPageStreamingMetadata, {
274
391
  metadata: options.streamingMetadataTags ?? options.streamingMetadata,
275
392
  pathname: options.resolvedMetadataPathname ?? options.routePath,
393
+ scriptNonce: options.scriptNonce,
276
394
  trailingSlash: options.trailingSlash
277
395
  });
278
396
  if (options.streamingMetadataOutlet && streamingMetadataOutletId) elements[streamingMetadataOutletId] = /* @__PURE__ */ jsx(AppPageMetadataOutlet, { metadata: options.streamingMetadataOutlet });
279
397
  const getEffectiveSlotParams = (slotKey, slotName) => resolveSlotOverride(slotKey, slotName)?.params ?? options.matchedParams;
280
398
  for (const treePosition of orderedTreePositions) {
399
+ if (isPrefetchLoadingShell && !includesPrefetchTreePosition(treePosition)) continue;
281
400
  const layoutIndex = layoutIndicesByTreePosition.get(treePosition);
282
401
  if (layoutIndex !== void 0) {
283
402
  const layoutEntry = layoutEntries[layoutIndex];
@@ -298,19 +417,31 @@ function buildAppPageElements(options) {
298
417
  pageDependencies.push(templateDependency);
299
418
  }
300
419
  const routeLoadingComponent = getDefaultExport(options.route.loading);
301
- const isPrefetchLoadingShell = renderMode === APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL;
302
- if (isPrefetchLoadingShell && routeLoadingComponent !== null) elements[APP_PREFETCH_LOADING_SHELL_MARKER_KEY] = "LoadingBoundary";
420
+ const prefetchLoadingComponent = getDefaultExport(prefetchLoadingEntry?.loadingModule);
421
+ if (isPrefetchLoadingShell && (prefetchLoadingComponent !== null || prefetchSlotLoadingEntries.length > 0)) elements[APP_PREFETCH_LOADING_SHELL_MARKER_KEY] = "LoadingBoundary";
303
422
  elements[pageElementId] = isPrefetchLoadingShell ? null : renderAfterAppDependencies(options.element, pageDependencies);
304
423
  for (const templateEntry of templateEntries) {
424
+ if (isPrefetchLoadingShell && !includesPrefetchTreePosition(templateEntry.treePosition)) continue;
305
425
  const templateComponent = getDefaultExport(templateEntry.templateModule);
306
426
  if (!templateComponent) continue;
307
427
  const TemplateComponent = templateComponent;
308
428
  const templateDependency = templateDependenciesById.get(templateEntry.id);
309
- const templateElement = templateDependency ? renderWithAppDependencyBarrier(/* @__PURE__ */ jsx(TemplateComponent, { children: /* @__PURE__ */ jsx(Children$1, {}) }), templateDependency) : /* @__PURE__ */ jsx(TemplateComponent, { children: /* @__PURE__ */ jsx(Children$1, {}) });
429
+ let templateElement = templateDependency ? renderWithAppDependencyBarrier(/* @__PURE__ */ jsx(TemplateComponent, { children: /* @__PURE__ */ jsx(Children$1, {}) }), templateDependency) : /* @__PURE__ */ jsx(TemplateComponent, { children: /* @__PURE__ */ jsx(Children$1, {}) });
430
+ const ancestorLoadingEntry = findNearestAncestorLoadingEntry(templateEntry.treePosition);
431
+ const ancestorLoadingComponent = getDefaultExport(ancestorLoadingEntry?.loadingModule);
432
+ if (ancestorLoadingComponent && ancestorLoadingEntry) {
433
+ const AncestorLoadingComponent = ancestorLoadingComponent;
434
+ const loadingResetKey = resolveAppPageSegmentStateKey(routeSegments, ancestorLoadingEntry.treePosition, options.matchedParams);
435
+ templateElement = /* @__PURE__ */ jsx(Suspense, {
436
+ fallback: /* @__PURE__ */ jsx(AncestorLoadingComponent, {}),
437
+ children: templateElement
438
+ }, loadingResetKey || routeResetKey);
439
+ }
310
440
  elements[templateEntry.id] = renderAfterAppDependencies(templateElement, templateDependenciesBeforeById.get(templateEntry.id) ?? []);
311
441
  }
312
442
  for (let index = 0; index < layoutEntries.length; index++) {
313
443
  const layoutEntry = layoutEntries[index];
444
+ if (isPrefetchLoadingShell && !includesPrefetchTreePosition(layoutEntry.treePosition)) continue;
314
445
  const layoutComponent = getDefaultExport(layoutEntry.layoutModule);
315
446
  if (!layoutComponent) continue;
316
447
  const layoutParams = resolveAppPageSegmentParams(options.route.routeSegments, layoutEntry.treePosition, options.matchedParams);
@@ -329,79 +460,147 @@ function buildAppPageElements(options) {
329
460
  }
330
461
  const LayoutComponent = layoutComponent;
331
462
  const layoutDependency = layoutDependenciesByIndex.get(index);
332
- const layoutElement = layoutDependency ? renderWithAppDependencyBarrier(/* @__PURE__ */ jsx(LayoutComponent, {
463
+ let layoutElement = layoutDependency ? renderWithAppDependencyBarrier(/* @__PURE__ */ jsx(LayoutComponent, {
333
464
  ...layoutProps,
334
465
  children: /* @__PURE__ */ jsx(Children$1, {})
335
466
  }), layoutDependency) : /* @__PURE__ */ jsx(LayoutComponent, {
336
467
  ...layoutProps,
337
468
  children: /* @__PURE__ */ jsx(Children$1, {})
338
469
  });
470
+ const ancestorLoadingEntry = findNearestAncestorLoadingEntry(layoutEntry.treePosition);
471
+ const ancestorLoadingComponent = getDefaultExport(ancestorLoadingEntry?.loadingModule);
472
+ if (ancestorLoadingComponent && ancestorLoadingEntry) {
473
+ const AncestorLoadingComponent = ancestorLoadingComponent;
474
+ const loadingResetKey = resolveAppPageSegmentStateKey(routeSegments, ancestorLoadingEntry.treePosition, options.matchedParams);
475
+ layoutElement = /* @__PURE__ */ jsx(Suspense, {
476
+ fallback: /* @__PURE__ */ jsx(AncestorLoadingComponent, {}),
477
+ children: layoutElement
478
+ }, loadingResetKey || routeResetKey);
479
+ }
339
480
  elements[layoutEntry.id] = renderAfterAppDependencies(layoutElement, layoutDependenciesBefore[index] ?? []);
340
481
  }
341
482
  for (const [slotKey, slot] of Object.entries(options.route.slots ?? {})) {
342
483
  const slotName = slot.name;
343
484
  const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;
485
+ const targetTreePosition = layoutEntries[targetIndex]?.treePosition ?? 0;
486
+ const ownerTreePosition = slot.ownerTreePosition ?? targetTreePosition;
487
+ const isOwnedAtRoutePrefetchCutoff = isPrefetchLoadingShell && prefetchLoadingEntry !== null && ownerTreePosition === prefetchLoadingEntry.treePosition;
488
+ if (isPrefetchLoadingShell && (prefetchLoadingEntry ? ownerTreePosition > prefetchLoadingEntry.treePosition : !includesPrefetchTreePosition(targetTreePosition))) continue;
344
489
  const slotId = resolveAppPageSlotId(slot, layoutEntries[targetIndex]?.treePath ?? "/");
345
490
  const slotOverride = resolveSlotOverride(slotKey, slotName);
346
491
  const slotParams = getEffectiveSlotParams(slotKey, slotName);
347
492
  const slotRouteSegments = slotOverride?.routeSegments ?? slot.routeSegments ?? [];
348
493
  const slotOwnerParams = resolveAppPageSegmentParams(options.route.routeSegments, layoutEntries[targetIndex]?.treePosition ?? 0, options.matchedParams);
349
494
  const slotResetKey = resolveAppPageRouteStateKey(slotRouteSegments, slotParams);
495
+ const hasSlotTreeOverride = slotOverride?.pageModule != null || slotOverride?.layoutModules !== void 0;
496
+ const slotLoadingEntries = createAppPageSlotLoadingEntries(slot, hasSlotTreeOverride ? slotOverride ?? null : null);
497
+ const prefetchSlotLoadingEntry = isOwnedAtRoutePrefetchCutoff ? prefetchLoadingEntry : isPrefetchLoadingShell ? getFirstLoadingEntry(slotLoadingEntries) : null;
498
+ if (isPrefetchLoadingShell && prefetchSlotLoadingEntry === null) continue;
350
499
  const overrideOrPageComponent = getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page);
351
500
  const defaultComponent = getDefaultExport(slot.default);
352
501
  if (!overrideOrPageComponent && defaultComponent && options.isRscRequest && options.mountedSlotIds?.has(slotId)) continue;
353
502
  const slotComponent = overrideOrPageComponent ?? defaultComponent;
354
- if (!slotComponent) {
503
+ if (!slotComponent && !isOwnedAtRoutePrefetchCutoff) {
355
504
  elements[slotId] = AppElementsWire.unmatchedSlotValue;
356
505
  continue;
357
506
  }
358
- const slotProps = { params: options.makeThenableParams(slotParams) };
359
- if (options.searchParams !== void 0) slotProps.searchParams = options.searchParams;
360
- if (slotOverride?.props) Object.assign(slotProps, slotOverride.props);
361
- let slotElement = options.createPageElement ? options.createPageElement(slotComponent, slotProps) : (() => {
362
- return /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
363
- })();
364
- const hasSlotTreeOverride = slotOverride?.pageModule != null || slotOverride?.layoutModules !== void 0;
365
- const interceptLayouts = slotOverride?.layoutModules ?? [];
366
- for (let layoutIndex = interceptLayouts.length - 1; layoutIndex >= 0; layoutIndex--) {
367
- const interceptLayoutComponent = getDefaultExport(interceptLayouts[layoutIndex]);
368
- if (!interceptLayoutComponent) continue;
369
- const InterceptLayoutComponent = interceptLayoutComponent;
370
- const interceptLayoutParams = resolveSlotLayoutParams(slotOverride?.branchSegments ?? slotRouteSegments, slotOverride?.layoutSegments?.[layoutIndex]?.length ?? slotRouteSegments.length, slotParams);
371
- slotElement = /* @__PURE__ */ jsx(InterceptLayoutComponent, {
372
- params: options.makeThenableParams(interceptLayoutParams),
373
- children: slotElement
507
+ let slotElement;
508
+ if (prefetchSlotLoadingEntry) slotElement = /* @__PURE__ */ jsx(getDefaultExport(prefetchSlotLoadingEntry.loadingModule), {});
509
+ else {
510
+ const slotProps = { params: options.makeThenableParams(slotParams) };
511
+ if (options.searchParams !== void 0) slotProps.searchParams = options.searchParams;
512
+ if (slotOverride?.props) Object.assign(slotProps, slotOverride.props);
513
+ slotElement = options.createPageElement ? options.createPageElement(slotComponent, slotProps) : (() => {
514
+ return /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
515
+ })();
516
+ if (overrideOrPageComponent) slotElement = /* @__PURE__ */ jsx(Fragment, { children: slotElement }, slotResetKey);
517
+ }
518
+ const branchSegments = slotOverride?.branchSegments ?? slotRouteSegments;
519
+ const branchLayouts = /* @__PURE__ */ new Map();
520
+ const addBranchLayout = (treePosition, entry) => {
521
+ const entries = branchLayouts.get(treePosition) ?? [];
522
+ entries.push(entry);
523
+ branchLayouts.set(treePosition, entries);
524
+ };
525
+ if (hasSlotTreeOverride) for (const [layoutIndex, layoutModule] of (slotOverride?.layoutModules ?? []).entries()) {
526
+ const component = getDefaultExport(layoutModule);
527
+ if (!component) continue;
528
+ const treePosition = slotOverride?.layoutSegments?.[layoutIndex]?.length ?? branchSegments.length;
529
+ addBranchLayout(treePosition, {
530
+ component,
531
+ params: resolveSlotLayoutParams(branchSegments, treePosition, slotParams)
374
532
  });
375
533
  }
376
- if (!hasSlotTreeOverride) for (let layoutIndex = (slot.configLayouts?.length ?? 0) - 1; layoutIndex >= 0; layoutIndex--) {
377
- const nestedLayoutComponent = getDefaultExport(slot.configLayouts?.[layoutIndex]);
378
- if (!nestedLayoutComponent) continue;
379
- const NestedLayoutComponent = nestedLayoutComponent;
380
- const nestedLayoutParams = resolveSlotLayoutParams(slotRouteSegments, slot.configLayoutTreePositions?.[layoutIndex] ?? 0, slotParams);
381
- slotElement = /* @__PURE__ */ jsx(NestedLayoutComponent, {
382
- params: options.makeThenableParams({
534
+ else for (const [layoutIndex, layoutModule] of (slot.configLayouts ?? []).entries()) {
535
+ const component = getDefaultExport(layoutModule);
536
+ if (!component) continue;
537
+ const treePosition = slot.configLayoutTreePositions?.[layoutIndex] ?? 0;
538
+ addBranchLayout(treePosition, {
539
+ component,
540
+ params: {
383
541
  ...slotOwnerParams,
384
- ...nestedLayoutParams
385
- }),
386
- children: slotElement
542
+ ...resolveSlotLayoutParams(slotRouteSegments, treePosition, slotParams)
543
+ }
387
544
  });
388
545
  }
389
546
  const slotLayoutComponent = overrideOrPageComponent ? getDefaultExport(slot.layout) : null;
390
- if (slotLayoutComponent) slotElement = /* @__PURE__ */ jsx(slotLayoutComponent, {
391
- params: options.makeThenableParams(slotOwnerParams),
392
- children: slotElement
393
- });
394
- const slotLoadingComponent = getDefaultExport(slot.loading);
395
- if (slotLoadingComponent) slotElement = /* @__PURE__ */ jsx(Suspense, {
396
- fallback: /* @__PURE__ */ jsx(slotLoadingComponent, {}),
397
- children: slotElement
398
- }, slotResetKey);
547
+ if (slotLayoutComponent) {
548
+ const rootEntries = branchLayouts.get(0) ?? [];
549
+ branchLayouts.set(0, [{
550
+ component: slotLayoutComponent,
551
+ params: slotOwnerParams
552
+ }, ...rootEntries]);
553
+ }
554
+ const branchLoadings = /* @__PURE__ */ new Map();
555
+ for (const entry of slotLoadingEntries) {
556
+ const component = getDefaultExport(entry.loadingModule);
557
+ if (!component) continue;
558
+ const components = branchLoadings.get(entry.treePosition) ?? [];
559
+ components.push(component);
560
+ branchLoadings.set(entry.treePosition, components);
561
+ }
399
562
  const slotErrorComponent = getErrorBoundaryExport(slot.error);
400
- if (slotErrorComponent) slotElement = /* @__PURE__ */ jsx(ErrorBoundary, {
401
- resetKey: slotResetKey,
402
- fallback: slotErrorComponent,
403
- children: slotElement
404
- });
563
+ const branchTreePositions = Array.from(/* @__PURE__ */ new Set([
564
+ ...branchLayouts.keys(),
565
+ ...branchLoadings.keys(),
566
+ ...slotErrorComponent ? [0] : []
567
+ ])).filter((treePosition) => !prefetchSlotLoadingEntry || !isOwnedAtRoutePrefetchCutoff && treePosition <= prefetchSlotLoadingEntry.treePosition).sort((left, right) => left - right);
568
+ for (let index = branchTreePositions.length - 1; index >= 0; index--) {
569
+ const treePosition = branchTreePositions[index];
570
+ const loadingComponents = prefetchSlotLoadingEntry ? [] : branchLoadings.get(treePosition) ?? [];
571
+ for (let loadingIndex = loadingComponents.length - 1; loadingIndex >= 0; loadingIndex--) {
572
+ const LoadingComponent = loadingComponents[loadingIndex];
573
+ const loadingResetKey = resolveAppPageSegmentStateKey(branchSegments, treePosition, slotParams);
574
+ slotElement = /* @__PURE__ */ jsx(Suspense, {
575
+ fallback: /* @__PURE__ */ jsx(LoadingComponent, {}),
576
+ children: slotElement
577
+ }, loadingResetKey || slotResetKey);
578
+ }
579
+ if (treePosition === 0 && slotErrorComponent) slotElement = /* @__PURE__ */ jsx(ErrorBoundary, {
580
+ resetKey: slotResetKey,
581
+ fallback: slotErrorComponent,
582
+ children: slotElement
583
+ });
584
+ const layoutEntriesAtPosition = branchLayouts.get(treePosition) ?? [];
585
+ for (let layoutIndex = layoutEntriesAtPosition.length - 1; layoutIndex >= 0; layoutIndex--) {
586
+ const layoutEntry = layoutEntriesAtPosition[layoutIndex];
587
+ const LayoutComponent = layoutEntry.component;
588
+ slotElement = /* @__PURE__ */ jsx(LayoutComponent, {
589
+ params: options.makeThenableParams(layoutEntry.params),
590
+ children: slotElement
591
+ });
592
+ }
593
+ }
594
+ const ownerLoadingEntry = isPrefetchLoadingShell ? void 0 : findNearestLoadingEntryAtOrAbove(ownerTreePosition);
595
+ const ownerLoadingComponent = getDefaultExport(ownerLoadingEntry?.loadingModule);
596
+ if (ownerLoadingComponent && ownerLoadingEntry) {
597
+ const OwnerLoadingComponent = ownerLoadingComponent;
598
+ const ownerResetKey = resolveAppPageSegmentStateKey(routeSegments, ownerLoadingEntry.treePosition, options.matchedParams);
599
+ slotElement = /* @__PURE__ */ jsx(Suspense, {
600
+ fallback: /* @__PURE__ */ jsx(OwnerLoadingComponent, {}),
601
+ children: slotElement
602
+ }, ownerResetKey || slotResetKey);
603
+ }
405
604
  elements[slotId] = renderAfterAppDependencies(slotElement, targetIndex >= 0 ? slotDependenciesByLayoutIndex[targetIndex] ?? [] : []);
406
605
  }
407
606
  let routeChildren = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(LayoutSegmentProvider, {
@@ -409,8 +608,8 @@ function buildAppPageElements(options) {
409
608
  segmentMap: { children: [APP_PAGE_SEGMENT_KEY] },
410
609
  children: /* @__PURE__ */ jsx(Slot, { id: pageElementId })
411
610
  }), createAppPageStreamingMetadataOutlet(streamingMetadataOutletId, options.streamingMetadataOutletSuspended)] });
412
- if (isPrefetchLoadingShell) if (routeLoadingComponent === null) routeChildren = null;
413
- else routeChildren = /* @__PURE__ */ jsx(routeLoadingComponent, {});
611
+ if (isPrefetchLoadingShell) if (prefetchLoadingComponent === null) routeChildren = null;
612
+ else routeChildren = /* @__PURE__ */ jsx(prefetchLoadingComponent, {});
414
613
  else {
415
614
  routeChildren = /* @__PURE__ */ jsx(RedirectBoundary, { children: routeChildren });
416
615
  if (routeLoadingComponent) routeChildren = /* @__PURE__ */ jsx(Suspense, {
@@ -420,7 +619,9 @@ function buildAppPageElements(options) {
420
619
  routeChildren = /* @__PURE__ */ jsx(AppRouterScrollTarget, { children: routeChildren });
421
620
  }
422
621
  const lastLayoutErrorModule = errorEntries.length > 0 ? errorEntries[errorEntries.length - 1].errorModule : null;
423
- const notFoundComponent = getDefaultExport(options.route.notFound) ?? getDefaultExport(options.rootNotFoundModule);
622
+ const configuredNotFoundComponent = getDefaultExport(options.route.notFound) ?? getDefaultExport(options.rootNotFoundModule);
623
+ const defaultNotFoundOwnerLayoutId = configuredNotFoundComponent === null ? layoutEntries[0]?.id ?? null : null;
624
+ const notFoundComponent = configuredNotFoundComponent ?? (defaultNotFoundOwnerLayoutId === null ? DEFAULT_NOT_FOUND_COMPONENT : null);
424
625
  if (notFoundComponent) routeChildren = /* @__PURE__ */ jsx(NotFoundBoundary, {
425
626
  resetKey: routeResetKey,
426
627
  fallback: /* @__PURE__ */ jsx(notFoundComponent, {}),
@@ -444,15 +645,24 @@ function buildAppPageElements(options) {
444
645
  fallback: pageErrorComponent,
445
646
  children: routeChildren
446
647
  });
447
- for (let index = orderedTreePositions.length - 1; index >= 0; index--) {
448
- const treePosition = orderedTreePositions[index];
648
+ const renderedTreePositions = isPrefetchLoadingShell ? orderedTreePositions.filter(includesPrefetchTreePosition) : orderedTreePositions;
649
+ for (let index = renderedTreePositions.length - 1; index >= 0; index--) {
650
+ const treePosition = renderedTreePositions[index];
449
651
  const segmentResetKey = resolveAppPageSegmentStateKey(routeSegments, treePosition, options.matchedParams);
450
652
  let segmentChildren = routeChildren;
451
653
  const layoutEntry = layoutEntriesByTreePosition.get(treePosition);
452
654
  const templateEntry = templateEntriesByTreePosition.get(treePosition);
655
+ const loadingEntry = loadingEntriesByTreePosition.get(treePosition);
453
656
  const errorEntry = errorEntriesByTreePosition.get(treePosition);
657
+ if (!isPrefetchLoadingShell && treePosition < routeSegments.length) {
658
+ const segmentLoadingComponent = getDefaultExport(loadingEntry?.loadingModule);
659
+ if (segmentLoadingComponent) segmentChildren = /* @__PURE__ */ jsx(Suspense, {
660
+ fallback: /* @__PURE__ */ jsx(segmentLoadingComponent, {}),
661
+ children: segmentChildren
662
+ }, segmentResetKey || routeResetKey);
663
+ }
454
664
  if (layoutEntry) {
455
- const layoutNotFoundComponent = getDefaultExport(layoutEntry.notFoundModule);
665
+ const layoutNotFoundComponent = getDefaultExport(layoutEntry.notFoundModule) ?? (layoutEntry.id === defaultNotFoundOwnerLayoutId ? DEFAULT_NOT_FOUND_COMPONENT : null);
456
666
  if (layoutNotFoundComponent) segmentChildren = /* @__PURE__ */ jsx(NotFoundBoundary, {
457
667
  resetKey: segmentResetKey,
458
668
  fallback: /* @__PURE__ */ jsx(layoutNotFoundComponent, {}),
@@ -518,7 +728,7 @@ function buildAppPageElements(options) {
518
728
  elements[routeId] = /* @__PURE__ */ jsxs(Fragment$1, { children: [
519
729
  createAppPageRouteHead(options.resolvedMetadata, options.resolvedViewport, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash),
520
730
  routeChildren,
521
- createAppPageRouteBodyMetadata(options.resolvedMetadata, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash),
731
+ createAppPageRouteBodyMetadata(options.resolvedMetadata, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash, options.scriptNonce),
522
732
  createAppPageStreamingMetadataBody(streamingMetadataBodyId)
523
733
  ] });
524
734
  registerAppElementRenderDependencies(elements, renderDependenciesByElementId);
@@ -1,8 +1,9 @@
1
1
  import { AppMiddlewareContext } from "./app-middleware.js";
2
+ import { EdgeApiExecutionRuntime } from "./edge-api-runtime.js";
2
3
 
3
4
  //#region src/server/app-pages-bridge.d.ts
4
5
  type PagesEntry = {
5
- handleApiRoute?: (request: Request, url: string) => Promise<Response> | Response;
6
+ handleApiRoute?: (request: Request, url: string, ctx: unknown, trustedRevalidateOrigin: string | undefined, edgeRuntime: EdgeApiExecutionRuntime) => Promise<Response> | Response;
6
7
  matchApiRoute?: (url: string, request: Request) => PagesRouteMatch | null;
7
8
  matchPageRoute?: (url: string, request: Request) => PagesRouteMatch | null;
8
9
  renderPage?: (request: Request, url: string, query: Record<string, unknown>, parsedUrl: unknown, middlewareRequestHeaders?: Headers | null, options?: {
@@ -1,3 +1,4 @@
1
+ import { getRequestExecutionContext } from "../shims/request-context.js";
1
2
  import { cloneRequestWithHeaders, cloneRequestWithUrl } from "./request-pipeline.js";
2
3
  import { pagesRouteHasPriorityOverAppRoute } from "./hybrid-route-priority.js";
3
4
  //#region src/server/app-pages-bridge.ts
@@ -26,7 +27,8 @@ async function renderPagesFallback(options, dependencies) {
26
27
  if (appRouteMatch !== null) {
27
28
  if (apiMatch === null || !pagesRouteHasPriorityOverAppRoute(apiMatch.route, appRouteMatch.route)) return null;
28
29
  }
29
- const pagesApiResponse = await pagesEntry.handleApiRoute(pagesRequest, pagesUrl);
30
+ const executionContext = getRequestExecutionContext();
31
+ const pagesApiResponse = await pagesEntry.handleApiRoute(pagesRequest, pagesUrl, void 0, executionContext?.trustedRevalidateOrigin ?? new URL(pagesRequest.url).origin, executionContext?.hostRuntime ?? "node");
30
32
  const draftCookie = getDraftModeCookieHeader();
31
33
  return applyDraftModeCookie(applyRouteHandlerMiddlewareContext(pagesApiResponse, middlewareContext), draftCookie);
32
34
  }
@@ -12,6 +12,10 @@ async function readAppRouteHandlerCacheResponse(options) {
12
12
  try {
13
13
  const cached = await options.isrGet(routeKey);
14
14
  const cachedValue = getCachedAppRouteValue(cached);
15
+ if (cached?.isExpired) {
16
+ options.isrDebug?.("MISS (expired route)", options.cleanPathname);
17
+ return null;
18
+ }
15
19
  if (cachedValue && !cached?.isStale) {
16
20
  options.isrDebug?.("HIT (route)", options.cleanPathname);
17
21
  options.clearRequestContext();
@@ -1,4 +1,4 @@
1
- import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
1
+ import { closeAfterResponse, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
2
2
  import { getRequestExecutionContext } from "../shims/request-context.js";
3
3
  import { reportRequestError } from "./instrumentation.js";
4
4
  import { consumeDynamicUsage, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, isDraftModeRequest, markDynamicUsage, setHeadersAccessPhase } from "../shims/headers.js";
@@ -23,7 +23,7 @@ function buildRouteHandlerPageCacheTags(pathname, extraTags, routeSegments) {
23
23
  return buildPageCacheTags(pathname, extraTags, routeSegments, "route");
24
24
  }
25
25
  async function runInRouteHandlerRevalidationContext(options, renderFn) {
26
- await runWithRequestContext(createRequestContext({
26
+ const requestContext = createRequestContext({
27
27
  headersContext: createStaticGenerationHeadersContext({
28
28
  draftModeEnabled: false,
29
29
  draftModeSecret: options.draftModeSecret,
@@ -33,7 +33,8 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
33
33
  }),
34
34
  executionContext: getRequestExecutionContext(),
35
35
  unstableCacheRevalidation: "foreground"
36
- }), async () => {
36
+ });
37
+ const revalidation = runWithRequestContext(requestContext, async () => {
37
38
  ensureFetchPatch();
38
39
  setCurrentFetchSoftTags(buildRouteHandlerPageCacheTags(options.cleanPathname, [], options.routeSegments));
39
40
  setCurrentFetchCacheMode(options.fetchCacheMode);
@@ -44,6 +45,11 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
44
45
  await _drainPendingRevalidations();
45
46
  }
46
47
  });
48
+ try {
49
+ await revalidation;
50
+ } finally {
51
+ await closeAfterResponse(requestContext);
52
+ }
47
53
  }
48
54
  async function dispatchAppRouteHandler(options) {
49
55
  const { route } = options;
@@ -1,9 +1,9 @@
1
1
  import "../utils/protocol-headers.js";
2
2
  import "./headers.js";
3
3
  import { processMiddlewareHeaders } from "./request-pipeline.js";
4
- import { setCacheStateHeaders } from "./cache-headers.js";
5
4
  import { applyCdnResponseHeaders } from "./cache-control.js";
6
5
  import { buildAppRouteMissIsrCacheControl, decideIsr } from "./isr-decision.js";
6
+ import { setCacheStateHeaders } from "./cache-headers.js";
7
7
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
8
8
  import { getSetCookieName } from "./cookie-utils.js";
9
9
  //#region src/server/app-route-handler-response.ts
@@ -28,6 +28,8 @@ type LazyModuleLoaderArray = readonly (LazyModuleThunk | null | undefined)[];
28
28
  type LazyLoadableIntercept = {
29
29
  interceptLayouts?: readonly unknown[] | null;
30
30
  __loadInterceptLayouts?: LazyModuleLoaderArray | null;
31
+ interceptLoadings?: readonly unknown[] | null;
32
+ __loadInterceptLoadings?: LazyModuleLoaderArray | null;
31
33
  __loadState?: {
32
34
  interceptLayoutsLoading: Promise<readonly unknown[]> | null;
33
35
  };
@@ -38,6 +40,7 @@ type LazyLoadableSlot = {
38
40
  layout?: unknown;
39
41
  configLayouts?: readonly unknown[];
40
42
  loading?: unknown;
43
+ loadings?: readonly unknown[];
41
44
  error?: unknown;
42
45
  notFound?: unknown;
43
46
  __loadPage?: LazyModuleThunk | null;
@@ -45,6 +48,7 @@ type LazyLoadableSlot = {
45
48
  __loadLayout?: LazyModuleThunk | null;
46
49
  __loadConfigLayouts?: LazyModuleLoaderArray | null;
47
50
  __loadLoading?: LazyModuleThunk | null;
51
+ __loadLoadings?: LazyModuleLoaderArray | null;
48
52
  __loadError?: LazyModuleThunk | null;
49
53
  __loadNotFound?: LazyModuleThunk | null; /** Hydrated only after an intercept matches, not with the slot's base modules. */
50
54
  intercepts?: LazyLoadableIntercept[];
@@ -54,6 +58,7 @@ type LazyLoadableRoute = {
54
58
  routeHandler?: unknown;
55
59
  layouts?: unknown[];
56
60
  templates?: unknown[];
61
+ loadings?: unknown[];
57
62
  errors?: unknown[];
58
63
  errorPaths?: unknown[];
59
64
  notFounds?: unknown[];
@@ -70,6 +75,7 @@ type LazyLoadableRoute = {
70
75
  __loadRouteHandler?: LazyModuleThunk | null;
71
76
  __loadLayouts?: LazyModuleLoaderArray | null;
72
77
  __loadTemplates?: LazyModuleLoaderArray | null;
78
+ __loadLoadings?: LazyModuleLoaderArray | null;
73
79
  __loadErrors?: LazyModuleLoaderArray | null;
74
80
  __loadErrorPaths?: LazyModuleLoaderArray | null;
75
81
  __loadNotFounds?: LazyModuleLoaderArray | null;