vinext 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/README.md +72 -1
  2. package/dist/build/app-page-static-eligibility.d.ts +15 -0
  3. package/dist/build/app-page-static-eligibility.js +82 -0
  4. package/dist/build/prerender-paths.js +3 -78
  5. package/dist/build/prerender.js +33 -8
  6. package/dist/build/server-manifest.d.ts +7 -0
  7. package/dist/build/server-manifest.js +11 -1
  8. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  9. package/dist/cache/cache-adapters-virtual.js +3 -3
  10. package/dist/client/navigation-runtime.d.ts +11 -0
  11. package/dist/client/navigation-runtime.js +1 -1
  12. package/dist/config/config-matchers.js +3 -1
  13. package/dist/config/next-config.d.ts +7 -0
  14. package/dist/config/next-config.js +18 -3
  15. package/dist/entries/app-rsc-entry.d.ts +2 -0
  16. package/dist/entries/app-rsc-entry.js +64 -43
  17. package/dist/index.d.ts +4 -1
  18. package/dist/index.js +59 -30
  19. package/dist/plugins/cache-flight-codec.d.ts +19 -0
  20. package/dist/plugins/cache-flight-codec.js +68 -0
  21. package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
  22. package/dist/plugins/commonjs-esm-facade.js +80 -0
  23. package/dist/plugins/fonts.d.ts +8 -11
  24. package/dist/plugins/fonts.js +71 -34
  25. package/dist/routing/file-matcher.d.ts +1 -0
  26. package/dist/routing/file-matcher.js +1 -1
  27. package/dist/server/api-handler.js +17 -7
  28. package/dist/server/app-browser-entry.js +11 -7
  29. package/dist/server/app-browser-history-controller.d.ts +2 -0
  30. package/dist/server/app-browser-history-controller.js +8 -0
  31. package/dist/server/app-browser-interception-context.js +26 -2
  32. package/dist/server/app-browser-navigation-controller.d.ts +7 -1
  33. package/dist/server/app-browser-navigation-controller.js +93 -10
  34. package/dist/server/app-fallback-renderer.d.ts +2 -0
  35. package/dist/server/app-fallback-renderer.js +1 -0
  36. package/dist/server/app-history-state.d.ts +3 -0
  37. package/dist/server/app-history-state.js +7 -0
  38. package/dist/server/app-middleware.js +2 -1
  39. package/dist/server/app-optimistic-routing.js +1 -1
  40. package/dist/server/app-page-boundary-render.d.ts +5 -0
  41. package/dist/server/app-page-boundary-render.js +6 -4
  42. package/dist/server/app-page-cache-finalizer.d.ts +11 -0
  43. package/dist/server/app-page-cache-finalizer.js +41 -7
  44. package/dist/server/app-page-cache-render.d.ts +18 -0
  45. package/dist/server/app-page-cache-render.js +63 -43
  46. package/dist/server/app-page-cache.d.ts +5 -0
  47. package/dist/server/app-page-cache.js +27 -7
  48. package/dist/server/app-page-dispatch.d.ts +9 -1
  49. package/dist/server/app-page-dispatch.js +47 -30
  50. package/dist/server/app-page-element-builder.d.ts +7 -0
  51. package/dist/server/app-page-element-builder.js +27 -42
  52. package/dist/server/app-page-execution.d.ts +15 -12
  53. package/dist/server/app-page-execution.js +30 -40
  54. package/dist/server/app-page-head.d.ts +5 -0
  55. package/dist/server/app-page-head.js +9 -3
  56. package/dist/server/app-page-probe.d.ts +0 -109
  57. package/dist/server/app-page-probe.js +3 -136
  58. package/dist/server/app-page-render-identity.d.ts +0 -1
  59. package/dist/server/app-page-render-identity.js +1 -1
  60. package/dist/server/app-page-render-observation.js +2 -2
  61. package/dist/server/app-page-render.d.ts +13 -5
  62. package/dist/server/app-page-render.js +219 -119
  63. package/dist/server/app-page-request.d.ts +0 -1
  64. package/dist/server/app-page-request.js +1 -2
  65. package/dist/server/app-page-response.d.ts +4 -3
  66. package/dist/server/app-page-response.js +4 -3
  67. package/dist/server/app-page-route-wiring.d.ts +17 -5
  68. package/dist/server/app-page-route-wiring.js +55 -33
  69. package/dist/server/app-page-rsc-render-status.d.ts +48 -0
  70. package/dist/server/app-page-rsc-render-status.js +54 -0
  71. package/dist/server/app-page-stream.d.ts +15 -8
  72. package/dist/server/app-page-stream.js +6 -0
  73. package/dist/server/app-request-stage-dispatch.js +1 -1
  74. package/dist/server/app-request-stage-independent-entry.js +4 -4
  75. package/dist/server/app-response-header-provenance.d.ts +2 -0
  76. package/dist/server/app-response-header-provenance.js +10 -4
  77. package/dist/server/app-route-handler-dispatch.js +1 -1
  78. package/dist/server/app-router-entry.js +3 -3
  79. package/dist/server/app-rsc-handler.d.ts +4 -0
  80. package/dist/server/app-rsc-handler.js +212 -96
  81. package/dist/server/app-rsc-request-normalization.d.ts +3 -1
  82. package/dist/server/app-rsc-request-normalization.js +4 -2
  83. package/dist/server/app-rsc-response-stage.d.ts +1 -1
  84. package/dist/server/app-rsc-response-stage.js +6 -4
  85. package/dist/server/app-rsc-route-matching.d.ts +9 -1
  86. package/dist/server/app-rsc-route-matching.js +36 -19
  87. package/dist/server/app-server-action-execution.js +1 -1
  88. package/dist/server/app-ssr-entry.d.ts +3 -2
  89. package/dist/server/app-ssr-entry.js +6 -4
  90. package/dist/server/app-ssr-stream.d.ts +6 -1
  91. package/dist/server/app-ssr-stream.js +34 -15
  92. package/dist/server/app-worker-stages.d.ts +2 -2
  93. package/dist/server/app-worker-stages.js +3 -3
  94. package/dist/server/cacheability-request.js +9 -5
  95. package/dist/server/config-headers.js +2 -0
  96. package/dist/server/dev-server.js +12 -2
  97. package/dist/server/headers.d.ts +14 -0
  98. package/dist/server/headers.js +15 -1
  99. package/dist/server/image-optimization.d.ts +16 -0
  100. package/dist/server/image-optimization.js +26 -6
  101. package/dist/server/isr-cache.js +2 -2
  102. package/dist/server/middleware-matcher-pattern.js +8 -4
  103. package/dist/server/middleware-response-headers.js +2 -0
  104. package/dist/server/multi-stage.d.ts +8 -0
  105. package/dist/server/navigation-planner.js +1 -1
  106. package/dist/server/node-response-signal.d.ts +16 -0
  107. package/dist/server/node-response-signal.js +26 -0
  108. package/dist/server/open-redirect.d.ts +47 -0
  109. package/dist/server/open-redirect.js +74 -1
  110. package/dist/server/pages-page-handler.js +21 -4
  111. package/dist/server/pages-request-stage-entry.js +8 -4
  112. package/dist/server/prod-server.d.ts +8 -7
  113. package/dist/server/prod-server.js +153 -69
  114. package/dist/server/request-pipeline.d.ts +20 -8
  115. package/dist/server/request-pipeline.js +21 -7
  116. package/dist/server/response-compression.d.ts +43 -0
  117. package/dist/server/response-compression.js +111 -0
  118. package/dist/server/seed-cache.js +10 -7
  119. package/dist/server/socket-error-backstop.d.ts +14 -0
  120. package/dist/server/socket-error-backstop.js +27 -4
  121. package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
  122. package/dist/shims/cache-adapter-instantiate.js +118 -0
  123. package/dist/shims/cache-callable-runtime.d.ts +2 -40
  124. package/dist/shims/cache-callable-runtime.js +50 -168
  125. package/dist/shims/cache-flight-arguments.d.ts +22 -0
  126. package/dist/shims/cache-flight-arguments.js +56 -0
  127. package/dist/shims/cache-request-state.d.ts +15 -0
  128. package/dist/shims/cache-request-state.js +31 -8
  129. package/dist/shims/cache-runtime.d.ts +6 -19
  130. package/dist/shims/cache-runtime.js +165 -225
  131. package/dist/shims/cache.d.ts +2 -2
  132. package/dist/shims/cache.js +5 -4
  133. package/dist/shims/cacheability-classification.d.ts +7 -0
  134. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  135. package/dist/shims/error-boundary-navigation.js +19 -1
  136. package/dist/shims/error-boundary.d.ts +10 -10
  137. package/dist/shims/error-boundary.js +26 -7
  138. package/dist/shims/fetch-cache.d.ts +6 -0
  139. package/dist/shims/fetch-cache.js +19 -1
  140. package/dist/shims/form.js +1 -1
  141. package/dist/shims/headers.d.ts +13 -0
  142. package/dist/shims/headers.js +47 -4
  143. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
  144. package/dist/shims/internal/app-page-props-cache-key.js +24 -15
  145. package/dist/shims/internal/headers-state.d.ts +0 -1
  146. package/dist/shims/metadata.js +3 -3
  147. package/dist/shims/navigation-errors.d.ts +6 -0
  148. package/dist/shims/navigation-errors.js +11 -1
  149. package/dist/shims/navigation.d.ts +7 -0
  150. package/dist/shims/navigation.js +14 -4
  151. package/dist/shims/request-context.d.ts +9 -0
  152. package/dist/shims/thenable-params.d.ts +4 -0
  153. package/dist/shims/thenable-params.js +25 -3
  154. package/dist/shims/unified-request-context.js +1 -0
  155. package/dist/utils/mdx-scan.d.ts +5 -0
  156. package/dist/utils/mdx-scan.js +8 -1
  157. package/dist/utils/regex-safety.d.ts +10 -0
  158. package/dist/utils/regex-safety.js +70 -18
  159. package/package.json +3 -3
@@ -1,14 +1,15 @@
1
1
  import { fnv1a64 } from "../utils/hash.js";
2
2
  import { APP_RSC_RENDER_MODE_PREFETCH_EMPTY, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "./app-rsc-render-mode.js";
3
+ import { createInlineScriptTag, escapeHtmlAttr } from "./html.js";
3
4
  import { createAppRenderDependency, registerAppElementRenderDependencies, renderAfterAppDependencies, renderAppComponentWithDependencyBarrier } from "./app-render-dependency.js";
4
5
  import { APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_STATIC_SIBLINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
5
6
  import { APP_PREFETCH_LOADING_SHELL_MARKER_KEY } from "./app-elements.js";
6
- import { createInlineScriptTag, escapeHtmlAttr } from "./html.js";
7
7
  import DefaultGlobalError from "../shims/default-global-error.js";
8
8
  import { ErrorBoundary, ForbiddenBoundary, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
9
9
  import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
10
10
  import DefaultNotFound from "../shims/default-not-found.js";
11
11
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
12
+ import { withUseCacheLayoutMarker } from "../shims/internal/app-page-props-cache-key.js";
12
13
  import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
13
14
  import { BfcacheSegmentBoundary, Children as Children$1, ParallelSlot, Slot } from "../shims/slot.js";
14
15
  import { StreamedIconsInsertion } from "../shims/streamed-icons.js";
@@ -64,7 +65,7 @@ function probeAppPageLayoutWithTracking(options) {
64
65
  });
65
66
  const layoutParams = resolveAppPageSegmentParams(options.route.routeSegments, treePosition, options.matchedParams);
66
67
  return probeReactServerSubtree(/* @__PURE__ */ jsx(LayoutComponent, {
67
- params: options.makeThenableParams(layoutParams, options.layoutParamAccess?.createThenableParamsObserver(layoutId)),
68
+ ...withUseCacheLayoutMarker(LayoutComponent, { params: options.makeThenableParams(layoutParams, options.layoutParamAccess?.createThenableParamsObserver(layoutId)) }),
68
69
  children: APP_PAGE_LAYOUT_PROBE_CHILD
69
70
  }));
70
71
  };
@@ -179,6 +180,14 @@ function createAppPageSlotLoadingEntries(slot, override) {
179
180
  }
180
181
  return entries;
181
182
  }
183
+ /**
184
+ * Only an override that replaces the slot's page or layouts changes its tree.
185
+ * A params-only override, as built for an inherited slot with its own param
186
+ * names, keeps the slot's nested loading boundaries.
187
+ */
188
+ function getAppPageSlotTreeOverride(override) {
189
+ return override?.pageModule != null || override?.layoutModules !== void 0 ? override ?? null : null;
190
+ }
182
191
  function getFirstLoadingEntry(entries) {
183
192
  return entries.reduce((first, entry) => first === null || entry.treePosition < first.treePosition ? entry : first, null);
184
193
  }
@@ -242,17 +251,24 @@ function createAppPageSlotBindings(route, layoutEntries, resolveSlotOverride, op
242
251
  }
243
252
  return normalizeAppElementsSlotBindings(bindings, { layoutIds: layoutEntries.map((entry) => entry.id) });
244
253
  }
245
- function createAppPageRouteHead(metadata, viewport, pathname, metadataPlacement, trailingSlash) {
246
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
247
- /* @__PURE__ */ jsx("meta", { charSet: "utf-8" }),
248
- metadata && metadataPlacement === "head" ? /* @__PURE__ */ jsx(MetadataHead, {
249
- metadata,
250
- pathname,
251
- trailingSlash
252
- }) : null,
253
- /* @__PURE__ */ jsx(ViewportHead, { viewport })
254
- ] });
254
+ function createAppPageRouteHead(resolveHead, pathname, metadataPlacement, trailingSlash) {
255
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("meta", { charSet: "utf-8" }), resolveHead ? /* @__PURE__ */ jsx(AppPageHead, {
256
+ metadataPlacement,
257
+ pathname,
258
+ resolveHead,
259
+ trailingSlash
260
+ }) : /* @__PURE__ */ jsx(ViewportHead, { viewport: {} })] });
261
+ }
262
+ async function AppPageHead(props) {
263
+ const head = props.resolveHead();
264
+ const [metadata, viewport] = await Promise.all([props.metadataPlacement === "head" ? head.metadata : null, head.viewport]);
265
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [metadata ? /* @__PURE__ */ jsx(MetadataHead, {
266
+ metadata,
267
+ pathname: props.pathname,
268
+ trailingSlash: props.trailingSlash
269
+ }) : null, /* @__PURE__ */ jsx(ViewportHead, { viewport })] });
255
270
  }
271
+ AppPageHead.displayName = "Vinext.Head";
256
272
  function hasStreamedIcons(metadata) {
257
273
  const icons = metadata.icons;
258
274
  if (!icons) return false;
@@ -282,15 +298,14 @@ function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement, t
282
298
  }
283
299
  async function AppPageStreamingMetadata(props) {
284
300
  try {
285
- return createAppPageRouteBodyMetadata(await props.metadata, props.pathname, "body", props.trailingSlash, props.scriptNonce);
301
+ return createAppPageRouteBodyMetadata(await props.resolveHead().metadata, props.pathname, "body", props.trailingSlash, props.scriptNonce);
286
302
  } catch {
287
303
  return null;
288
304
  }
289
305
  }
290
306
  AppPageStreamingMetadata.displayName = "Vinext.StreamingMetadata";
291
307
  async function AppPageMetadataOutlet(props) {
292
- await props.metadata;
293
- return null;
308
+ return props.resolveHead().outlet;
294
309
  }
295
310
  AppPageMetadataOutlet.displayName = "Vinext.MetadataOutlet";
296
311
  function createAppPageStreamingMetadataOutlet(elementId, suspended = true) {
@@ -319,8 +334,8 @@ function buildAppPageElements(options) {
319
334
  const routeId = renderIdentity?.routeId ?? AppElementsWire.encodeRouteId(options.routePath, interceptionContext);
320
335
  const pageId = renderIdentity?.pageId ?? AppElementsWire.encodePageId(options.routePath, interceptionContext);
321
336
  const pageElementId = options.route.childrenSlot ? resolveAppPageChildrenSlotId(options.route.childrenSlot) : pageId;
322
- const streamingMetadataBodyId = options.streamingMetadata ? `__vinext_streaming_metadata_body:${routeId}` : null;
323
- const streamingMetadataOutletId = options.streamingMetadataOutlet ? `__vinext_streaming_metadata_outlet:${routeId}` : null;
337
+ const metadataPlacement = options.metadataPlacement ?? "head";
338
+ const streamingMetadataOutletId = options.resolveHead ? `__vinext_streaming_metadata_outlet:${routeId}` : null;
324
339
  const layoutEntries = createAppPageLayoutEntries(options.route);
325
340
  const templateEntries = createAppPageTemplateEntries(options.route);
326
341
  const loadingEntries = createAppPageLoadingEntries(options.route);
@@ -337,7 +352,6 @@ function buildAppPageElements(options) {
337
352
  const isPrefetchLoadingShell = renderMode === APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL;
338
353
  const pageRenderDependency = isPrefetchLoadingShell ? null : options.pageRenderDependency;
339
354
  const prefetchLoadingEntry = isPrefetchLoadingShell ? getPrefetchLoadingEntry(options.route) : null;
340
- const metadataPlacement = options.metadataPlacement ?? "head";
341
355
  const layoutEntriesByTreePosition = /* @__PURE__ */ new Map();
342
356
  const templateEntriesByTreePosition = /* @__PURE__ */ new Map();
343
357
  const loadingEntriesByTreePosition = /* @__PURE__ */ new Map();
@@ -380,8 +394,11 @@ function buildAppPageElements(options) {
380
394
  routePath: options.routePath
381
395
  });
382
396
  const prefetchSlotLoadingEntries = isPrefetchLoadingShell ? Object.entries(options.route.slots ?? {}).flatMap(([slotKey, slot]) => {
383
- return getFirstLoadingEntry(createAppPageSlotLoadingEntries(slot, resolveSlotOverride(slotKey, slot.name) ?? null)) ? [{ ownerTreePosition: slot.ownerTreePosition ?? 0 }] : [];
397
+ return getFirstLoadingEntry(createAppPageSlotLoadingEntries(slot, getAppPageSlotTreeOverride(resolveSlotOverride(slotKey, slot.name)))) ? [{ ownerTreePosition: slot.ownerTreePosition ?? 0 }] : [];
384
398
  }) : [];
399
+ const prefetchLoadingComponent = getDefaultExport(prefetchLoadingEntry?.loadingModule);
400
+ const shouldRenderPrefetchLoadingShell = isPrefetchLoadingShell && (prefetchLoadingComponent !== null || prefetchSlotLoadingEntries.length > 0);
401
+ const streamingMetadataBodyId = options.resolveHead && metadataPlacement === "body" && (!isPrefetchLoadingShell || shouldRenderPrefetchLoadingShell) ? `__vinext_streaming_metadata_body:${routeId}` : null;
385
402
  const prefetchCutoffTreePosition = isPrefetchLoadingShell ? prefetchLoadingEntry?.treePosition ?? prefetchSlotLoadingEntries.reduce((deepest, entry) => Math.max(deepest, entry.ownerTreePosition), 0) : null;
386
403
  const includesPrefetchTreePosition = (treePosition) => prefetchCutoffTreePosition === null || treePosition <= prefetchCutoffTreePosition;
387
404
  const segmentPlan = createAppPageSegmentPlan({
@@ -426,13 +443,13 @@ function buildAppPageElements(options) {
426
443
  const elements = {};
427
444
  for (const slotPlan of segmentPlan.slots) for (const segment of slotPlan.nestedBfcacheSegments) elements[segment.id] = null;
428
445
  if (options.route.staticSiblings && options.route.staticSiblings.length > 0) elements[APP_STATIC_SIBLINGS_KEY] = options.route.staticSiblings;
429
- if (options.streamingMetadata && streamingMetadataBodyId) elements[streamingMetadataBodyId] = /* @__PURE__ */ jsx(AppPageStreamingMetadata, {
430
- metadata: options.streamingMetadataTags ?? options.streamingMetadata,
446
+ if (options.resolveHead && streamingMetadataBodyId) elements[streamingMetadataBodyId] = /* @__PURE__ */ jsx(AppPageStreamingMetadata, {
431
447
  pathname: options.resolvedMetadataPathname ?? options.routePath,
448
+ resolveHead: options.resolveHead,
432
449
  scriptNonce: options.scriptNonce,
433
450
  trailingSlash: options.trailingSlash
434
451
  });
435
- if (options.streamingMetadataOutlet && streamingMetadataOutletId) elements[streamingMetadataOutletId] = /* @__PURE__ */ jsx(AppPageMetadataOutlet, { metadata: options.streamingMetadataOutlet });
452
+ if (options.resolveHead && streamingMetadataOutletId) elements[streamingMetadataOutletId] = /* @__PURE__ */ jsx(AppPageMetadataOutlet, { resolveHead: options.resolveHead });
436
453
  const getEffectiveSlotParams = (slotKey, _slotName) => slotPlansByKey.get(slotKey)?.params ?? options.matchedParams;
437
454
  for (const treePosition of orderedTreePositions) {
438
455
  if (isPrefetchLoadingShell && !includesPrefetchTreePosition(treePosition)) continue;
@@ -457,8 +474,6 @@ function buildAppPageElements(options) {
457
474
  }
458
475
  pageRenderDependency?.setResultDependencies(pageDependencies);
459
476
  const routeLoadingComponent = getDefaultExport(options.route.loading);
460
- const prefetchLoadingComponent = getDefaultExport(prefetchLoadingEntry?.loadingModule);
461
- const shouldRenderPrefetchLoadingShell = isPrefetchLoadingShell && (prefetchLoadingComponent !== null || prefetchSlotLoadingEntries.length > 0);
462
477
  if (shouldRenderPrefetchLoadingShell) elements[APP_PREFETCH_LOADING_SHELL_MARKER_KEY] = "LoadingBoundary";
463
478
  const pageLoadingModule = resolveAppPageLoadingModuleAtOrAbove(options.route, routeSegments.length);
464
479
  const PageLoadingComponent = pageRenderDependency ? getDefaultExport(pageLoadingModule) : null;
@@ -508,11 +523,11 @@ function buildAppPageElements(options) {
508
523
  }
509
524
  const LayoutComponent = layoutComponent;
510
525
  const layoutDependency = layoutDependenciesByIndex.get(index);
511
- let layoutElement = layoutDependency ? renderAppComponentWithDependencyBarrier(LayoutComponent, {
526
+ let layoutElement = layoutDependency ? renderAppComponentWithDependencyBarrier(LayoutComponent, withUseCacheLayoutMarker(LayoutComponent, {
512
527
  ...layoutProps,
513
528
  children: /* @__PURE__ */ jsx(Children$1, {})
514
- }, layoutDependency) : /* @__PURE__ */ jsx(LayoutComponent, {
515
- ...layoutProps,
529
+ }), layoutDependency) : /* @__PURE__ */ jsx(LayoutComponent, {
530
+ ...withUseCacheLayoutMarker(LayoutComponent, layoutProps),
516
531
  children: /* @__PURE__ */ jsx(Children$1, {})
517
532
  });
518
533
  const ancestorLoadingEntry = findNearestAncestorLoadingEntry(layoutEntry.treePosition);
@@ -532,8 +547,9 @@ function buildAppPageElements(options) {
532
547
  const isOwnedAtRoutePrefetchCutoff = isPrefetchLoadingShell && prefetchLoadingEntry !== null && ownerTreePosition === prefetchLoadingEntry.treePosition;
533
548
  if (!includedInPayload) continue;
534
549
  const slotOwnerParams = resolveAppPageSegmentParams(options.route.routeSegments, layoutEntries[targetIndex]?.treePosition ?? 0, options.matchedParams);
535
- const hasSlotTreeOverride = slotOverride?.pageModule != null || slotOverride?.layoutModules !== void 0;
536
- const slotLoadingEntries = createAppPageSlotLoadingEntries(slot, hasSlotTreeOverride ? slotOverride ?? null : null);
550
+ const slotTreeOverride = getAppPageSlotTreeOverride(slotOverride);
551
+ const hasSlotTreeOverride = slotTreeOverride !== null;
552
+ const slotLoadingEntries = createAppPageSlotLoadingEntries(slot, slotTreeOverride);
537
553
  const prefetchSlotLoadingEntry = isOwnedAtRoutePrefetchCutoff ? prefetchLoadingEntry : isPrefetchLoadingShell ? getFirstLoadingEntry(slotLoadingEntries) : null;
538
554
  if (isPrefetchLoadingShell && prefetchSlotLoadingEntry === null) continue;
539
555
  const resolvedOverrideOrPageComponent = slotOverride?.pageModule || slot.page ? traceGetLayoutOrPageModule(APP_PAGE_SEGMENT_KEY, () => getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page)) : null;
@@ -557,6 +573,10 @@ function buildAppPageElements(options) {
557
573
  return /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
558
574
  })();
559
575
  if (overrideOrPageComponent) slotElement = /* @__PURE__ */ jsx(Fragment, { children: slotElement }, slotResetKey);
576
+ slotElement = /* @__PURE__ */ jsx(RedirectBoundary, {
577
+ resetKey: slotResetKey,
578
+ children: slotElement
579
+ });
560
580
  }
561
581
  const branchLayouts = /* @__PURE__ */ new Map();
562
582
  const addBranchLayout = (treePosition, entry) => {
@@ -637,7 +657,7 @@ function buildAppPageElements(options) {
637
657
  const layoutEntry = layoutEntriesAtPosition[layoutIndex];
638
658
  const LayoutComponent = layoutEntry.component;
639
659
  slotElement = /* @__PURE__ */ jsx(LayoutComponent, {
640
- params: options.makeThenableParams(layoutEntry.params),
660
+ ...withUseCacheLayoutMarker(LayoutComponent, { params: options.makeThenableParams(layoutEntry.params) }),
641
661
  children: slotElement
642
662
  });
643
663
  }
@@ -669,7 +689,10 @@ function buildAppPageElements(options) {
669
689
  if (prefetchLoadingComponent === null) routeChildren = null;
670
690
  else routeChildren = /* @__PURE__ */ jsx(prefetchLoadingComponent, {});
671
691
  } else {
672
- routeChildren = /* @__PURE__ */ jsx(RedirectBoundary, { children: routeChildren });
692
+ routeChildren = /* @__PURE__ */ jsx(RedirectBoundary, {
693
+ resetKey: routeResetKey,
694
+ children: routeChildren
695
+ });
673
696
  if (routeLoadingComponent) routeChildren = /* @__PURE__ */ jsx(Suspense, {
674
697
  fallback: /* @__PURE__ */ jsx(routeLoadingComponent, {}),
675
698
  children: routeChildren
@@ -787,9 +810,8 @@ function buildAppPageElements(options) {
787
810
  }) : routeChildren
788
811
  });
789
812
  const routeElement = /* @__PURE__ */ jsxs(Fragment$1, { children: [
790
- createAppPageRouteHead(options.resolvedMetadata, options.resolvedViewport, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash),
813
+ createAppPageRouteHead(options.resolveHead, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash),
791
814
  routeChildren,
792
- createAppPageRouteBodyMetadata(options.resolvedMetadata, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash, options.scriptNonce),
793
815
  createAppPageStreamingMetadataBody(streamingMetadataBodyId)
794
816
  ] });
795
817
  elements[routeId] = pageRenderDependency ? renderAfterAppDependencies(routeElement, [pageRenderDependency]) : routeElement;
@@ -0,0 +1,48 @@
1
+ import { NavigationContext } from "../shims/navigation-context-state.js";
2
+ import "../shims/navigation.js";
3
+ import { RootParams } from "../shims/root-params.js";
4
+ import { AppPageSsrHandler } from "./app-page-stream.js";
5
+ //#region src/server/app-page-rsc-render-status.d.ts
6
+ /**
7
+ * The status of a finished RSC render, as Next.js's static generation decides
8
+ * it from the document's shell. A special error that rejects the shell sets
9
+ * it. One inside a Suspense boundary leaves the render a 200.
10
+ */
11
+ export type AppPageRscRenderStatus = {
12
+ kind: "page";
13
+ } | {
14
+ kind: "special-error";
15
+ status: number;
16
+ headers?: Record<string, string>;
17
+ } |
18
+ /**
19
+ * A render not stored: another error rejected the shell, or
20
+ * generateMetadata()'s special error, whose document an RSC miss can't write.
21
+ */
22
+ {
23
+ kind: "unstorable";
24
+ };
25
+ type CreateAppPageRscRenderStatusResolverOptions = {
26
+ basePath?: string;
27
+ capturedRscData: Promise<ArrayBuffer>;
28
+ getCapturedSpecialError: () => unknown;
29
+ getCapturedSpecialErrors: (error: unknown) => readonly unknown[];
30
+ isForceStatic: boolean;
31
+ loadSsrHandler: () => Promise<AppPageSsrHandler>;
32
+ navigationContext: NavigationContext | null;
33
+ rootParams?: RootParams;
34
+ };
35
+ /**
36
+ * Resolve an RSC-only render's status once its Flight payload is complete.
37
+ * Flight can't tell whether a special error sits inside a Suspense boundary, so
38
+ * a render that threw one renders the document's shell from the same payload,
39
+ * as Next.js's static generation renders HTML beside RSC. Its server
40
+ * components don't run again. A render without a special error is a 200.
41
+ */
42
+ export declare function createAppPageRscRenderStatusResolver(options: CreateAppPageRscRenderStatusResolverOptions): () => Promise<AppPageRscRenderStatus>;
43
+ /**
44
+ * The status Next.js sends an RSC request for a render with this status. Its
45
+ * payload carries a redirect, so a redirect is a 200 with its `location`.
46
+ */
47
+ export declare function resolveAppPageRscResponseStatus(status: number): number;
48
+ //#endregion
@@ -0,0 +1,54 @@
1
+ import { resolveAppPageShellSpecialError, resolveAppPageSpecialErrorStoredHeaders } from "./app-page-execution.js";
2
+ import { isAppSsrRenderResult } from "./app-page-stream.js";
3
+ //#region src/server/app-page-rsc-render-status.ts
4
+ const PAGE_STATUS = { kind: "page" };
5
+ /**
6
+ * Resolve an RSC-only render's status once its Flight payload is complete.
7
+ * Flight can't tell whether a special error sits inside a Suspense boundary, so
8
+ * a render that threw one renders the document's shell from the same payload,
9
+ * as Next.js's static generation renders HTML beside RSC. Its server
10
+ * components don't run again. A render without a special error is a 200.
11
+ */
12
+ function createAppPageRscRenderStatusResolver(options) {
13
+ let status;
14
+ return () => status ??= resolveAppPageRscRenderStatus(options);
15
+ }
16
+ async function resolveAppPageRscRenderStatus(options) {
17
+ const rscData = await options.capturedRscData;
18
+ if (options.getCapturedSpecialError() === null) return PAGE_STATUS;
19
+ const ssrHandler = await options.loadSsrHandler();
20
+ let rendered;
21
+ try {
22
+ rendered = await ssrHandler.handleSsr(new Response(rscData).body, options.navigationContext, {
23
+ links: [],
24
+ preloads: [],
25
+ styles: []
26
+ }, {
27
+ basePath: options.basePath,
28
+ isForceStatic: options.isForceStatic,
29
+ isStaticGeneration: true,
30
+ onSsrError: () => void 0,
31
+ rootParams: options.rootParams
32
+ });
33
+ } catch (error) {
34
+ const specialError = resolveAppPageShellSpecialError(error, options.getCapturedSpecialErrors(error));
35
+ if (!specialError || specialError.fromMetadata === true) return { kind: "unstorable" };
36
+ const headers = resolveAppPageSpecialErrorStoredHeaders(specialError, options.basePath);
37
+ return {
38
+ kind: "special-error",
39
+ status: specialError.statusCode,
40
+ ...headers ? { headers } : {}
41
+ };
42
+ }
43
+ (isAppSsrRenderResult(rendered) ? rendered.htmlStream : rendered).cancel().catch(() => {});
44
+ return PAGE_STATUS;
45
+ }
46
+ /**
47
+ * The status Next.js sends an RSC request for a render with this status. Its
48
+ * payload carries a redirect, so a redirect is a 200 with its `location`.
49
+ */
50
+ function resolveAppPageRscResponseStatus(status) {
51
+ return status >= 300 && status < 400 ? 200 : status;
52
+ }
53
+ //#endregion
54
+ export { createAppPageRscRenderStatusResolver, resolveAppPageRscResponseStatus };
@@ -83,8 +83,9 @@ export type AppPageSsrHandler = {
83
83
  initialDevServerError?: unknown;
84
84
  /** Report an SSR/Fizz render failure through instrumentation. */
85
85
  onSsrError?: (error: unknown) => unknown;
86
- /** Mirror inline Flight chunks into Next.js's `self.__next_f` transport. */
87
- mirrorNextFlight?: boolean;
86
+ /** Mirror inline Flight chunks into Next.js's `self.__next_f` transport, or start
87
+ * mirroring once a function returns true. */
88
+ mirrorNextFlight?: boolean | (() => boolean);
88
89
  /** When true, an SSR-phase-only shell render error resolves to the
89
90
  * default `__next_error__` error-document shell (with the original
90
91
  * flight payload and bootstrap) instead of rejecting. See handleSsr. */
@@ -141,8 +142,9 @@ type RenderAppPageHtmlStreamOptions = {
141
142
  initialDevServerError?: unknown;
142
143
  /** Report an SSR/Fizz render failure through instrumentation. */
143
144
  onSsrError?: (error: unknown) => unknown;
144
- /** Mirror inline Flight chunks into Next.js's `self.__next_f` transport. */
145
- mirrorNextFlight?: boolean;
145
+ /** Mirror inline Flight chunks into Next.js's `self.__next_f` transport, or start
146
+ * mirroring once a function returns true. */
147
+ mirrorNextFlight?: boolean | (() => boolean);
146
148
  /** True when the app supplies a custom global-error.tsx. Disables the
147
149
  * default error-document shell fallback so SSR shell errors keep driving
148
150
  * the server-rendered global-error boundary re-render. */
@@ -175,12 +177,17 @@ type RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError> = {
175
177
  type AppPageRscErrorTracker = {
176
178
  getCapturedError: () => unknown;
177
179
  /**
178
- * Returns a NEXT_REDIRECT or NEXT_HTTP_ERROR_FALLBACK error captured during
179
- * the RSC render. Read after the SSR shell promise resolves to swap a
180
- * 307/404 in place of the streamed body when redirect()/notFound() throws
181
- * synchronously inside a route-level Suspense boundary (loading.tsx).
180
+ * Returns the first NEXT_REDIRECT or NEXT_HTTP_ERROR_FALLBACK error captured
181
+ * during the RSC render, if any. Whether it set the render's status depends
182
+ * on whether it rejected the document's shell.
182
183
  */
183
184
  getCapturedSpecialError: () => unknown;
185
+ /**
186
+ * The special errors the RSC render threw with the digest of `error`. The
187
+ * SSR shell rejects with its own copy, decoded from the Flight digest, which
188
+ * loses server-side markers such as generateMetadata()'s.
189
+ */
190
+ getCapturedSpecialErrors: (error: unknown) => readonly unknown[];
184
191
  isCapturedError: (error: unknown) => boolean;
185
192
  onRenderError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
186
193
  };
@@ -151,6 +151,7 @@ function createAppPageRscErrorTracker(baseOnError) {
151
151
  let capturedSpecialError = null;
152
152
  const capturedErrors = /* @__PURE__ */ new Set();
153
153
  const capturedDigests = /* @__PURE__ */ new Set();
154
+ const specialErrorsByDigest = /* @__PURE__ */ new Map();
154
155
  return {
155
156
  getCapturedError() {
156
157
  return capturedError;
@@ -158,6 +159,10 @@ function createAppPageRscErrorTracker(baseOnError) {
158
159
  getCapturedSpecialError() {
159
160
  return capturedSpecialError;
160
161
  },
162
+ getCapturedSpecialErrors(error) {
163
+ const digest = getNextErrorDigest(error);
164
+ return digest !== null && specialErrorsByDigest.get(digest) || [];
165
+ },
161
166
  isCapturedError(error) {
162
167
  if (capturedErrors.has(error)) return true;
163
168
  const digest = getNextErrorDigest(error);
@@ -173,6 +178,7 @@ function createAppPageRscErrorTracker(baseOnError) {
173
178
  const result = baseOnError(error, requestInfo, errorContext);
174
179
  const digest = typeof result === "string" ? result : getNextErrorDigest(error);
175
180
  if (digest !== null && !isNavigationSignalError(error)) capturedDigests.add(digest);
181
+ else if (digest !== null) specialErrorsByDigest.set(digest, [...specialErrorsByDigest.get(digest) ?? [], error]);
176
182
  return result;
177
183
  }
178
184
  };
@@ -40,7 +40,7 @@ async function dispatchAppRequestStage(request, ctx, dispatchResponseStage, opti
40
40
  draftModeCookie: null,
41
41
  middlewareCookieOverlay: null,
42
42
  prerenderDiscovery: options.prerenderDiscovery,
43
- protocolVersion: 10,
43
+ protocolVersion: 11,
44
44
  requestOrigin: new URL(request.url).origin,
45
45
  scriptNonce: null,
46
46
  staticFileSignalToken,
@@ -3,9 +3,8 @@ import { runWithExecutionContext } from "../shims/request-context.js";
3
3
  import "./server-globals.js";
4
4
  import "./app-rsc-vary.js";
5
5
  import { VINEXT_CACHEABILITY_PROBE_QUERY_PARAM, VINEXT_EXPECTED_WORKER_VERSION_HEADER } from "./headers.js";
6
- import { badRequestResponse, notFoundResponse } from "./http-error-responses.js";
7
- import { isOpenRedirectShaped } from "./open-redirect.js";
8
- import { cloneRequestWithHeaders, filterInternalHeaders } from "./request-pipeline.js";
6
+ import { badRequestResponse } from "./http-error-responses.js";
7
+ import { cloneRequestWithHeaders, filterInternalHeaders, guardProtocolRelativeUrl } from "./request-pipeline.js";
9
8
  import { getExplicitCdnCacheAdapter } from "../shims/cdn-cache-state.js";
10
9
  import { applyCdnResponseIdentityHeaders, validateCdnRequest } from "./cache-control.js";
11
10
  import { registerLazyDataCacheHandler } from "../shims/cache-handler.js";
@@ -71,7 +70,8 @@ async function handleRequest(request, env, platformCtx, dispatchResponseStage, a
71
70
  }
72
71
  const url = new URL(request.url);
73
72
  if (isImageOptimizationPath(url.pathname) && assets && getImageOptimizer()) return handleConfiguredImageOptimization(request, (assetPath) => Promise.resolve(assets.fetch(new Request(new URL(assetPath, request.url)))), __imageAllowedWidths, __imageConfig);
74
- if (isOpenRedirectShaped(url.pathname)) return notFoundResponse();
73
+ const protocolRelativeGuard = guardProtocolRelativeUrl(url.pathname, url.search);
74
+ if (protocolRelativeGuard) return protocolRelativeGuard;
75
75
  try {
76
76
  decodeURIComponent(url.pathname);
77
77
  } catch {
@@ -3,6 +3,8 @@
3
3
  export declare function markFrameworkLinkHeaders(headers: Headers, linkHeader: string | string[] | null | undefined): void;
4
4
  /** Whether the response carries renderer-owned Link values that config may prepend to. */
5
5
  export declare function hasFrameworkLinkHeaders(headers: Headers): boolean;
6
+ /** The renderer-owned part of the response's Link header, without middleware's. */
7
+ export declare function getFrameworkLinkHeader(headers: Headers): string | null;
6
8
  /** Mark Link values returned by an Edge route handler after config and middleware. */
7
9
  export declare function markEdgeRouteHandlerLinkHeaders(headers: Headers, linkHeader: string | null | undefined): void;
8
10
  /** Whether config must precede a later framework or Edge-handler Link value. */
@@ -1,17 +1,22 @@
1
1
  import { preserveFullyBufferedBodyMetadata } from "./fully-buffered-response.js";
2
2
  import "../shims/unified-request-context.js";
3
3
  //#region src/server/app-response-header-provenance.ts
4
- const frameworkLinkHeaders = /* @__PURE__ */ new WeakSet();
4
+ const frameworkLinkHeaders = /* @__PURE__ */ new WeakMap();
5
5
  const edgeRouteHandlerLinkHeaders = /* @__PURE__ */ new WeakSet();
6
6
  const APP_RESPONSE_STAGE_LINK_PROVENANCE_HEADER = "x-vinext-app-stage-post-config-link";
7
7
  /** Mark response headers whose Link value was emitted by the App page renderer. */
8
8
  function markFrameworkLinkHeaders(headers, linkHeader) {
9
- if (linkHeader && (typeof linkHeader === "string" || linkHeader.length > 0)) frameworkLinkHeaders.add(headers);
9
+ const value = Array.isArray(linkHeader) ? linkHeader.join(", ") : linkHeader;
10
+ if (value) frameworkLinkHeaders.set(headers, value);
10
11
  }
11
12
  /** Whether the response carries renderer-owned Link values that config may prepend to. */
12
13
  function hasFrameworkLinkHeaders(headers) {
13
14
  return frameworkLinkHeaders.has(headers);
14
15
  }
16
+ /** The renderer-owned part of the response's Link header, without middleware's. */
17
+ function getFrameworkLinkHeader(headers) {
18
+ return frameworkLinkHeaders.get(headers) ?? null;
19
+ }
15
20
  /** Mark Link values returned by an Edge route handler after config and middleware. */
16
21
  function markEdgeRouteHandlerLinkHeaders(headers, linkHeader) {
17
22
  if (linkHeader) edgeRouteHandlerLinkHeaders.add(headers);
@@ -22,7 +27,8 @@ function hasPostConfigLinkHeaders(headers) {
22
27
  }
23
28
  /** Preserve Link provenance when a response wrapper reconstructs a Response. */
24
29
  function copyLinkHeaderProvenance(source, target) {
25
- if (frameworkLinkHeaders.has(source)) frameworkLinkHeaders.add(target);
30
+ const frameworkLink = frameworkLinkHeaders.get(source);
31
+ if (frameworkLink !== void 0) frameworkLinkHeaders.set(target, frameworkLink);
26
32
  if (edgeRouteHandlerLinkHeaders.has(source)) edgeRouteHandlerLinkHeaders.add(target);
27
33
  }
28
34
  /** Serialize otherwise process-local Link provenance across a response-stage transport. */
@@ -56,4 +62,4 @@ function consumeResponseStageLinkProvenance(response) {
56
62
  };
57
63
  }
58
64
  //#endregion
59
- export { consumeResponseStageLinkProvenance, copyLinkHeaderProvenance, hasFrameworkLinkHeaders, hasPostConfigLinkHeaders, markEdgeRouteHandlerLinkHeaders, markFrameworkLinkHeaders, serializeResponseStageLinkProvenance };
65
+ export { consumeResponseStageLinkProvenance, copyLinkHeaderProvenance, getFrameworkLinkHeader, hasFrameworkLinkHeaders, hasPostConfigLinkHeaders, markEdgeRouteHandlerLinkHeaders, markFrameworkLinkHeaders, serializeResponseStageLinkProvenance };
@@ -9,12 +9,12 @@ import { markDynamicUsage } from "../shims/internal/headers-state.js";
9
9
  import { consumeDynamicUsage, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, isDraftModeRequest, setHeadersAccessPhase } from "../shims/headers.js";
10
10
  import { _drainPendingRevalidations } from "../shims/cache-request-state.js";
11
11
  import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
12
+ import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
12
13
  import { setNavigationContext } from "../shims/navigation-context-state.js";
13
14
  import { makeThenableParams } from "../shims/thenable-params.js";
14
15
  import { traceResponseStart } from "./response-start-tracing.js";
15
16
  import { buildPageCacheTags } from "./implicit-tags.js";
16
17
  import { applyRouteHandlerMiddlewareContext, finalizeRouteHandlerResponse } from "./app-route-handler-response.js";
17
- import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
18
18
  import "../shims/navigation.js";
19
19
  import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
20
20
  import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, hasNonStaticAppRouteHandlerMethods, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
@@ -5,8 +5,7 @@ import "./server-globals.js";
5
5
  import "./app-rsc-vary.js";
6
6
  import { VINEXT_CACHEABILITY_PROBE_QUERY_PARAM } from "./headers.js";
7
7
  import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } from "./http-error-responses.js";
8
- import { isOpenRedirectShaped } from "./open-redirect.js";
9
- import { cloneRequestWithHeaders, filterInternalHeaders } from "./request-pipeline.js";
8
+ import { cloneRequestWithHeaders, filterInternalHeaders, guardProtocolRelativeUrl } from "./request-pipeline.js";
10
9
  import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
11
10
  import { applyCdnResponseIdentityHeaders, validateCdnRequest } from "./cache-control.js";
12
11
  import { getImageOptimizer, handleConfiguredImageOptimization, isImageOptimizationPath } from "./image-optimization.js";
@@ -83,7 +82,8 @@ async function handleRequest(request, env, platformCtx) {
83
82
  if (cdnValidationResponse) return cdnValidationResponse;
84
83
  const url = new URL(request.url);
85
84
  if (isImageOptimizationPath(url.pathname) && assets && getImageOptimizer()) return handleConfiguredImageOptimization(request, (assetPath) => Promise.resolve(assets.fetch(new Request(new URL(assetPath, request.url)))), __imageAllowedWidths, __imageConfig);
86
- if (isOpenRedirectShaped(url.pathname)) return notFoundResponse();
85
+ const protocolRelativeGuard = guardProtocolRelativeUrl(url.pathname, url.search);
86
+ if (protocolRelativeGuard) return protocolRelativeGuard;
87
87
  try {
88
88
  decodeURIComponent(url.pathname);
89
89
  } catch {
@@ -85,6 +85,8 @@ type DispatchMatchedPageOptions<TRoute> = {
85
85
  scriptNonce?: string;
86
86
  searchParams: URLSearchParams;
87
87
  renderMode: AppRscRenderMode;
88
+ /** Render the document whole before its first byte (a regeneration or warm-up). */
89
+ renderWholeDocument?: boolean;
88
90
  };
89
91
  type DispatchMatchedRouteHandlerOptions<TRoute> = {
90
92
  /**
@@ -235,6 +237,8 @@ export type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
235
237
  matchInterceptRoute?: (pathname: string, sourcePathname: string, interceptionId?: string | null) => AppRscRouteMatch<TRoute> | null;
236
238
  matchRoute: (pathname: string) => AppRscRouteMatch<TRoute> | null;
237
239
  matchRequestRoute?: (pathname: string) => AppRscRouteMatch<TRoute> | null;
240
+ /** `matchRequestRoute` without its decoded static page substitution. */
241
+ matchRawRequestRoute?: (pathname: string) => AppRscRouteMatch<TRoute> | null;
238
242
  runMiddleware?: (options: RunAppMiddlewareOptions) => Promise<ApplyAppMiddlewareResult>;
239
243
  publicFiles: ReadonlySet<string>;
240
244
  prefetchInlining?: PrefetchInliningConfig;