vinext 1.0.0 → 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 (263) hide show
  1. package/README.md +72 -1
  2. package/THIRD_PARTY_LICENSES.md +26 -0
  3. package/dist/build/app-page-static-eligibility.d.ts +15 -0
  4. package/dist/build/app-page-static-eligibility.js +82 -0
  5. package/dist/build/lifecycle.js +10 -10
  6. package/dist/build/pages-client-assets-module.js +6 -1
  7. package/dist/build/precompress.js +1 -1
  8. package/dist/build/prerender-paths.js +6 -85
  9. package/dist/build/prerender.d.ts +8 -1
  10. package/dist/build/prerender.js +167 -46
  11. package/dist/build/run-prerender.js +4 -3
  12. package/dist/build/server-entry.d.ts +2 -0
  13. package/dist/build/server-entry.js +7 -1
  14. package/dist/build/server-manifest.d.ts +7 -0
  15. package/dist/build/server-manifest.js +11 -1
  16. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  17. package/dist/cache/cache-adapters-virtual.js +3 -3
  18. package/dist/client/browser-globals.d.ts +4 -0
  19. package/dist/client/browser-globals.js +5 -0
  20. package/dist/client/navigation-runtime.d.ts +11 -1
  21. package/dist/client/navigation-runtime.js +3 -3
  22. package/dist/config/config-matchers.js +3 -1
  23. package/dist/config/dotenv.js +14 -3
  24. package/dist/config/next-config.d.ts +7 -0
  25. package/dist/config/next-config.js +18 -3
  26. package/dist/entries/app-rsc-entry.d.ts +2 -0
  27. package/dist/entries/app-rsc-entry.js +67 -45
  28. package/dist/index.d.ts +4 -1
  29. package/dist/index.js +200 -100
  30. package/dist/init-cloudflare.d.ts +1 -1
  31. package/dist/init-cloudflare.js +6 -6
  32. package/dist/init-platform.js +1 -1
  33. package/dist/init.js +4 -2
  34. package/dist/plugins/cache-flight-codec.d.ts +19 -0
  35. package/dist/plugins/cache-flight-codec.js +68 -0
  36. package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
  37. package/dist/plugins/commonjs-esm-facade.js +80 -0
  38. package/dist/plugins/commonjs-syntax.d.ts +16 -0
  39. package/dist/plugins/commonjs-syntax.js +22 -0
  40. package/dist/plugins/fonts.d.ts +8 -11
  41. package/dist/plugins/fonts.js +71 -34
  42. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  43. package/dist/plugins/ignore-dynamic-requests.js +54 -3
  44. package/dist/plugins/import-meta-url.js +6 -6
  45. package/dist/plugins/og-asset-ownership.d.ts +2 -0
  46. package/dist/plugins/og-asset-ownership.js +24 -13
  47. package/dist/plugins/og-assets.d.ts +18 -0
  48. package/dist/plugins/og-assets.js +50 -8
  49. package/dist/plugins/og-harfbuzz.js +38 -27
  50. package/dist/plugins/optimize-imports.js +2 -1
  51. package/dist/plugins/require-context.d.ts +1 -0
  52. package/dist/plugins/require-context.js +28 -1
  53. package/dist/plugins/scan-build-css.d.ts +12 -0
  54. package/dist/plugins/scan-build-css.js +39 -0
  55. package/dist/plugins/strip-server-exports.d.ts +2 -0
  56. package/dist/plugins/strip-server-exports.js +3 -1
  57. package/dist/plugins/transform-result.d.ts +18 -0
  58. package/dist/plugins/transform-result.js +23 -2
  59. package/dist/plugins/typeof-window.d.ts +10 -0
  60. package/dist/plugins/typeof-window.js +33 -9
  61. package/dist/routing/app-route-graph.d.ts +0 -1
  62. package/dist/routing/app-route-graph.js +2 -4
  63. package/dist/routing/app-route-ids.d.ts +3 -0
  64. package/dist/routing/app-route-ids.js +6 -0
  65. package/dist/routing/file-matcher.d.ts +1 -0
  66. package/dist/routing/file-matcher.js +1 -1
  67. package/dist/server/api-handler.js +17 -7
  68. package/dist/server/app-bfcache-id.d.ts +1 -0
  69. package/dist/server/app-bfcache-id.js +7 -1
  70. package/dist/server/app-bfcache-identity.js +1 -2
  71. package/dist/server/app-browser-entry.js +15 -9
  72. package/dist/server/app-browser-history-controller.d.ts +2 -0
  73. package/dist/server/app-browser-history-controller.js +8 -0
  74. package/dist/server/app-browser-hydration.d.ts +1 -1
  75. package/dist/server/app-browser-hydration.js +2 -2
  76. package/dist/server/app-browser-interception-context.js +26 -2
  77. package/dist/server/app-browser-navigation-controller.d.ts +7 -1
  78. package/dist/server/app-browser-navigation-controller.js +94 -11
  79. package/dist/server/app-browser-state.js +1 -1
  80. package/dist/server/app-browser-stream.d.ts +1 -1
  81. package/dist/server/app-fallback-renderer.d.ts +2 -0
  82. package/dist/server/app-fallback-renderer.js +1 -0
  83. package/dist/server/app-history-state.d.ts +3 -1
  84. package/dist/server/app-history-state.js +9 -5
  85. package/dist/server/app-middleware.js +2 -1
  86. package/dist/server/app-optimistic-routing.js +1 -1
  87. package/dist/server/app-page-boundary-render.d.ts +5 -0
  88. package/dist/server/app-page-boundary-render.js +6 -4
  89. package/dist/server/app-page-cache-finalizer.d.ts +11 -0
  90. package/dist/server/app-page-cache-finalizer.js +41 -7
  91. package/dist/server/app-page-cache-render.d.ts +18 -0
  92. package/dist/server/app-page-cache-render.js +65 -44
  93. package/dist/server/app-page-cache.d.ts +5 -0
  94. package/dist/server/app-page-cache.js +27 -7
  95. package/dist/server/app-page-dispatch.d.ts +9 -1
  96. package/dist/server/app-page-dispatch.js +47 -30
  97. package/dist/server/app-page-element-builder.d.ts +7 -0
  98. package/dist/server/app-page-element-builder.js +27 -42
  99. package/dist/server/app-page-execution.d.ts +15 -12
  100. package/dist/server/app-page-execution.js +30 -40
  101. package/dist/server/app-page-head.d.ts +5 -0
  102. package/dist/server/app-page-head.js +9 -3
  103. package/dist/server/app-page-probe.d.ts +0 -109
  104. package/dist/server/app-page-probe.js +3 -136
  105. package/dist/server/app-page-render-identity.d.ts +0 -1
  106. package/dist/server/app-page-render-identity.js +1 -1
  107. package/dist/server/app-page-render-observation.js +2 -2
  108. package/dist/server/app-page-render.d.ts +13 -5
  109. package/dist/server/app-page-render.js +219 -118
  110. package/dist/server/app-page-request.d.ts +0 -1
  111. package/dist/server/app-page-request.js +1 -2
  112. package/dist/server/app-page-response.d.ts +4 -3
  113. package/dist/server/app-page-response.js +4 -3
  114. package/dist/server/app-page-route-wiring.d.ts +17 -5
  115. package/dist/server/app-page-route-wiring.js +55 -33
  116. package/dist/server/app-page-rsc-render-status.d.ts +48 -0
  117. package/dist/server/app-page-rsc-render-status.js +54 -0
  118. package/dist/server/app-page-search-params-observation.js +1 -1
  119. package/dist/server/app-page-stream.d.ts +15 -8
  120. package/dist/server/app-page-stream.js +7 -1
  121. package/dist/server/app-page-tracing.js +2 -1
  122. package/dist/server/app-pages-bridge.js +3 -2
  123. package/dist/server/app-render-abort-error.d.ts +3 -0
  124. package/dist/server/app-render-abort-error.js +8 -0
  125. package/dist/server/app-request-stage-dispatch.js +1 -1
  126. package/dist/server/app-request-stage-independent-entry.js +8 -11
  127. package/dist/server/app-response-header-provenance.d.ts +2 -0
  128. package/dist/server/app-response-header-provenance.js +10 -4
  129. package/dist/server/app-route-handler-cache.d.ts +2 -1
  130. package/dist/server/app-route-handler-cache.js +11 -7
  131. package/dist/server/app-route-handler-dispatch.js +11 -4
  132. package/dist/server/app-route-handler-execution.d.ts +9 -1
  133. package/dist/server/app-route-handler-execution.js +28 -13
  134. package/dist/server/app-route-handler-policy.js +2 -2
  135. package/dist/server/app-route-handler-response.d.ts +1 -1
  136. package/dist/server/app-route-handler-response.js +14 -5
  137. package/dist/server/app-router-entry.d.ts +2 -1
  138. package/dist/server/app-router-entry.js +8 -12
  139. package/dist/server/app-rsc-errors.d.ts +0 -1
  140. package/dist/server/app-rsc-errors.js +2 -6
  141. package/dist/server/app-rsc-handler.d.ts +5 -0
  142. package/dist/server/app-rsc-handler.js +229 -102
  143. package/dist/server/app-rsc-request-normalization.d.ts +4 -2
  144. package/dist/server/app-rsc-request-normalization.js +7 -4
  145. package/dist/server/app-rsc-response-finalizer.js +4 -1
  146. package/dist/server/app-rsc-response-stage.d.ts +1 -1
  147. package/dist/server/app-rsc-response-stage.js +6 -4
  148. package/dist/server/app-rsc-route-matching.d.ts +9 -1
  149. package/dist/server/app-rsc-route-matching.js +37 -20
  150. package/dist/server/app-server-action-execution.d.ts +2 -1
  151. package/dist/server/app-server-action-execution.js +1 -1
  152. package/dist/server/app-ssr-entry.d.ts +3 -2
  153. package/dist/server/app-ssr-entry.js +9 -7
  154. package/dist/server/app-ssr-search-params-gate.js +1 -1
  155. package/dist/server/app-ssr-stream.d.ts +6 -1
  156. package/dist/server/app-ssr-stream.js +35 -16
  157. package/dist/server/app-worker-stages.d.ts +2 -2
  158. package/dist/server/app-worker-stages.js +3 -3
  159. package/dist/server/cache-control.js +3 -11
  160. package/dist/server/cacheability-request.js +56 -52
  161. package/dist/server/config-headers.js +3 -1
  162. package/dist/server/dev-server.js +23 -5
  163. package/dist/server/headers.d.ts +16 -0
  164. package/dist/server/headers.js +19 -1
  165. package/dist/server/http-error-responses.js +1 -0
  166. package/dist/server/image-optimization.d.ts +16 -0
  167. package/dist/server/image-optimization.js +26 -6
  168. package/dist/server/isr-cache.d.ts +2 -0
  169. package/dist/server/isr-cache.js +8 -3
  170. package/dist/server/metadata-route-response.js +94 -37
  171. package/dist/server/middleware-matcher-pattern.js +8 -4
  172. package/dist/server/middleware-response-headers.js +2 -0
  173. package/dist/server/multi-stage.d.ts +8 -0
  174. package/dist/server/navigation-planner.js +1 -1
  175. package/dist/server/node-response-signal.d.ts +16 -0
  176. package/dist/server/node-response-signal.js +26 -0
  177. package/dist/server/open-redirect.d.ts +47 -0
  178. package/dist/server/open-redirect.js +74 -1
  179. package/dist/server/pages-api-route.js +8 -2
  180. package/dist/server/pages-asset-tags.d.ts +1 -0
  181. package/dist/server/pages-asset-tags.js +73 -22
  182. package/dist/server/pages-client-assets.d.ts +2 -0
  183. package/dist/server/pages-page-data.d.ts +6 -1
  184. package/dist/server/pages-page-data.js +71 -65
  185. package/dist/server/pages-page-handler.js +50 -15
  186. package/dist/server/pages-page-response.js +3 -1
  187. package/dist/server/pages-request-pipeline.d.ts +2 -1
  188. package/dist/server/pages-request-pipeline.js +20 -5
  189. package/dist/server/pages-request-stage-entry.js +14 -8
  190. package/dist/server/prerender-manifest.d.ts +6 -0
  191. package/dist/server/prerender-manifest.js +1 -1
  192. package/dist/server/prod-server.d.ts +8 -7
  193. package/dist/server/prod-server.js +152 -78
  194. package/dist/server/request-pipeline.d.ts +20 -8
  195. package/dist/server/request-pipeline.js +21 -7
  196. package/dist/server/response-compression.d.ts +43 -0
  197. package/dist/server/response-compression.js +111 -0
  198. package/dist/server/response-stage-cacheability.js +1 -1
  199. package/dist/server/seed-cache.js +10 -7
  200. package/dist/server/socket-error-backstop.d.ts +14 -0
  201. package/dist/server/socket-error-backstop.js +27 -4
  202. package/dist/server/worker-revalidation-context.d.ts +2 -1
  203. package/dist/server/worker-revalidation-context.js +1 -0
  204. package/dist/server/workers-tracing.d.ts +17 -0
  205. package/dist/server/workers-tracing.js +48 -8
  206. package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
  207. package/dist/shims/cache-adapter-instantiate.js +118 -0
  208. package/dist/shims/cache-callable-runtime.d.ts +2 -40
  209. package/dist/shims/cache-callable-runtime.js +50 -168
  210. package/dist/shims/cache-flight-arguments.d.ts +22 -0
  211. package/dist/shims/cache-flight-arguments.js +56 -0
  212. package/dist/shims/cache-request-state.d.ts +18 -14
  213. package/dist/shims/cache-request-state.js +33 -21
  214. package/dist/shims/cache-runtime.d.ts +6 -19
  215. package/dist/shims/cache-runtime.js +168 -226
  216. package/dist/shims/cache.d.ts +3 -2
  217. package/dist/shims/cache.js +8 -5
  218. package/dist/shims/cacheability-classification.d.ts +8 -1
  219. package/dist/shims/cacheability-classification.js +2 -2
  220. package/dist/shims/cdn-cache.d.ts +10 -1
  221. package/dist/shims/cdn-cache.js +16 -9
  222. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  223. package/dist/shims/error-boundary-navigation.js +19 -1
  224. package/dist/shims/error-boundary.d.ts +10 -10
  225. package/dist/shims/error-boundary.js +26 -7
  226. package/dist/shims/error.d.ts +4 -18
  227. package/dist/shims/error.js +17 -10
  228. package/dist/shims/error.react-server.d.ts +4 -6
  229. package/dist/shims/error.react-server.js +4 -1
  230. package/dist/shims/fetch-cache.d.ts +6 -0
  231. package/dist/shims/fetch-cache.js +23 -4
  232. package/dist/shims/form.js +1 -1
  233. package/dist/shims/headers.d.ts +19 -69
  234. package/dist/shims/headers.js +82 -183
  235. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
  236. package/dist/shims/internal/app-page-props-cache-key.js +24 -15
  237. package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
  238. package/dist/shims/internal/cache-context-accessor.js +15 -0
  239. package/dist/shims/internal/headers-state.d.ts +73 -0
  240. package/dist/shims/internal/headers-state.js +157 -0
  241. package/dist/shims/metadata.js +3 -3
  242. package/dist/shims/navigation-errors.d.ts +6 -0
  243. package/dist/shims/navigation-errors.js +11 -1
  244. package/dist/shims/navigation.d.ts +7 -0
  245. package/dist/shims/navigation.js +16 -6
  246. package/dist/shims/request-context.d.ts +9 -0
  247. package/dist/shims/request-state-types.d.ts +2 -1
  248. package/dist/shims/root-params.js +1 -1
  249. package/dist/shims/server.js +52 -2
  250. package/dist/shims/thenable-params.d.ts +4 -0
  251. package/dist/shims/thenable-params.js +25 -3
  252. package/dist/shims/unified-request-context.d.ts +1 -1
  253. package/dist/shims/unified-request-context.js +1 -0
  254. package/dist/utils/encode-cache-tag.d.ts +1 -0
  255. package/dist/utils/encode-cache-tag.js +11 -1
  256. package/dist/utils/mdx-scan.d.ts +5 -0
  257. package/dist/utils/mdx-scan.js +8 -1
  258. package/dist/utils/regex-safety.d.ts +10 -0
  259. package/dist/utils/regex-safety.js +70 -18
  260. package/dist/utils/vite-cli-invocation.js +8 -1
  261. package/package.json +8 -4
  262. package/dist/server/metadata-route-cache-policy.d.ts +0 -5
  263. package/dist/server/metadata-route-cache-policy.js +0 -6
@@ -2,5 +2,5 @@ import { VinextResponseStageDispatchOptions } from "./multi-stage.js";
2
2
  import { AppWorkerResponseStageProps } from "./app-worker-stages.js";
3
3
  import { AppRscHandlerRoute, CreateAppRscHandlerOptions } from "./app-rsc-handler.js";
4
4
  //#region src/server/app-rsc-response-stage.d.ts
5
- export declare function renderAppWorkerResponseStage<TRoute extends AppRscHandlerRoute>(options: CreateAppRscHandlerOptions<TRoute>, rawRequest: Request, ctx: unknown, props: AppWorkerResponseStageProps, _stageOptions?: VinextResponseStageDispatchOptions): Promise<Response>;
5
+ export declare function renderAppWorkerResponseStage<TRoute extends AppRscHandlerRoute>(options: CreateAppRscHandlerOptions<TRoute>, rawRequest: Request, ctx: unknown, props: AppWorkerResponseStageProps, stageOptions?: VinextResponseStageDispatchOptions): Promise<Response>;
6
6
  //#endregion
@@ -60,14 +60,15 @@ function rematchAppWorkerResponseStageRoute(options, normalized, props) {
60
60
  let match = null;
61
61
  if (props.matchKind === "interception") {
62
62
  if (normalized.interceptionContextHeader !== null) match = options.matchInterceptRoute?.(props.routePathname, normalized.interceptionContextHeader, props.interceptionId) ?? null;
63
- } else if (props.matchKind === "request") match = options.matchRequestRoute?.(props.routePathname) ?? null;
63
+ } else if (props.matchKind === "raw-request") match = options.matchRawRequestRoute?.(props.routePathname) ?? null;
64
+ else if (props.matchKind === "request") match = options.matchRequestRoute?.(props.routePathname) ?? null;
64
65
  else match = options.matchRoute(props.routePathname);
65
66
  if (!match) return null;
66
67
  if (match.route.pattern !== props.routePattern || !haveSamePageParams(match.params, props.params)) return null;
67
68
  return match;
68
69
  }
69
- async function renderAppWorkerResponseStage(options, rawRequest, ctx, props, _stageOptions) {
70
- if (props.protocolVersion !== 10 || props.buildId !== options.buildId) return new Response("Incompatible vinext App response stage", { status: 409 });
70
+ async function renderAppWorkerResponseStage(options, rawRequest, ctx, props, stageOptions) {
71
+ if (props.protocolVersion !== 11 || props.buildId !== options.buildId) return new Response("Incompatible vinext App response stage", { status: 409 });
71
72
  if (props.kind === "app-full-request") return new Response("Invalid vinext App response stage", { status: 400 });
72
73
  options.registerCacheAdapters();
73
74
  await options.ensureInstrumentation?.();
@@ -232,7 +233,8 @@ async function renderAppWorkerResponseStage(options, rawRequest, ctx, props, _st
232
233
  route,
233
234
  searchParams,
234
235
  scriptNonce: props.scriptNonce ?? void 0,
235
- renderMode: normalized.renderMode
236
+ renderMode: normalized.renderMode,
237
+ renderWholeDocument: stageOptions?.renderWholeDocument === true
236
238
  });
237
239
  }, {
238
240
  cacheComponents: options.createPprFallbackShells !== void 0,
@@ -120,7 +120,11 @@ type AppRscInterceptLookupEntry = {
120
120
  slotId: string | null;
121
121
  targetRouteGraphId: string | null;
122
122
  };
123
- export declare function createAppRscRouteMatcher<Route extends AppRscRouteForMatching>(routes: Route[]): {
123
+ /**
124
+ * @param decodedPathnamePatterns Static page patterns that answer their
125
+ * segment-decoded pathname (built by `buildAppDecodedPathnamePatterns`).
126
+ */
127
+ export declare function createAppRscRouteMatcher<Route extends AppRscRouteForMatching>(routes: Route[], decodedPathnamePatterns?: readonly string[]): {
124
128
  hasInterceptionId(interceptionId: string): boolean;
125
129
  matchRoute(url: string): {
126
130
  route: Route;
@@ -130,6 +134,10 @@ export declare function createAppRscRouteMatcher<Route extends AppRscRouteForMat
130
134
  route: Route;
131
135
  params: AppRscRouteParams;
132
136
  } | null;
137
+ matchRawRequestRoute(url: string): {
138
+ route: Route;
139
+ params: AppRscRouteParams;
140
+ } | null;
133
141
  findIntercept(pathname: string, sourcePathname?: string | null, interceptionId?: string | null): AppRscInterceptMatch | null;
134
142
  };
135
143
  //#endregion
@@ -1,5 +1,5 @@
1
- import { decodeMatchedParams, splitPathSegments, splitPathnameForRouteMatch } from "../routing/utils.js";
2
- import { createAppRouteGraphInterceptionId } from "../routing/app-route-graph.js";
1
+ import { decodeMatchedParams, decodeRouteSegment, splitPathSegments, splitPathnameForRouteMatch } from "../routing/utils.js";
2
+ import { createAppRouteGraphInterceptionId } from "../routing/app-route-ids.js";
3
3
  import { buildRouteTrie, trieMatchRaw } from "../routing/route-trie.js";
4
4
  import { extractRawRoutePatternParams, matchRoutePatternPrefix, matchRoutePatternRaw } from "../routing/route-pattern.js";
5
5
  import { canonicalizeAppPageParams } from "./app-page-segment-state.js";
@@ -18,17 +18,6 @@ function appRscPathnameParts(pathname, isNormalized = false) {
18
18
  const normalizedPathname = pathOnly === "/" ? "/" : pathOnly.replace(/\/$/, "");
19
19
  return isNormalized ? splitPathSegments(normalizedPathname) : splitPathnameForRouteMatch(normalizedPathname);
20
20
  }
21
- function appRscInterceptionSourcePathnameParts(pathname) {
22
- const pathOnly = pathname.split("?")[0];
23
- const normalizedPathname = pathOnly === "/" ? "/" : pathOnly.replace(/\/$/, "");
24
- return splitPathSegments(normalizedPathname).map((segment) => {
25
- try {
26
- return decodeURIComponent(segment);
27
- } catch {
28
- return segment;
29
- }
30
- });
31
- }
32
21
  function isAppRouteHandlerRoute(route) {
33
22
  return route.routeHandler != null || typeof route.__loadRouteHandler === "function";
34
23
  }
@@ -36,11 +25,38 @@ function normalizeMatchedParamsForRoute(result) {
36
25
  if (isAppRouteHandlerRoute(result.route)) decodeMatchedParams(result.params);
37
26
  else canonicalizeAppPageParams(result.params);
38
27
  }
39
- function createAppRscRouteMatcher(routes) {
28
+ /**
29
+ * @param decodedPathnamePatterns Static page patterns that answer their
30
+ * segment-decoded pathname (built by `buildAppDecodedPathnamePatterns`).
31
+ */
32
+ function createAppRscRouteMatcher(routes, decodedPathnamePatterns = []) {
40
33
  const routeTrie = buildRouteTrie(routes);
41
34
  const interceptLookup = createInterceptLookup(routes);
42
35
  const interceptionIds = new Set(interceptLookup.flatMap((entry) => entry.interceptionId === null ? [] : [entry.interceptionId]));
43
36
  const routeIndexes = new Map(routes.map((route, index) => [route, index]));
37
+ const decodedPathnamePatternSet = new Set(decodedPathnamePatterns);
38
+ const decodedPathnameRoutes = /* @__PURE__ */ new Map();
39
+ for (const route of routes) {
40
+ const key = route.patternParts.join("/");
41
+ if (decodedPathnamePatternSet.has(route.pattern) && !decodedPathnameRoutes.has(key)) decodedPathnameRoutes.set(key, route);
42
+ }
43
+ function matchRawRequestParts(rawParts) {
44
+ const result = trieMatchRaw(routeTrie, rawParts);
45
+ if (result) normalizeMatchedParamsForRoute(result);
46
+ return result;
47
+ }
48
+ function matchRequestParts(rawParts) {
49
+ const result = matchRawRequestParts(rawParts);
50
+ if (!result) return null;
51
+ if (decodedPathnameRoutes.size > 0 && result.route.patternParts.some((part) => part.startsWith(":")) && !isAppRouteHandlerRoute(result.route) && rawParts.some((part) => part.includes("%"))) {
52
+ const route = decodedPathnameRoutes.get(rawParts.map(decodeRouteSegment).join("/"));
53
+ if (route && route !== result.route) return {
54
+ route,
55
+ params: createRouteParams()
56
+ };
57
+ }
58
+ return result;
59
+ }
44
60
  return {
45
61
  hasInterceptionId(interceptionId) {
46
62
  return interceptionIds.has(interceptionId);
@@ -54,16 +70,16 @@ function createAppRscRouteMatcher(routes) {
54
70
  return result;
55
71
  },
56
72
  matchRequestRoute(url) {
57
- const result = trieMatchRaw(routeTrie, appRscPathnameParts(url, true));
58
- if (!result) return null;
59
- normalizeMatchedParamsForRoute(result);
60
- return result;
73
+ return matchRequestParts(appRscPathnameParts(url, true));
74
+ },
75
+ matchRawRequestRoute(url) {
76
+ return matchRawRequestParts(appRscPathnameParts(url, true));
61
77
  },
62
78
  findIntercept(pathname, sourcePathname = null, interceptionId = null) {
63
79
  if (sourcePathname === null) return null;
64
80
  const urlParts = appRscPathnameParts(pathname, true);
65
- const sourceParts = appRscInterceptionSourcePathnameParts(sourcePathname);
66
- const matchedSourceRoute = trieMatchRaw(routeTrie, sourceParts);
81
+ const sourceParts = appRscPathnameParts(sourcePathname, true);
82
+ const matchedSourceRoute = matchRawRequestParts(sourceParts);
67
83
  for (const entry of interceptLookup) {
68
84
  if (interceptionId !== null && entry.interceptionId !== interceptionId) continue;
69
85
  if (!matchInterceptSource(sourceParts, entry)) continue;
@@ -75,6 +91,7 @@ function createAppRscRouteMatcher(routes) {
75
91
  const sourceRoute = routes[concreteSourceRouteIndex];
76
92
  if (sourceRoute && isAppRouteHandlerRoute(sourceRoute)) continue;
77
93
  const matchedSourceParams = concreteSourceRoute ? concreteSourceRoute.params : sourceRoute ? matchSlotOwnerSourceParams(sourceParts, sourceRoute.patternParts, entry.sourceMatchPatternParts !== null) : null;
94
+ if (!concreteSourceRoute && matchedSourceParams) canonicalizeAppPageParams(matchedSourceParams);
78
95
  if (matchedSourceParams === null && entry.sourceMatchPatternParts === null) continue;
79
96
  const sourceParams = matchedSourceParams && entry.sourceMatchPatternParts !== null ? pickPatternParams(matchedSourceParams, entry.sourceMatchPatternParts) : matchedSourceParams ?? createRouteParams();
80
97
  return {
@@ -2,7 +2,8 @@ import { AppRscRenderMode } from "./app-rsc-render-mode.js";
2
2
  import { ActionRevalidationKind } from "../shims/cache-request-state.js";
3
3
  import { AppRenderErrorContextOverrides } from "./app-rsc-error-handler.js";
4
4
  import { FetchCacheMode } from "../shims/fetch-cache.js";
5
- import { HeadersAccessPhase } from "../shims/headers.js";
5
+ import { HeadersAccessPhase } from "../shims/internal/headers-state.js";
6
+ import "../shims/headers.js";
6
7
  import { ReactFormState } from "react-dom/client";
7
8
  //#region src/server/app-server-action-execution.d.ts
8
9
  type AppPageParams = Record<string, string | string[]>;
@@ -19,10 +19,10 @@ import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js
19
19
  import { applyEdgeRuntimeHeader } from "./app-page-response.js";
20
20
  import { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
21
21
  import { buildAppPageTags } from "./implicit-tags.js";
22
+ import "./app-page-stream.js";
22
23
  import { getSetCookieName } from "./cookie-utils.js";
23
24
  import { createServerActionNotFoundResponse, getServerActionNotFoundMessage, isServerActionNotFoundError } from "./server-action-not-found.js";
24
25
  import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
25
- import "./app-page-stream.js";
26
26
  import { resolveAppPageActionRerenderTarget } from "./app-page-request.js";
27
27
  import { createRootParamsUsageController, runWithRootParamsUsage } from "../shims/root-params.js";
28
28
  import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
@@ -46,8 +46,9 @@ export declare function handleSsr(rscStream: ReadableStream<Uint8Array>, navCont
46
46
  initialDevServerError?: unknown;
47
47
  /** Report an SSR/Fizz render failure through instrumentation. */
48
48
  onSsrError?: (error: unknown) => unknown;
49
- /** Mirror inline Flight chunks into Next.js's `self.__next_f` transport. */
50
- mirrorNextFlight?: boolean;
49
+ /** Mirror inline Flight chunks into Next.js's `self.__next_f` transport, or start
50
+ * mirroring once a function returns true. */
51
+ mirrorNextFlight?: boolean | (() => boolean);
51
52
  /** When true, wait for the full React tree (including Suspense boundaries)
52
53
  * to resolve before returning the HTML stream. Used for static prerender
53
54
  * and ISR cache writes to avoid caching fallback content. */
@@ -1,10 +1,8 @@
1
1
  import "./server-globals.js";
2
2
  import { notFoundResponse } from "./http-error-responses.js";
3
- import { isOpenRedirectShaped } from "./open-redirect.js";
4
- import { AppElementsWire } from "./app-elements-wire.js";
5
- import "./app-elements.js";
3
+ import { isOpenRedirectShaped, repeatedSlashRedirectResponse } from "./open-redirect.js";
6
4
  import { isPprFallbackShellAbortError } from "../shims/ppr-fallback-shell.js";
7
- import { onRenderDynamicLatched } from "../shims/headers.js";
5
+ import { onRenderDynamicLatched } from "../shims/internal/headers-state.js";
8
6
  import { AppRouterContext } from "../shims/internal/app-router-context.js";
9
7
  import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
10
8
  import { withScriptNonce } from "../shims/script-nonce-context.js";
@@ -12,18 +10,20 @@ import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr, safeJsonSt
12
10
  import { getClientTraceMetadataHTML, markClientTraceMetadataBlock } from "./client-trace-metadata.js";
13
11
  import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
14
12
  import { setPagesClientAssets } from "./pages-client-assets.js";
13
+ import { AppElementsWire } from "./app-elements-wire.js";
14
+ import "./app-elements.js";
15
15
  import { ServerInsertedHTMLContext, clearServerInsertedHTML, getBfcacheIdMapContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "../shims/navigation-context-state.js";
16
16
  import "../shims/navigation-server.js";
17
17
  import DefaultGlobalError from "../shims/default-global-error.js";
18
18
  import { BfcacheIdentityMapContext, ElementsContext, Slot } from "../shims/slot.js";
19
19
  import { getNextErrorDigest } from "./next-error-digest.js";
20
20
  import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
21
- import { createClientPageSsrSearchParamsSource } from "./app-page-search-params-observation.js";
22
- import { isAppRenderAbortError } from "./app-rsc-errors.js";
21
+ import { isAppRenderAbortError } from "./app-render-abort-error.js";
22
+ import { RSC_FORM_STATE_GLOBAL } from "../client/browser-globals.js";
23
23
  import { createNavigationRuntimeRenderedSearchScript, createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, waitAtLeastOneReactRenderTask } from "./app-ssr-stream.js";
24
24
  import { createInitialBfcacheMaps } from "./app-bfcache-identity.js";
25
- import { RSC_FORM_STATE_GLOBAL } from "./app-browser-hydration.js";
26
25
  import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
26
+ import { createClientPageSsrSearchParamsSource } from "./app-page-search-params-observation.js";
27
27
  import { runWithRootParamsScope } from "../shims/root-params.js";
28
28
  import { runWithNavigationContext } from "../shims/navigation-state.js";
29
29
  import { startCandidateSearchParamsGate } from "./app-ssr-search-params-gate.js";
@@ -357,6 +357,8 @@ async function handleSsr(rscStream, navContext, fontData, options) {
357
357
  }
358
358
  var app_ssr_entry_default = { async fetch(request) {
359
359
  const url = new URL(request.url);
360
+ const slashRedirect = repeatedSlashRedirectResponse(url.pathname + url.search);
361
+ if (slashRedirect) return slashRedirect;
360
362
  if (isOpenRedirectShaped(url.pathname)) return notFoundResponse();
361
363
  const result = await (await import.meta.viteRsc.loadModule("rsc", "index")).default(request);
362
364
  if (result instanceof Response) return result;
@@ -1,4 +1,4 @@
1
- import { isRenderDynamicLatched, markDynamicUsage, onRenderDynamicLatched } from "../shims/headers.js";
1
+ import { isRenderDynamicLatched, markDynamicUsage, onRenderDynamicLatched } from "../shims/internal/headers-state.js";
2
2
  import { createSearchParamsGate } from "../shims/search-params-gate.js";
3
3
  //#region src/server/app-ssr-search-params-gate.ts
4
4
  /**
@@ -6,7 +6,12 @@ type RscEmbedTransform = {
6
6
  getRawBuffer(): Promise<ArrayBuffer>;
7
7
  };
8
8
  type RscEmbedTransformOptions = {
9
- mirrorNextFlight?: boolean;
9
+ /**
10
+ * Mirror inline Flight chunks into Next.js's `self.__next_f` transport. A
11
+ * function is checked at each flush; once it returns true, the chunks
12
+ * already embedded are mirrored first.
13
+ */
14
+ mirrorNextFlight?: boolean | (() => boolean);
10
15
  scriptNonce?: string;
11
16
  getInitialNavigationCacheMetadata?: () => InitialNavigationCacheMetadata;
12
17
  };
@@ -1,6 +1,6 @@
1
1
  import { createInlineScriptTag, escapeHtmlAttr, htmlTokenListContains, safeJsonStringify } from "./html.js";
2
2
  import { bytesToBase64, concatUint8Arrays } from "./app-rsc-embedded-chunks.js";
3
- import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "../client/navigation-runtime.js";
3
+ import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "../client/browser-globals.js";
4
4
  //#region src/server/app-ssr-stream.ts
5
5
  const RSC_EMBED_TEXT_BATCH_MAX_LENGTH = 65536;
6
6
  function waitAtLeastOneReactRenderTask() {
@@ -49,12 +49,36 @@ function createRscEmbedTransform(embedStream, optionsOrNonce = {}) {
49
49
  const reader = embedStream.getReader();
50
50
  let pendingChunks = [];
51
51
  const rawChunks = [];
52
+ let embeddedRawChunkCount = 0;
53
+ let rawBufferTaken = false;
54
+ let finalized = false;
52
55
  let reading = false;
53
56
  let mirroredNextFlightBootstrap = false;
54
57
  const textDecoder = new TextDecoder("utf-8", {
55
58
  fatal: true,
56
59
  ignoreBOM: true
57
60
  });
61
+ function decodeChunk(bytes) {
62
+ try {
63
+ return textDecoder.decode(bytes);
64
+ } catch {
65
+ return [3, bytesToBase64(bytes)];
66
+ }
67
+ }
68
+ function releaseRawChunks() {
69
+ const mayStartMirror = typeof options.mirrorNextFlight === "function" && !mirroredNextFlightBootstrap && !finalized;
70
+ if (rawBufferTaken && !mayStartMirror) rawChunks.length = 0;
71
+ }
72
+ function startNextFlightMirror() {
73
+ if (mirroredNextFlightBootstrap) return "";
74
+ const mirror = options.mirrorNextFlight;
75
+ if (mirror !== true && (typeof mirror !== "function" || !mirror())) return "";
76
+ mirroredNextFlightBootstrap = true;
77
+ let scripts = createInlineScriptTag(createNextFlightBootstrapScript(), options.scriptNonce) + createInlineScriptTag(createNextFlightCleanupScript(), options.scriptNonce);
78
+ for (let index = 0; index < embeddedRawChunkCount; index++) scripts += createInlineScriptTag(createNextFlightChunkScript(decodeChunk(rawChunks[index])), options.scriptNonce);
79
+ releaseRawChunks();
80
+ return scripts;
81
+ }
58
82
  async function pumpReader() {
59
83
  if (reading) return;
60
84
  reading = true;
@@ -63,11 +87,7 @@ function createRscEmbedTransform(embedStream, optionsOrNonce = {}) {
63
87
  const result = await reader.read();
64
88
  if (result.done) break;
65
89
  rawChunks.push(result.value);
66
- try {
67
- pendingChunks.push(textDecoder.decode(result.value));
68
- } catch {
69
- pendingChunks.push([3, bytesToBase64(result.value)]);
70
- }
90
+ pendingChunks.push(decodeChunk(result.value));
71
91
  }
72
92
  } catch (error) {
73
93
  if (process.env.NODE_ENV !== "production") console.warn("[vinext] RSC embed stream read error:", error);
@@ -80,8 +100,10 @@ function createRscEmbedTransform(embedStream, optionsOrNonce = {}) {
80
100
  return {
81
101
  flush() {
82
102
  if (pendingChunks.length === 0) return "";
103
+ const mirrorScripts = startNextFlightMirror();
83
104
  const chunks = pendingChunks;
84
105
  pendingChunks = [];
106
+ embeddedRawChunkCount += chunks.length;
85
107
  const embeddedChunks = [];
86
108
  let textChunks = [];
87
109
  let textLength = 0;
@@ -100,30 +122,27 @@ function createRscEmbedTransform(embedStream, optionsOrNonce = {}) {
100
122
  embeddedChunks.push(chunk);
101
123
  }
102
124
  flushTextChunks();
103
- let scripts = "";
125
+ let scripts = mirrorScripts;
104
126
  for (const chunk of embeddedChunks) {
105
127
  scripts += createInlineScriptTag(createNavigationRuntimeRscChunkScript(chunk), options.scriptNonce);
106
- if (options.mirrorNextFlight) {
107
- if (!mirroredNextFlightBootstrap) {
108
- scripts += createInlineScriptTag(createNextFlightBootstrapScript(), options.scriptNonce);
109
- scripts += createInlineScriptTag(createNextFlightCleanupScript(), options.scriptNonce);
110
- mirroredNextFlightBootstrap = true;
111
- }
112
- scripts += createInlineScriptTag(createNextFlightChunkScript(chunk), options.scriptNonce);
113
- }
128
+ if (mirroredNextFlightBootstrap) scripts += createInlineScriptTag(createNextFlightChunkScript(chunk), options.scriptNonce);
114
129
  }
115
130
  return scripts;
116
131
  },
117
132
  async finalize() {
118
133
  await pumpPromise;
119
134
  let scripts = this.flush();
135
+ scripts += startNextFlightMirror();
136
+ finalized = true;
137
+ releaseRawChunks();
120
138
  scripts += createInlineScriptTag(createNavigationRuntimeRscDoneScript(options.getInitialNavigationCacheMetadata?.()), options.scriptNonce);
121
139
  return scripts;
122
140
  },
123
141
  async getRawBuffer() {
124
142
  await pumpPromise;
125
143
  const buffer = concatUint8Arrays(rawChunks);
126
- rawChunks.length = 0;
144
+ rawBufferTaken = true;
145
+ releaseRawChunks();
127
146
  return buffer.buffer;
128
147
  }
129
148
  };
@@ -3,7 +3,7 @@ import { VinextResponseStageCacheability, VinextResponseStageDispatchOptions, Vi
3
3
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
4
4
  import { TrustedPrerenderState } from "./prerender-route-params.js";
5
5
  //#region src/server/app-worker-stages.d.ts
6
- export declare const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION = 10;
6
+ export declare const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION = 11;
7
7
  export declare const APP_METADATA_RESPONSE_STAGE_NO_MATCH_HEADER = "x-vinext-app-metadata-stage-no-match";
8
8
  type AppPageParams = Record<string, string | string[]>;
9
9
  type AppWorkerResponseStageEnvelope = {
@@ -34,7 +34,7 @@ export type AppMatchedWorkerResponseStageProps = AppWorkerResponseStageEnvelope
34
34
  interceptionContext: string | null;
35
35
  interceptionId: string | null;
36
36
  isRscRequest: boolean;
37
- matchKind: "interception" | "request" | "resolved";
37
+ matchKind: "interception" | "raw-request" | "request" | "resolved";
38
38
  mountedSlotsHeader: string | null;
39
39
  params: AppPageParams;
40
40
  resolvedUrl: string;
@@ -3,7 +3,7 @@ import { cacheabilityManifestPageState, cacheabilityRequestIdentity, cacheabilit
3
3
  import { keepOnlyValidatedRscCacheBustingSearchParam } from "./app-rsc-cache-busting.js";
4
4
  import { isTrustedPrerenderState } from "./prerender-route-params.js";
5
5
  //#region src/server/app-worker-stages.ts
6
- const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION = 10;
6
+ const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION = 11;
7
7
  const APP_METADATA_RESPONSE_STAGE_NO_MATCH_HEADER = "x-vinext-app-metadata-stage-no-match";
8
8
  const STATIC_FILE_SIGNAL_TOKEN_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
9
9
  /** Normalize a shared App page HEAD request onto its method-invariant GET representation. */
@@ -80,7 +80,7 @@ function isCanonicalHttpOrigin(value) {
80
80
  function isAppWorkerResponseStageProps(value) {
81
81
  if (!value || typeof value !== "object") return false;
82
82
  const props = value;
83
- if (props.protocolVersion !== 10 || props.buildId !== null && typeof props.buildId !== "string" || !isResponseStageCacheability(props.cacheability) || props.draftModeCookie !== null && typeof props.draftModeCookie !== "string" || props.middlewareCookieOverlay !== null && typeof props.middlewareCookieOverlay !== "string" || !isCanonicalHttpOrigin(props.requestOrigin) || props.scriptNonce !== null && typeof props.scriptNonce !== "string") return false;
83
+ if (props.protocolVersion !== 11 || props.buildId !== null && typeof props.buildId !== "string" || !isResponseStageCacheability(props.cacheability) || props.draftModeCookie !== null && typeof props.draftModeCookie !== "string" || props.middlewareCookieOverlay !== null && typeof props.middlewareCookieOverlay !== "string" || !isCanonicalHttpOrigin(props.requestOrigin) || props.scriptNonce !== null && typeof props.scriptNonce !== "string") return false;
84
84
  if (props.kind === "app-full-request") return typeof props.prerenderDiscovery === "boolean" && typeof props.staticFileSignalToken === "string" && STATIC_FILE_SIGNAL_TOKEN_RE.test(props.staticFileSignalToken) && (props.trustedPrerenderState === null || isTrustedPrerenderState(props.trustedPrerenderState));
85
85
  if (props.kind === "hybrid-pages") {
86
86
  const hybrid = props;
@@ -91,7 +91,7 @@ function isAppWorkerResponseStageProps(value) {
91
91
  const special = props;
92
92
  return typeof special.canonicalPathname === "string" && special.canonicalPathname.startsWith("/") && typeof special.cleanPathname === "string" && special.cleanPathname.startsWith("/") && typeof special.isRscRequest === "boolean" && (special.mountedSlotsHeader === null || typeof special.mountedSlotsHeader === "string") && typeof special.resolvedUrl === "string" && special.resolvedUrl.startsWith("/") && (props.kind !== "app-metadata" || typeof props.routePathname === "string" && props.routePathname.startsWith("/")) && (special.renderMode === "navigation" || special.renderMode === "prefetch-empty" || special.renderMode === "prefetch-dynamic-shell" || special.renderMode === "prefetch-loading-shell");
93
93
  }
94
- return (props.kind === "app-page" || props.kind === "app-route-handler") && typeof props.bypassInterceptionContextCache === "boolean" && typeof props.cachePathname === "string" && props.cachePathname.startsWith("/") && typeof props.canUseCanonicalLoadingShell === "boolean" && typeof props.canonicalPathname === "string" && props.canonicalPathname.startsWith("/") && typeof props.cleanPathname === "string" && props.cleanPathname.startsWith("/") && (props.forceDynamic === void 0 || typeof props.forceDynamic === "boolean") && (props.interceptionContext === null || typeof props.interceptionContext === "string") && (props.interceptionId === null || typeof props.interceptionId === "string") && typeof props.isRscRequest === "boolean" && (props.matchKind === "interception" || props.matchKind === "request" || props.matchKind === "resolved") && (props.mountedSlotsHeader === null || typeof props.mountedSlotsHeader === "string") && isAppPageParams(props.params) && typeof props.resolvedUrl === "string" && props.resolvedUrl.startsWith("/") && typeof props.routePattern === "string" && props.routePattern.startsWith("/") && typeof props.routePathname === "string" && props.routePathname.startsWith("/") && (props.renderMode === "navigation" || props.renderMode === "prefetch-empty" || props.renderMode === "prefetch-dynamic-shell" || props.renderMode === "prefetch-loading-shell");
94
+ return (props.kind === "app-page" || props.kind === "app-route-handler") && typeof props.bypassInterceptionContextCache === "boolean" && typeof props.cachePathname === "string" && props.cachePathname.startsWith("/") && typeof props.canUseCanonicalLoadingShell === "boolean" && typeof props.canonicalPathname === "string" && props.canonicalPathname.startsWith("/") && typeof props.cleanPathname === "string" && props.cleanPathname.startsWith("/") && (props.forceDynamic === void 0 || typeof props.forceDynamic === "boolean") && (props.interceptionContext === null || typeof props.interceptionContext === "string") && (props.interceptionId === null || typeof props.interceptionId === "string") && typeof props.isRscRequest === "boolean" && (props.matchKind === "interception" || props.matchKind === "raw-request" || props.matchKind === "request" || props.matchKind === "resolved") && (props.mountedSlotsHeader === null || typeof props.mountedSlotsHeader === "string") && isAppPageParams(props.params) && typeof props.resolvedUrl === "string" && props.resolvedUrl.startsWith("/") && typeof props.routePattern === "string" && props.routePattern.startsWith("/") && typeof props.routePathname === "string" && props.routePathname.startsWith("/") && (props.renderMode === "navigation" || props.renderMode === "prefetch-empty" || props.renderMode === "prefetch-dynamic-shell" || props.renderMode === "prefetch-loading-shell");
95
95
  }
96
96
  function isSerializedHeaders(value) {
97
97
  return Array.isArray(value) && value.every((entry) => Array.isArray(entry) && entry.length === 2 && typeof entry[0] === "string" && typeof entry[1] === "string");
@@ -91,7 +91,7 @@ function applyCdnResponseHeaders(headers, input) {
91
91
  if (value === "") continue;
92
92
  headers.set(name, value);
93
93
  }
94
- if (useNextDeployPolicy) headers.set("Cache-Control", BROWSER_REVALIDATE_CACHE_CONTROL);
94
+ if (useNextDeployPolicy) headers.set("Cache-Control", input.browserCacheControl ?? "public, max-age=0, must-revalidate");
95
95
  }
96
96
  /**
97
97
  * Reconcile request-stage policy composed above a reusable response artifact.
@@ -106,19 +106,11 @@ function reconcileCdnResponseHeadersAfterOuterPolicy(headers, outerPolicyHeaders
106
106
  return;
107
107
  }
108
108
  const cacheControl = outerPolicyHeaders.get("cache-control");
109
- if (cacheControl !== null) {
110
- applyCdnResponseHeaders(headers, { cacheControl });
111
- for (const [name, value] of outerPolicyHeaders) {
112
- if (name === "cache-control") continue;
113
- if (isCdnResponsePolicyHeader(name)) headers.set(name, value);
114
- }
115
- return;
116
- }
117
- for (const [name, value] of outerPolicyHeaders) if (isCdnResponsePolicyHeader(name) && isNonCacheableCdnResponsePolicy(name, value)) {
109
+ if (cacheControl !== null) headers.set("Cache-Control", cacheControl);
110
+ for (const [name, value] of outerPolicyHeaders) if (name !== "cache-control" && isCdnResponsePolicyHeader(name) && isNonCacheableCdnResponsePolicy(name, value)) {
118
111
  applyCdnResponseHeaders(headers, { cacheControl: NO_STORE_CACHE_CONTROL });
119
112
  return;
120
113
  }
121
- if (hasExplicitNonCacheableResponsePolicy(outerPolicyHeaders)) applyCdnResponseHeaders(headers, { cacheControl: NO_STORE_CACHE_CONTROL });
122
114
  }
123
115
  /** Apply adapter-owned build identity to an HTML or RSC page response. */
124
116
  function applyCdnResponseIdentityHeaders(response, request) {