vinext 1.4.2 → 1.4.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 (116) hide show
  1. package/README.md +4 -1
  2. package/dist/build/prerender-paths.d.ts +11 -1
  3. package/dist/build/prerender-paths.js +41 -11
  4. package/dist/cli.js +1 -1
  5. package/dist/client/dev-error-overlay.d.ts +2 -1
  6. package/dist/client/dev-error-overlay.js +8 -3
  7. package/dist/config/config-matchers.js +6 -2
  8. package/dist/config/next-config.d.ts +9 -0
  9. package/dist/entries/app-rsc-entry.js +24 -12
  10. package/dist/entries/pages-server-entry.js +17 -4
  11. package/dist/index.js +48 -39
  12. package/dist/init-platform.js +2 -2
  13. package/dist/init.js +42 -5
  14. package/dist/server/api-handler.js +8 -5
  15. package/dist/server/app-browser-entry.js +26 -47
  16. package/dist/server/app-browser-error.d.ts +1 -1
  17. package/dist/server/app-browser-error.js +13 -4
  18. package/dist/server/app-browser-navigation-controller.js +2 -2
  19. package/dist/server/app-browser-server-action-client.js +2 -2
  20. package/dist/server/app-browser-state.js +2 -2
  21. package/dist/server/app-browser-supplemental-refresh.d.ts +13 -0
  22. package/dist/server/app-browser-supplemental-refresh.js +36 -4
  23. package/dist/server/app-browser-visible-commit.js +1 -1
  24. package/dist/server/app-history-state.js +1 -1
  25. package/dist/server/app-middleware.d.ts +2 -0
  26. package/dist/server/app-middleware.js +1 -0
  27. package/dist/server/app-page-boundary-render.js +4 -2
  28. package/dist/server/app-page-dispatch.d.ts +1 -0
  29. package/dist/server/app-page-dispatch.js +5 -1
  30. package/dist/server/app-page-element-builder.d.ts +2 -0
  31. package/dist/server/app-page-element-builder.js +6 -5
  32. package/dist/server/app-page-render.js +1 -1
  33. package/dist/server/app-page-route-wiring.d.ts +7 -5
  34. package/dist/server/app-page-route-wiring.js +11 -9
  35. package/dist/server/app-pages-bridge.d.ts +6 -0
  36. package/dist/server/app-pages-bridge.js +8 -3
  37. package/dist/server/app-request-context.js +1 -1
  38. package/dist/server/app-request-stage-independent-entry.js +2 -3
  39. package/dist/server/app-route-handler-dispatch.js +1 -1
  40. package/dist/server/app-route-handler-execution.js +1 -1
  41. package/dist/server/app-route-handler-response.d.ts +1 -0
  42. package/dist/server/app-route-handler-response.js +27 -2
  43. package/dist/server/app-router-entry.js +2 -3
  44. package/dist/server/app-rsc-cache-busting.d.ts +8 -0
  45. package/dist/server/app-rsc-cache-busting.js +13 -1
  46. package/dist/server/app-rsc-combined-handler.js +2 -1
  47. package/dist/server/app-rsc-handler.d.ts +4 -0
  48. package/dist/server/app-rsc-handler.js +41 -24
  49. package/dist/server/app-rsc-response-finalizer.d.ts +15 -3
  50. package/dist/server/app-rsc-response-finalizer.js +51 -7
  51. package/dist/server/app-rsc-response-stage.js +1 -1
  52. package/dist/server/app-server-action-execution.js +1 -1
  53. package/dist/server/app-ssr-entry.js +18 -10
  54. package/dist/server/config-headers.d.ts +7 -0
  55. package/dist/server/config-headers.js +20 -1
  56. package/dist/server/edge-api-runtime.d.ts +6 -2
  57. package/dist/server/edge-api-runtime.js +21 -4
  58. package/dist/server/image-animation.d.ts +9 -0
  59. package/dist/server/image-animation.js +118 -0
  60. package/dist/server/image-optimization.d.ts +25 -5
  61. package/dist/server/image-optimization.js +305 -21
  62. package/dist/server/image-source-reader.d.ts +34 -0
  63. package/dist/server/image-source-reader.js +126 -0
  64. package/dist/server/metadata-route-response.d.ts +6 -1
  65. package/dist/server/metadata-route-response.js +24 -6
  66. package/dist/server/middleware-matcher.d.ts +1 -0
  67. package/dist/server/middleware-matcher.js +1 -1
  68. package/dist/server/middleware-runtime.d.ts +5 -0
  69. package/dist/server/middleware-runtime.js +48 -15
  70. package/dist/server/middleware.d.ts +1 -1
  71. package/dist/server/middleware.js +2 -1
  72. package/dist/server/navigation-planner.js +14 -6
  73. package/dist/server/nitro-request-target-plugin.d.ts +17 -0
  74. package/dist/server/nitro-request-target-plugin.js +22 -0
  75. package/dist/server/open-redirect.d.ts +2 -1
  76. package/dist/server/open-redirect.js +2 -1
  77. package/dist/server/pages-client-assets.d.ts +1 -0
  78. package/dist/server/pages-i18n.d.ts +7 -0
  79. package/dist/server/pages-i18n.js +14 -1
  80. package/dist/server/pages-node-compat.js +7 -3
  81. package/dist/server/pages-page-handler.js +4 -4
  82. package/dist/server/pages-request-pipeline.d.ts +9 -0
  83. package/dist/server/pages-request-pipeline.js +29 -10
  84. package/dist/server/pages-request-stage-entry.js +7 -2
  85. package/dist/server/pages-router-entry.js +3 -0
  86. package/dist/server/prod-server.d.ts +1 -1
  87. package/dist/server/prod-server.js +48 -54
  88. package/dist/server/remove-request-headers.d.ts +16 -0
  89. package/dist/server/remove-request-headers.js +23 -0
  90. package/dist/server/srvx-middleware-origin.d.ts +13 -0
  91. package/dist/server/srvx-middleware-origin.js +19 -0
  92. package/dist/server/srvx-request-target.d.ts +12 -0
  93. package/dist/server/srvx-request-target.js +20 -0
  94. package/dist/server/static-file-cache.js +10 -22
  95. package/dist/server/worker-image-optimization.d.ts +8 -1
  96. package/dist/server/worker-image-optimization.js +25 -6
  97. package/dist/server/worker-revalidation-context.js +1 -0
  98. package/dist/shims/cache-runtime.js +1 -1
  99. package/dist/shims/cache.js +6 -3
  100. package/dist/shims/client-page-root.js +2 -2
  101. package/dist/shims/error-boundary.d.ts +6 -2
  102. package/dist/shims/error-boundary.js +6 -4
  103. package/dist/shims/internal/navigation-untracked.js +1 -1
  104. package/dist/shims/metadata.js +1 -1
  105. package/dist/shims/navigation-server.js +1 -1
  106. package/dist/shims/navigation.js +4 -4
  107. package/dist/shims/navigation.react-server.js +3 -3
  108. package/dist/shims/request-context.d.ts +3 -1
  109. package/dist/shims/root-params.js +16 -2
  110. package/dist/shims/slot.js +3 -3
  111. package/dist/shims/url-utils.js +6 -1
  112. package/dist/utils/client-entry-manifest.d.ts +5 -0
  113. package/dist/utils/client-entry-manifest.js +1 -0
  114. package/dist/utils/client-runtime-metadata.d.ts +5 -0
  115. package/dist/utils/client-runtime-metadata.js +33 -7
  116. package/package.json +1 -1
@@ -1,3 +1,4 @@
1
+ import { BrowserRouteManifest, BrowserRouteManifestInterception } from "../routing/browser-route-manifest.js";
1
2
  import { AppElements } from "./app-elements-wire.js";
2
3
  import "./app-elements.js";
3
4
  import { AppRouterState } from "./app-browser-state.js";
@@ -31,6 +32,18 @@ export declare function resolvePersistedSourcePageRefreshes(options: {
31
32
  refreshUrl: URL;
32
33
  state: Pick<AppRouterState, "previousNextUrl" | "slotBindings">;
33
34
  }): string[];
35
+ export type PersistedRefreshInterception = {
36
+ interception: BrowserRouteManifestInterception;
37
+ interceptionContext: string;
38
+ targetPathname: string;
39
+ };
40
+ export declare function resolvePersistedRefreshInterceptions(options: {
41
+ basePath: string;
42
+ refreshUrl: URL;
43
+ requestInterceptionContext: string | null;
44
+ routeManifest: BrowserRouteManifest | null;
45
+ state: Pick<AppRouterState, "interception" | "slotBindings">;
46
+ }): PersistedRefreshInterception[];
34
47
  export declare function createSupplementalRefreshCoordinator(): {
35
48
  abortAll(): void;
36
49
  begin(options: {
@@ -1,6 +1,7 @@
1
- import { addBasePathToPathname, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
2
- import { normalizePathnameForRouteMatch } from "../routing/utils.js";
1
+ import { removeTrailingSlash, restoreBasePath, stripBasePath } from "../utils/base-path.js";
2
+ import { normalizePathnameForRouteMatch, splitPathnameForRouteMatch } from "../routing/utils.js";
3
3
  import { normalizePath } from "./normalize-path.js";
4
+ import { matchRoutePattern } from "../routing/route-pattern.js";
4
5
  import { APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_SLOT_BINDINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
5
6
  import "./app-elements.js";
6
7
  import { isNestedBfcacheSlotSegmentIdFor } from "./bfcache-identity.js";
@@ -131,7 +132,7 @@ function resolvePersistedSourcePageRefreshes(options) {
131
132
  });
132
133
  for (const activeRoutePath of activeRoutePaths) {
133
134
  if (activeRoutePath !== refreshRoutePathname && (refreshRoutePathname === "/" || activeRoutePath.startsWith(refreshRoutePathname + "/"))) continue;
134
- const pathname = addBasePathToPathname(activeRoutePath, options.basePath);
135
+ const pathname = restoreBasePath(activeRoutePath, options.basePath);
135
136
  if (sourceUrlsByPathname.has(pathname)) continue;
136
137
  const sourceUrl = new URL(pathname, options.refreshUrl);
137
138
  sourceUrl.search = options.refreshUrl.search;
@@ -145,6 +146,37 @@ function resolvePersistedSourcePageRefreshes(options) {
145
146
  }
146
147
  return resolved;
147
148
  }
149
+ function getMatchedUrlPathname(matchedUrl) {
150
+ return new URL(matchedUrl, "https://vinext.local").pathname;
151
+ }
152
+ function resolvePersistedRefreshInterceptions(options) {
153
+ const { basePath, refreshUrl, requestInterceptionContext, routeManifest, state } = options;
154
+ if (routeManifest === null) return [];
155
+ const refreshPathname = stripBasePath(refreshUrl.pathname, basePath);
156
+ const refreshPathParts = splitPathnameForRouteMatch(refreshPathname);
157
+ const resolved = [];
158
+ for (const binding of state.slotBindings) {
159
+ if (binding.state !== "active" || !binding.activeRouteId) continue;
160
+ if (!binding.interceptionId || !binding.interceptionSourceMatchedUrl) continue;
161
+ const activeRoute = AppElementsWire.parseElementKey(binding.activeRouteId);
162
+ if (activeRoute?.kind !== "route") continue;
163
+ const match = routeManifest.segmentGraph.interceptions.get(binding.interceptionId);
164
+ if (!match) continue;
165
+ const retainedInterception = state.interception?.slotId === binding.slotId && matchRoutePattern(splitPathnameForRouteMatch(getMatchedUrlPathname(state.interception.targetMatchedUrl)), match.targetPatternParts) !== null ? state.interception : null;
166
+ const targetPathname = retainedInterception?.targetMatchedUrl ?? activeRoute.path;
167
+ const targetParts = splitPathnameForRouteMatch(getMatchedUrlPathname(targetPathname));
168
+ if (requestInterceptionContext !== null && state.interception?.slotId === binding.slotId && matchRoutePattern(refreshPathParts, match.targetPatternParts) !== null && matchRoutePattern(targetParts, match.targetPatternParts) !== null) continue;
169
+ const targetUrl = new URL(targetPathname, refreshUrl);
170
+ targetUrl.pathname = restoreBasePath(targetUrl.pathname, basePath);
171
+ targetUrl.search = refreshUrl.search;
172
+ resolved.push({
173
+ interception: match,
174
+ interceptionContext: retainedInterception?.sourceMatchedUrl ?? binding.interceptionSourceMatchedUrl,
175
+ targetPathname: `${targetUrl.pathname}${targetUrl.search}`
176
+ });
177
+ }
178
+ return resolved;
179
+ }
148
180
  function createSupplementalRefreshCoordinator() {
149
181
  const controllers = /* @__PURE__ */ new Set();
150
182
  return {
@@ -202,4 +234,4 @@ async function resolveSupplementalRefreshes(options) {
202
234
  }
203
235
  }
204
236
  //#endregion
205
- export { SupplementalRefreshError, createSupplementalRefreshCoordinator, mergeRefreshedParallelSlot, requireCompleteSupplementalRefresh, resolvePersistedSourcePageRefreshes, resolveServerActionSupplementalRefresh, resolveSupplementalRefreshes };
237
+ export { SupplementalRefreshError, createSupplementalRefreshCoordinator, mergeRefreshedParallelSlot, requireCompleteSupplementalRefresh, resolvePersistedRefreshInterceptions, resolvePersistedSourcePageRefreshes, resolveServerActionSupplementalRefresh, resolveSupplementalRefreshes };
@@ -1,8 +1,8 @@
1
1
  import { AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
2
2
  import "./app-elements.js";
3
- import { createBfcacheSegmentIdentityMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
4
3
  import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
5
4
  import { mergeElements } from "../shims/slot.js";
5
+ import { createBfcacheSegmentIdentityMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
6
6
  import { createPendingNavigationCommit, resolvePendingNavigationCommitDispositionDecision } from "./app-browser-state.js";
7
7
  import { resolveAppPageRouteStateKey } from "./app-page-segment-state.js";
8
8
  //#region src/server/app-browser-visible-commit.ts
@@ -1,7 +1,7 @@
1
+ import { isNonNegativeSafeInteger } from "../utils/number.js";
1
2
  import { AppElementsWire } from "./app-elements-wire.js";
2
3
  import "./app-elements.js";
3
4
  import { isBfcacheSegmentId } from "./app-bfcache-id.js";
4
- import { isNonNegativeSafeInteger } from "../utils/number.js";
5
5
  //#region src/server/app-history-state.ts
6
6
  const VINEXT_PREVIOUS_NEXT_URL_HISTORY_STATE_KEY = "__vinext_previousNextUrl";
7
7
  const VINEXT_HISTORY_INDEX_HISTORY_STATE_KEY = "__vinext_historyIndex";
@@ -26,6 +26,8 @@ export type ApplyAppMiddlewareOptions = {
26
26
  middlewareRequest?: Request;
27
27
  module: MiddlewareModule;
28
28
  request: Request;
29
+ /** Forwarded to `executeMiddleware`. */
30
+ restoreLocaleRootTrailingSlash?: boolean;
29
31
  validateExternalRewriteRequest?: () => Promise<Response | null>;
30
32
  /**
31
33
  * Forwarded to `executeMiddleware` so the NextRequest exposes a NextURL with
@@ -203,6 +203,7 @@ async function applyAppMiddleware(options) {
203
203
  },
204
204
  requestBodyAlreadyIsolated: true,
205
205
  request: middlewareRequest,
206
+ restoreLocaleRootTrailingSlash: options.restoreLocaleRootTrailingSlash,
206
207
  skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
207
208
  trailingSlash: options.trailingSlash
208
209
  });
@@ -3,14 +3,14 @@ import { isNavigationSignalError } from "../utils/navigation-signal.js";
3
3
  import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders } from "./cache-control.js";
4
4
  import { isRenderDynamicLatched, isStaticGenerationAccessError } from "../shims/internal/headers-state.js";
5
5
  import { copyLinkHeaderProvenance } from "./app-response-header-provenance.js";
6
+ import { withUseCacheLayoutMarker } from "../shims/internal/app-page-props-cache-key.js";
7
+ import { rewriteClientHookError } from "../shims/client-hook-error.js";
6
8
  import { createArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
7
9
  import { AppElementsWire } from "./app-elements-wire.js";
8
10
  import "./app-elements.js";
9
11
  import DefaultGlobalError from "../shims/default-global-error.js";
10
12
  import { ErrorBoundary, GlobalErrorBoundary, SerializedErrorBoundary } from "../shims/error-boundary.js";
11
- import { rewriteClientHookError } from "../shims/client-hook-error.js";
12
13
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
13
- import { withUseCacheLayoutMarker } from "../shims/internal/app-page-props-cache-key.js";
14
14
  import { MetadataHead, ViewportHead } from "../shims/metadata.js";
15
15
  import { buildRscRedirectFlightStream } from "./app-rsc-redirect-flight.js";
16
16
  import { bufferAppPageBinaryStream, buildAppPageSpecialErrorResponse, resolveAppPageSpecialError } from "./app-page-execution.js";
@@ -85,8 +85,10 @@ function wrapRenderedBoundaryElement(options) {
85
85
  renderErrorBoundary(GlobalErrorComponent, children) {
86
86
  return createElement(GlobalErrorBoundary, {
87
87
  fallback: DEFAULT_GLOBAL_ERROR_COMPONENT,
88
+ wrapsGlobalErrorBoundary: true,
88
89
  children: createElement(ErrorBoundary, {
89
90
  fallback: GlobalErrorComponent,
91
+ isGlobalErrorBoundary: true,
90
92
  children
91
93
  })
92
94
  });
@@ -166,6 +166,7 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
166
166
  buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, options?: {
167
167
  isForceStatic?: boolean;
168
168
  isUncacheableRender?: boolean;
169
+ routeTreeOnlyPrefetchShell?: boolean;
169
170
  /** Layouts the navigating client holds, which the render may leave out. */
170
171
  mountedLayouts?: ReadonlySet<string> | null;
171
172
  observeMetadataSearchParamsAccess?: boolean;
@@ -293,7 +293,8 @@ async function dispatchAppPageInner(options) {
293
293
  const isOnDemandRevalidate = _isOnDemandRevalidate();
294
294
  const shouldReadCache = isStoredRender && !isOnDemandRevalidate;
295
295
  const isCacheCandidate = isCacheEligibleRender && isStaticEligible && options.pprFallbackShell === void 0 && !isNeverStoredPath;
296
- const isUncacheableRender = !(isCacheEligibleRender && isStaticEligible) && options.pprFallbackShell === void 0 && (options.pprRuntime === void 0 || !options.isProduction);
296
+ const routeTreeOnlyPrefetchShell = options.pprFallbackShell === void 0 && (options.pprRuntime === void 0 || !options.isProduction);
297
+ const isUncacheableRender = !(isCacheEligibleRender && isStaticEligible) && routeTreeOnlyPrefetchShell;
297
298
  const mountedLayouts = isUncacheableRender && options.isRscRequest && (options.renderMode ?? "navigation") === "navigation" && options.interceptionContext === null && options.isProgressiveActionRender !== true ? parseMountedLayoutsHeader(options.request.headers.get(VINEXT_MOUNTED_LAYOUTS_HEADER)) : null;
298
299
  if (shouldReadCache && isStaticEligible) {
299
300
  traceOperation = resolveAppPageTraceOperation({
@@ -387,6 +388,7 @@ async function dispatchAppPageInner(options) {
387
388
  isForceStatic: revalidationDynamicConfig === "force-static",
388
389
  observeMetadataSearchParamsAccess: revalidationDynamicConfig !== "force-static",
389
390
  observePageSearchParamsAccess: revalidationDynamicConfig !== "force-static",
391
+ routeTreeOnlyPrefetchShell,
390
392
  serveStreamingMetadata: placeGeneratedMetadataInBody,
391
393
  placeStreamedMetadataInHead: true,
392
394
  onHeadPrepared(head) {
@@ -552,6 +554,7 @@ async function dispatchAppPageInner(options) {
552
554
  observeMetadataSearchParamsAccess: interceptDynamicConfig !== "force-static",
553
555
  observePageSearchParamsAccess: interceptDynamicConfig !== "force-static",
554
556
  isUncacheableRender,
557
+ routeTreeOnlyPrefetchShell,
555
558
  serveStreamingMetadata: placeGeneratedMetadataInBody,
556
559
  placeStreamedMetadataInHead: options.renderWholeDocument === true,
557
560
  onHeadPrepared
@@ -611,6 +614,7 @@ async function dispatchAppPageInner(options) {
611
614
  observeMetadataSearchParamsAccess: !isForceStatic,
612
615
  observePageSearchParamsAccess: !isForceStatic,
613
616
  isUncacheableRender,
617
+ routeTreeOnlyPrefetchShell,
614
618
  mountedLayouts: interceptResult.interceptOpts ? null : mountedLayouts,
615
619
  serveStreamingMetadata: placeGeneratedMetadataInBody,
616
620
  placeStreamedMetadataInHead: options.renderWholeDocument === true,
@@ -66,6 +66,8 @@ export type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> =
66
66
  isForceStatic?: boolean;
67
67
  /** The render can never be stored (see buildAppPageElements). */
68
68
  isUncacheableRender?: boolean;
69
+ /** A loading shell without a loading boundary is the route tree (see buildAppPageElements). */
70
+ routeTreeOnlyPrefetchShell?: boolean;
69
71
  /** Layouts the navigating client holds (see buildAppPageElements). */
70
72
  mountedLayouts?: ReadonlySet<string> | null;
71
73
  /** Observe page metadata `searchParams` access for cache-safety classification. */
@@ -1,11 +1,12 @@
1
1
  import { isPromiseLike } from "../utils/promise.js";
2
2
  import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
3
+ import { makeThenableParams } from "../shims/thenable-params.js";
4
+ import { withUseCacheLayoutMarker, withUseCachePageMarker } from "../shims/internal/app-page-props-cache-key.js";
3
5
  import { AppElementsWire } from "./app-elements-wire.js";
4
6
  import "./app-elements.js";
5
- import { APP_PAGE_SEGMENT_KEY, isAppPageRouteGroupSegment, resolveAppPagePatternStateKey, resolveAppPageRouteStateKey, resolveAppPageSemanticSegmentStateKey } from "./app-page-segment-state.js";
7
+ import { ClientPageRoot } from "../shims/client-page-root.js";
6
8
  import { ErrorBoundary, ForbiddenBoundary, NotFoundBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
7
- import { withUseCacheLayoutMarker, withUseCachePageMarker } from "../shims/internal/app-page-props-cache-key.js";
8
- import { makeThenableParams } from "../shims/thenable-params.js";
9
+ import { APP_PAGE_SEGMENT_KEY, isAppPageRouteGroupSegment, resolveAppPagePatternStateKey, resolveAppPageRouteStateKey, resolveAppPageSemanticSegmentStateKey } from "./app-page-segment-state.js";
9
10
  import { tagAppPagePageError, tagAppPageSlotError } from "./app-page-execution.js";
10
11
  import { createAppPageMetadataSearchParamsObserver, makeObservedAppPageSearchParamsThenable } from "./app-page-search-params-observation.js";
11
12
  import { resolveAppPageBranchParams } from "./app-page-params.js";
@@ -19,7 +20,6 @@ import { resolveAppPageModuleTraceSegment, traceCreateComponentTree, traceGetLay
19
20
  import { buildAppPageElements, createAppPageSourcePage, createAppPageTreePath, resolveAppPageLoadingModuleAtOrAbove } from "./app-page-route-wiring.js";
20
21
  import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
21
22
  import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
22
- import { ClientPageRoot } from "../shims/client-page-root.js";
23
23
  import { createAppPageRenderIdentity } from "./app-page-render-identity.js";
24
24
  import { Fragment, Suspense, cache, createElement } from "react";
25
25
  //#region src/server/app-page-element-builder.ts
@@ -107,7 +107,7 @@ function traceAppPageInterceptLayoutModules(modules, branchSegments, layoutSegme
107
107
  async function buildPageElements(options) {
108
108
  const { route, params, routePath, displayPathname = routePath, pageRequest, globalErrorModule, rootNotFoundModule, rootForbiddenModule, rootUnauthorizedModule, metadataRoutes } = options;
109
109
  const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
110
- const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION, observeMetadataSearchParamsAccess = false, observePageSearchParamsAccess = false, isForceStatic = false, isUncacheableRender = false, mountedLayouts = null, serveStreamingMetadata, placeStreamedMetadataInHead = false, isProduction = process.env.NODE_ENV === "production", onHeadPrepared } = pageRequest;
110
+ const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION, observeMetadataSearchParamsAccess = false, observePageSearchParamsAccess = false, isForceStatic = false, isUncacheableRender = false, routeTreeOnlyPrefetchShell = false, mountedLayouts = null, serveStreamingMetadata, placeStreamedMetadataInHead = false, isProduction = process.env.NODE_ENV === "production", onHeadPrepared } = pageRequest;
111
111
  const pageModule = route.page;
112
112
  const isSiblingIntercept = opts?.interceptSlotKey === "__vinext_page_intercept" && !!opts?.interceptPage;
113
113
  const effectivePageModule = isSiblingIntercept ? opts.interceptPage : pageModule;
@@ -414,6 +414,7 @@ async function buildPageElements(options) {
414
414
  globalErrorModule: globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE,
415
415
  isRscRequest,
416
416
  isUncacheableRender,
417
+ routeTreeOnlyPrefetchShell,
417
418
  interceptionId: opts?.interceptionId ?? null,
418
419
  mountedLayouts,
419
420
  mountedSlotIds,
@@ -17,11 +17,11 @@ import { applyPrerenderCacheLifeHeader, applyPrerenderCacheTagsHeader } from "./
17
17
  import { copyLinkHeaderProvenance, getFrameworkLinkHeader } from "./app-response-header-provenance.js";
18
18
  import { traceResponseStartWithCompletion } from "./response-start-tracing.js";
19
19
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
20
+ import { isBailoutToCSRError } from "../shims/navigation-errors.js";
20
21
  import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
21
22
  import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
22
23
  import "./app-elements.js";
23
24
  import { appendRscCompletionMetadata } from "./rsc-completion-metadata.js";
24
- import { isBailoutToCSRError } from "../shims/navigation-errors.js";
25
25
  import { applyClientStaleTimeHeader, applyEdgeRuntimeHeader, buildAppPageHtmlResponse, buildAppPageRscResponse, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy, resolveUncacheableCacheControl } from "./app-page-response.js";
26
26
  import { buildAppPageFontLinkHeader, readAppPageBinaryStream, resolveAppPageCaughtNotFoundBoundaries, resolveAppPageShellSpecialError, resolveAppPageSpecialError, resolveAppPageSpecialErrorStoredHeaders, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
27
27
  import { buildAppPageHtmlDocumentResponse, buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, createAppPageSsrErrorHandler, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery } from "./app-page-stream.js";
@@ -220,11 +220,7 @@ type BuildAppPageElementsOptions<TModule extends AppPageModule = AppPageModule,
220
220
  isRscRequest?: boolean;
221
221
  /**
222
222
  * The render can never be stored and, in production, is never sent with
223
- * static cache headers (see app-page-dispatch.ts), so a loading-shell
224
- * prefetch without a loading boundary may skip its layouts. A render that
225
- * may be stored keeps them, so a layout's dynamic API read still keeps it
226
- * out of the cache. An explicit CDN cache policy on a dynamic route can
227
- * still store the route tree, as a CDN would store Next.js's.
223
+ * static cache headers (see app-page-dispatch.ts).
228
224
  */
229
225
  isUncacheableRender?: boolean;
230
226
  /**
@@ -236,6 +232,12 @@ type BuildAppPageElementsOptions<TModule extends AppPageModule = AppPageModule,
236
232
  mountedLayouts?: ReadonlySet<string> | null;
237
233
  mountedSlotIds?: ReadonlySet<string> | null;
238
234
  renderIdentity?: AppPageRenderIdentity;
235
+ /**
236
+ * The render has no PPR (see app-page-dispatch.ts), so a loading-shell
237
+ * prefetch without a loading boundary sends only the route tree. Without it,
238
+ * the layouts render, as Next.js renders them with isRoutePPREnabled.
239
+ */
240
+ routeTreeOnlyPrefetchShell?: boolean;
239
241
  renderMode?: AppRscRenderMode;
240
242
  routePath: string;
241
243
  semanticPageIdentity?: Readonly<{
@@ -1,24 +1,24 @@
1
1
  import { APP_RSC_RENDER_MODE_PREFETCH_EMPTY, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "./app-rsc-render-mode.js";
2
2
  import { fnv1a64 } from "../utils/hash.js";
3
3
  import { createInlineScriptTag, escapeHtmlAttr } from "./html.js";
4
+ import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
5
+ import { withUseCacheLayoutMarker } from "../shims/internal/app-page-props-cache-key.js";
4
6
  import { APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_STATIC_SIBLINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
5
7
  import { APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_STREAMING_METADATA_BODY_ID_PREFIX } from "./app-elements.js";
6
8
  import { createBfcacheChildSegmentStateKey } from "./bfcache-identity.js";
7
- import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
8
- import { hashMountedLayoutIdentity } from "./app-mounted-layouts.js";
9
9
  import { BfcacheChildrenBoundary, BfcacheSegmentBoundary, Children as Children$1, ParallelSlot, Slot } from "../shims/slot.js";
10
- import { APP_PAGE_SEGMENT_KEY, isAppPageRouteGroupSegment, resolveAppPageChildSegments, resolveAppPageSegmentStateKey, resolveAppPageTemplateStateKey } from "./app-page-segment-state.js";
10
+ import DefaultForbidden from "../shims/default-forbidden.js";
11
11
  import DefaultGlobalError from "../shims/default-global-error.js";
12
+ import DefaultNotFound from "../shims/default-not-found.js";
13
+ import DefaultUnauthorized from "../shims/default-unauthorized.js";
12
14
  import { ErrorBoundary, ForbiddenBoundary, GlobalErrorBoundary, HttpAccessFallbackPassthrough, NotFoundBoundary, RedirectBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
13
15
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
14
- import { withUseCacheLayoutMarker } from "../shims/internal/app-page-props-cache-key.js";
15
16
  import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
17
+ import { StreamedIconsInsertion } from "../shims/streamed-icons.js";
18
+ import { hashMountedLayoutIdentity } from "./app-mounted-layouts.js";
19
+ import { APP_PAGE_SEGMENT_KEY, isAppPageRouteGroupSegment, resolveAppPageChildSegments, resolveAppPageSegmentStateKey, resolveAppPageTemplateStateKey } from "./app-page-segment-state.js";
16
20
  import { APP_PAGE_NOT_FOUND_BOUNDARY_ID, tagAppPageLayoutError, tagAppPageSlotError } from "./app-page-execution.js";
17
21
  import { resolveAppPageBranchParams, resolveAppPageSegmentParams } from "./app-page-params.js";
18
- import DefaultForbidden from "../shims/default-forbidden.js";
19
- import DefaultNotFound from "../shims/default-not-found.js";
20
- import DefaultUnauthorized from "../shims/default-unauthorized.js";
21
- import { StreamedIconsInsertion } from "../shims/streamed-icons.js";
22
22
  import { createAppRenderDependency, invokeAppComponentMappingErrors, isReactOwnedAppComponent, renderAfterAppDependencies, renderAppComponentWithDependencyBarrier } from "./app-render-dependency.js";
23
23
  import { createAppPageLayoutGate, registerAppPageLayoutGate } from "./app-page-layout-gate.js";
24
24
  import { probeReactServerSubtree } from "./app-page-probe.js";
@@ -514,7 +514,7 @@ function buildAppPageElements(options) {
514
514
  [pageElementId]: null,
515
515
  [routeId]: null
516
516
  };
517
- if (isPrefetchLoadingShell && !shouldRenderPrefetchLoadingShell && options.isUncacheableRender === true) return {
517
+ if (isPrefetchLoadingShell && !shouldRenderPrefetchLoadingShell && options.routeTreeOnlyPrefetchShell === true) return {
518
518
  ...metadataEntries,
519
519
  ...options.route.staticSiblings && options.route.staticSiblings.length > 0 ? { [APP_STATIC_SIBLINGS_KEY]: options.route.staticSiblings } : {},
520
520
  [pageElementId]: null,
@@ -981,8 +981,10 @@ function buildAppPageElements(options) {
981
981
  const globalErrorComponent = getErrorBoundaryExport(options.globalErrorModule);
982
982
  routeChildren = /* @__PURE__ */ jsx(GlobalErrorBoundary, {
983
983
  fallback: DEFAULT_GLOBAL_ERROR_COMPONENT,
984
+ wrapsGlobalErrorBoundary: globalErrorComponent !== null,
984
985
  children: globalErrorComponent ? /* @__PURE__ */ jsx(ErrorBoundary, {
985
986
  fallback: globalErrorComponent,
987
+ isGlobalErrorBoundary: true,
986
988
  children: routeChildren
987
989
  }) : routeChildren
988
990
  });
@@ -57,6 +57,12 @@ type RenderPagesFallbackOptions = {
57
57
  pathname?: string;
58
58
  pagesDataRequest?: Request | null;
59
59
  request: Request;
60
+ /**
61
+ * The basePath `request.url` still carries. The page renderer receives the
62
+ * URL without it, as in the Pages Router pipeline, so `req.url` and `asPath`
63
+ * leave it out like Next.js.
64
+ */
65
+ requestBasePath?: string;
60
66
  /** The shared cache entry answers every host; a request-time render is not stored. */
61
67
  sharedAcrossHosts?: boolean;
62
68
  url: URL;
@@ -1,5 +1,7 @@
1
+ import { stripBasePath } from "../utils/base-path.js";
1
2
  import { cloneRequestWithHeaders, cloneRequestWithUrl } from "./request-pipeline.js";
2
3
  import { getRequestExecutionContext } from "../shims/request-context.js";
4
+ import { isLocaleRedirect, markLocaleRedirect } from "./pages-i18n.js";
3
5
  import { beginRouteCacheability, markRouteCacheabilityDynamic } from "../shims/cacheability-classification.js";
4
6
  import { mergeHeaders } from "./worker-utils.js";
5
7
  import { pagesRouteHasPriorityOverAppRoute } from "./hybrid-route-priority.js";
@@ -18,7 +20,7 @@ function applyPagesMiddlewareContext(response, middlewareContext) {
18
20
  * Fallback handler to route App Router requests to the Pages Router when no App Router route matches.
19
21
  */
20
22
  async function renderPagesFallback(options, dependencies) {
21
- const { allowRscDocumentFallback = false, appRouteMatch = null, isDataRequest = false, isRscRequest, initialResponseHeaders, matchKind, middlewareContext, pathname = options.url.pathname, pagesDataRequest = null, request, sharedAcrossHosts = false, url } = options;
23
+ const { allowRscDocumentFallback = false, appRouteMatch = null, isDataRequest = false, isRscRequest, initialResponseHeaders, matchKind, middlewareContext, pathname = options.url.pathname, pagesDataRequest = null, request, requestBasePath = "", sharedAcrossHosts = false, url } = options;
22
24
  const { loadPagesEntry, buildRequestHeaders, applyRouteHandlerMiddlewareContext, getDraftModeCookieHeader } = dependencies;
23
25
  if (isRscRequest && !allowRscDocumentFallback) return null;
24
26
  const pagesEntry = await loadPagesEntry();
@@ -67,8 +69,10 @@ async function renderPagesFallback(options, dependencies) {
67
69
  if (runtimeDataKind === "server" || runtimeDataKind === "initial") markRouteCacheabilityDynamic("getInitialProps render shares a cache entry across hosts");
68
70
  }
69
71
  const pagesRequest = claimPagesRequest();
72
+ const renderRequestUrl = new URL(pagesDataRequest?.url ?? pagesRequest.url);
73
+ if (!pagesDataRequest) renderRequestUrl.pathname = stripBasePath(renderRequestUrl.pathname, requestBasePath);
70
74
  const renderArgs = [
71
- pagesDataRequest ? cloneRequestWithUrl(pagesRequest, pagesDataRequest.url) : pagesRequest,
75
+ renderRequestUrl.href === pagesRequest.url ? pagesRequest : cloneRequestWithUrl(pagesRequest, renderRequestUrl.href),
72
76
  pagesUrl,
73
77
  {},
74
78
  getRequestExecutionContext() ?? void 0,
@@ -76,7 +80,8 @@ async function renderPagesFallback(options, dependencies) {
76
80
  ];
77
81
  const pagesRes = isDataRequest ? await (initialResponseHeaders ? pagesEntry.renderPage(...renderArgs, { isDataReq: true }, initialResponseHeaders) : pagesEntry.renderPage(...renderArgs, { isDataReq: true })) : await (initialResponseHeaders ? pagesEntry.renderPage(...renderArgs, void 0, initialResponseHeaders) : pagesEntry.renderPage(...renderArgs));
78
82
  if (pagesRes.status === 404 && pageMatch === null) return null;
79
- return applyDraftModeCookie(applyPagesMiddlewareContext(pagesRes, middlewareContext), getDraftModeCookieHeader());
83
+ const response = applyDraftModeCookie(applyPagesMiddlewareContext(pagesRes, middlewareContext), getDraftModeCookieHeader());
84
+ return isLocaleRedirect(pagesRes) ? markLocaleRedirect(response) : response;
80
85
  }
81
86
  /**
82
87
  * Append a middleware-emitted `__prerender_bypass` Set-Cookie header to a Pages
@@ -1,7 +1,7 @@
1
1
  import { setHeadersContext } from "../shims/headers.js";
2
+ import { setRootParams } from "../shims/root-params.js";
2
3
  import { setNavigationContext } from "../shims/navigation-context-state.js";
3
4
  import "../shims/navigation-server.js";
4
- import { setRootParams } from "../shims/root-params.js";
5
5
  //#region src/server/app-request-context.ts
6
6
  /**
7
7
  * Set navigation context in the ALS-backed store. "use client" components
@@ -9,7 +9,7 @@ import "./server-globals.js";
9
9
  import { getExplicitCdnCacheAdapter } from "../shims/cdn-cache-state.js";
10
10
  import { applyCdnResponseIdentityHeaders, validateCdnRequest } from "./cache-control.js";
11
11
  import { registerLazyDataCacheHandler } from "../shims/cache-handler.js";
12
- import { getImageOptimizer, readImageOptimizationSignal } from "./image-optimization.js";
12
+ import { readImageOptimizationSignal } from "./image-optimization.js";
13
13
  import { consumeFrameworkRequestRoute, traceFrameworkRequest } from "./request-tracing.js";
14
14
  import { createStaticAssetRequest, resolveStaticAssetSignal } from "./worker-utils.js";
15
15
  import { readTrustedPrerenderStateFromHeaders } from "./prerender-route-params.js";
@@ -75,7 +75,6 @@ async function handleRequest(request, env, platformCtx, dispatchResponseStage, a
75
75
  if (cdnValidationResponse) return cdnValidationResponse;
76
76
  }
77
77
  const url = new URL(request.url);
78
- const servesImages = Boolean(assets) && getImageOptimizer() !== null;
79
78
  const protocolRelativeGuard = guardProtocolRelativeUrl(url.pathname, url.search);
80
79
  if (protocolRelativeGuard) return protocolRelativeGuard;
81
80
  try {
@@ -104,7 +103,7 @@ async function handleRequest(request, env, platformCtx, dispatchResponseStage, a
104
103
  };
105
104
  const handle = () => requestRscHandler(request, ctx, trackedDispatchResponseStage, probeMode, ctx.isPrerenderPathDiscovery === true, trustedPrerenderState);
106
105
  let response = await runWithExecutionContext(ctx, handle);
107
- const imageSignal = servesImages ? readImageOptimizationSignal(response) : null;
106
+ const imageSignal = assets ? readImageOptimizationSignal(response) : null;
108
107
  if (imageSignal && assets) {
109
108
  const { fetchSignalledPublicFile, serveWorkerImageOptimization } = await import("./worker-image-optimization.js");
110
109
  response = await serveWorkerImageOptimization(request, imageSignal, __imageAllowedWidths, __imageConfig, {
@@ -14,9 +14,9 @@ import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchCacheMode, setC
14
14
  import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
15
15
  import { traceResponseStart } from "./response-start-tracing.js";
16
16
  import { applyRouteHandlerMiddlewareContext, finalizeRouteHandlerResponse } from "./app-route-handler-response.js";
17
+ import { makeThenableParams } from "../shims/thenable-params.js";
17
18
  import { setNavigationContext } from "../shims/navigation-context-state.js";
18
19
  import "../shims/navigation.js";
19
- import { makeThenableParams } from "../shims/thenable-params.js";
20
20
  import { buildPageCacheTags } from "./implicit-tags.js";
21
21
  import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
22
22
  import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, hasNonStaticAppRouteHandlerMethods, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
@@ -10,8 +10,8 @@ import { isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
10
10
  import { _drainPendingRevalidations } from "../shims/cache-request-state.js";
11
11
  import { copyLinkHeaderProvenance } from "./app-response-header-provenance.js";
12
12
  import { applyRouteHandlerMiddlewareContext, applyRouteHandlerRevalidateHeader, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, finalizeRouteHandlerResponse, markRouteHandlerCacheMiss } from "./app-route-handler-response.js";
13
- import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
14
13
  import { runWithRootParamsUsage } from "../shims/root-params.js";
14
+ import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
15
15
  import { createTrackedAppRouteRequest, markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
16
16
  import { resolveAppRouteHandlerSpecialError, shouldApplyAppRouteHandlerRevalidateHeader, shouldCompleteAppRouteHandlerResponse, shouldWriteAppRouteHandlerCache } from "./app-route-handler-policy.js";
17
17
  import { createStaticGenerationHeadersContext, getAppRouteStaticGenerationErrorMessage } from "./app-static-generation.js";
@@ -17,6 +17,7 @@ type FinalizeRouteHandlerResponseOptions = {
17
17
  draftCookie?: string | null;
18
18
  isHead: boolean;
19
19
  };
20
+ export declare function stripRouteHandlerFramingHeaders(response: Response): Response;
20
21
  export declare function applyRouteHandlerMiddlewareContext(response: Response, middlewareContext: RouteHandlerMiddlewareContext, options?: MiddlewareResponseMergeOptions & {
21
22
  appendResponseLink?: boolean;
22
23
  }): Response;
@@ -1,3 +1,4 @@
1
+ import { preserveFullyBufferedBodyMetadata } from "./fully-buffered-response.js";
1
2
  import "../utils/protocol-headers.js";
2
3
  import { NEXT_CACHE_TAGS_HEADER, VINEXT_METADATA_ROUTE_CACHE_HEADER } from "./headers.js";
3
4
  import { processMiddlewareHeaders } from "./request-pipeline.js";
@@ -11,6 +12,28 @@ import { getSetCookieName } from "./cookie-utils.js";
11
12
  //#region src/server/app-route-handler-response.ts
12
13
  const APP_ROUTE_REWRITE_ERROR = "NextResponse.rewrite() was used in a app route handler, this is not currently supported. Please remove the invocation to continue.";
13
14
  const APP_ROUTE_NEXT_ERROR = "NextResponse.next() was used in a app route handler, this is not supported. See here for more info: https://nextjs.org/docs/messages/next-response-next-in-app-route-handler";
15
+ const ROUTE_HANDLER_FRAMING_HEADERS = [
16
+ "content-length",
17
+ "content-encoding",
18
+ "transfer-encoding"
19
+ ];
20
+ function shouldDropRouteHandlerFramingHeaders(headers) {
21
+ if ("WebSocketPair" in globalThis) return false;
22
+ return ROUTE_HANDLER_FRAMING_HEADERS.some((name) => headers.has(name));
23
+ }
24
+ function deleteRouteHandlerFramingHeaders(headers) {
25
+ for (const name of ROUTE_HANDLER_FRAMING_HEADERS) headers.delete(name);
26
+ }
27
+ function stripRouteHandlerFramingHeaders(response) {
28
+ if (!shouldDropRouteHandlerFramingHeaders(response.headers)) return response;
29
+ const headers = new Headers(response.headers);
30
+ deleteRouteHandlerFramingHeaders(headers);
31
+ return preserveFullyBufferedBodyMetadata(response, new Response(response.body, {
32
+ status: response.status,
33
+ statusText: response.statusText,
34
+ headers
35
+ }));
36
+ }
14
37
  function hasMiddlewareHeader(headers) {
15
38
  for (const key of headers.keys()) if (key.startsWith("x-middleware-")) return true;
16
39
  return false;
@@ -42,6 +65,7 @@ function buildRouteHandlerCachedResponse(cachedValue, options) {
42
65
  else headers.set(key, value);
43
66
  headers.delete(NEXT_CACHE_TAGS_HEADER);
44
67
  headers.delete(VINEXT_METADATA_ROUTE_CACHE_HEADER);
68
+ if (shouldDropRouteHandlerFramingHeaders(headers)) deleteRouteHandlerFramingHeaders(headers);
45
69
  setCacheStateHeaders(headers, options.cacheState);
46
70
  const { cacheControl } = decideIsr({
47
71
  cacheState: options.cacheState,
@@ -152,8 +176,9 @@ async function buildAppRouteCacheValue(response, browserCacheControl) {
152
176
  }
153
177
  function finalizeRouteHandlerResponse(response, options) {
154
178
  const { pendingCookies, draftCookie, isHead } = options;
155
- if (pendingCookies.length === 0 && !draftCookie && !isHead && !hasMiddlewareHeader(response.headers)) return response;
179
+ if (pendingCookies.length === 0 && !draftCookie && !isHead && !hasMiddlewareHeader(response.headers) && !shouldDropRouteHandlerFramingHeaders(response.headers)) return response;
156
180
  const headers = new Headers(response.headers);
181
+ if (shouldDropRouteHandlerFramingHeaders(headers)) deleteRouteHandlerFramingHeaders(headers);
157
182
  processMiddlewareHeaders(headers);
158
183
  applyMutableCookieFallbacks(headers, pendingCookies);
159
184
  if (draftCookie) headers.append("Set-Cookie", draftCookie);
@@ -164,4 +189,4 @@ function finalizeRouteHandlerResponse(response, options) {
164
189
  });
165
190
  }
166
191
  //#endregion
167
- export { applyRouteHandlerMiddlewareContext, applyRouteHandlerRevalidateHeader, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, buildRouteHandlerCachedResponse, finalizeRouteHandlerResponse, markRouteHandlerCacheMiss };
192
+ export { applyRouteHandlerMiddlewareContext, applyRouteHandlerRevalidateHeader, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, buildRouteHandlerCachedResponse, finalizeRouteHandlerResponse, markRouteHandlerCacheMiss, stripRouteHandlerFramingHeaders };
@@ -8,7 +8,7 @@ import { runWithExecutionContext } from "../shims/request-context.js";
8
8
  import "./server-globals.js";
9
9
  import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
10
10
  import { applyCdnResponseIdentityHeaders, validateCdnRequest } from "./cache-control.js";
11
- import { getImageOptimizer, readImageOptimizationSignal } from "./image-optimization.js";
11
+ import { readImageOptimizationSignal } from "./image-optimization.js";
12
12
  import { traceFrameworkRequest } from "./request-tracing.js";
13
13
  import { createStaticAssetRequest, resolveStaticAssetSignal } from "./worker-utils.js";
14
14
  import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
@@ -83,7 +83,6 @@ async function handleRequest(request, env, platformCtx) {
83
83
  const cdnValidationResponse = await validateCdnRequest(request);
84
84
  if (cdnValidationResponse) return cdnValidationResponse;
85
85
  const url = new URL(request.url);
86
- const servesImages = Boolean(assets) && getImageOptimizer() !== null;
87
86
  const protocolRelativeGuard = guardProtocolRelativeUrl(url.pathname, url.search);
88
87
  if (protocolRelativeGuard) return protocolRelativeGuard;
89
88
  try {
@@ -109,7 +108,7 @@ async function handleRequest(request, env, platformCtx) {
109
108
  const result = await (ctx ? runWithExecutionContext(ctx, handleFn) : handleFn());
110
109
  if (result instanceof Response) {
111
110
  let response = result;
112
- const imageSignal = servesImages ? readImageOptimizationSignal(response) : null;
111
+ const imageSignal = assets ? readImageOptimizationSignal(response) : null;
113
112
  if (imageSignal && assets) {
114
113
  const { fetchSignalledPublicFile, serveWorkerImageOptimization } = await import("./worker-image-optimization.js");
115
114
  response = await serveWorkerImageOptimization(request, imageSignal, __imageAllowedWidths, __imageConfig, {
@@ -78,6 +78,14 @@ export declare function createRscRequestHeaders(options?: CreateRscRequestHeader
78
78
  * their bytes can legitimately differ from the destination's full route.
79
79
  */
80
80
  export declare function canonicalizePrewarmableRscRequestHeaders(headers: Headers): boolean;
81
+ /**
82
+ * Convert a search-param shell prefetch to the canonical navigation of its
83
+ * page. The shell renders the page with an empty query (app-page-dispatch.ts),
84
+ * which is what the query-free navigation renders, as Next.js's static
85
+ * prefetch of a page segment never varies on search params. The caller drops
86
+ * the query from the URL.
87
+ */
88
+ export declare function canonicalizeDynamicShellRscRequestHeaders(headers: Headers): boolean;
81
89
  /**
82
90
  * Convert an ordinary loading-boundary prefetch to the shared loading-shell
83
91
  * variant. The payload is selected by the three retained mode headers; visible
@@ -199,6 +199,18 @@ function canonicalizePrewarmableRscRequestHeaders(headers) {
199
199
  return true;
200
200
  }
201
201
  /**
202
+ * Convert a search-param shell prefetch to the canonical navigation of its
203
+ * page. The shell renders the page with an empty query (app-page-dispatch.ts),
204
+ * which is what the query-free navigation renders, as Next.js's static
205
+ * prefetch of a page segment never varies on search params. The caller drops
206
+ * the query from the URL.
207
+ */
208
+ function canonicalizeDynamicShellRscRequestHeaders(headers) {
209
+ if (headers.get("X-Vinext-Rsc-Render-Mode") !== "prefetch-dynamic-shell" || headers.has("X-Vinext-Interception-Context") || headers.has("X-Vinext-Interception-Id") || headers.has("X-Vinext-Mounted-Slots")) return false;
210
+ headers.delete(VINEXT_RSC_RENDER_MODE_HEADER);
211
+ return canonicalizePrewarmableRscRequestHeaders(headers);
212
+ }
213
+ /**
202
214
  * Convert an ordinary loading-boundary prefetch to the shared loading-shell
203
215
  * variant. The payload is selected by the three retained mode headers; visible
204
216
  * router state is transport context and must not fragment the shared response.
@@ -285,4 +297,4 @@ async function resolveInvalidRscCacheBustingRequest(options) {
285
297
  });
286
298
  }
287
299
  //#endregion
288
- export { VINEXT_RSC_BUILD_ID_HEADER, VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader, canonicalizeLoadingShellRscRequestHeaders, canonicalizePrewarmableRscRequestHeaders, computeRscCacheBustingSearchParam, createCanonicalLoadingShellRscRequestHeaders, createCanonicalRscRequestHeaders, createCanonicalRscRequestUrl, createRscRedirectLocation, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, formatRscRequestPath, getVinextRscCompatibilityId, hasRscCacheBustingSearchParam, isRscCompatibilityIdCompatible, keepOnlyValidatedRscCacheBustingSearchParam, parseRscRequestPath, resolveHardNavigationTargetFromRscResponse, resolveInvalidRscCacheBustingRequest, resolveRscCompatibilityNavigationDecision, setRscCacheBustingSearchParam, stripRscCacheBustingSearchParam, toPathAbsolutePathname };
300
+ export { VINEXT_RSC_BUILD_ID_HEADER, VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader, canonicalizeDynamicShellRscRequestHeaders, canonicalizeLoadingShellRscRequestHeaders, canonicalizePrewarmableRscRequestHeaders, computeRscCacheBustingSearchParam, createCanonicalLoadingShellRscRequestHeaders, createCanonicalRscRequestHeaders, createCanonicalRscRequestUrl, createRscRedirectLocation, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, formatRscRequestPath, getVinextRscCompatibilityId, hasRscCacheBustingSearchParam, isRscCompatibilityIdCompatible, keepOnlyValidatedRscCacheBustingSearchParam, parseRscRequestPath, resolveHardNavigationTargetFromRscResponse, resolveInvalidRscCacheBustingRequest, resolveRscCompatibilityNavigationDecision, setRscCacheBustingSearchParam, stripRscCacheBustingSearchParam, toPathAbsolutePathname };
@@ -1,13 +1,14 @@
1
1
  import { getRequestExecutionContext, runWithExecutionContext } from "../shims/request-context.js";
2
2
  import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
3
3
  import { createAppRscRequestHandler } from "./app-rsc-handler.js";
4
+ import { resolveSrvxMiddlewareOrigin } from "./srvx-middleware-origin.js";
4
5
  //#region src/server/app-rsc-combined-handler.ts
5
6
  /** Combined request/response handler used by default single-stage App entries. */
6
7
  function createAppRscHandler(options) {
7
8
  const appRscRequestHandler = createAppRscRequestHandler(options);
8
9
  const appRscHandler = (request, ctx, ...rest) => {
9
10
  if (ctx != null || getRequestExecutionContext()) return appRscRequestHandler(request, ctx, ...rest);
10
- const executionContext = createWorkerRevalidationContext(void 0, (internalRequest, internalCtx) => runWithExecutionContext(internalCtx, () => appRscRequestHandler(internalRequest, internalCtx)), "node");
11
+ const executionContext = createWorkerRevalidationContext({ middlewareOrigin: resolveSrvxMiddlewareOrigin(request) }, (internalRequest, internalCtx) => runWithExecutionContext(internalCtx, () => appRscRequestHandler(internalRequest, internalCtx)), "node");
11
12
  return runWithExecutionContext(executionContext, () => appRscRequestHandler(request, ctx, ...rest));
12
13
  };
13
14
  return Object.assign(appRscHandler, { handleResponseStage(request, ctx, props, stageOptions) {