vinext 1.3.1 → 1.4.1

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 (271) hide show
  1. package/README.md +25 -22
  2. package/THIRD_PARTY_LICENSES.md +47 -0
  3. package/dist/_virtual/_rolldown/runtime.js +3 -2
  4. package/dist/build/prerender.js +4 -3
  5. package/dist/build/report.d.ts +0 -14
  6. package/dist/build/report.js +1 -51
  7. package/dist/check.js +4 -7
  8. package/dist/cli.js +3 -0
  9. package/dist/client/dev-error-overlay-store.d.ts +1 -0
  10. package/dist/client/dev-error-overlay.d.ts +2 -0
  11. package/dist/client/dev-error-overlay.js +20 -4
  12. package/dist/client/navigation-runtime.d.ts +13 -1
  13. package/dist/client/navigation-runtime.js +1 -1
  14. package/dist/config/config-matchers.js +2 -0
  15. package/dist/config/destination-params.d.ts +2 -1
  16. package/dist/config/destination-params.js +52 -2
  17. package/dist/config/next-config.d.ts +25 -0
  18. package/dist/config/next-config.js +82 -4
  19. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
  20. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
  21. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
  22. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
  23. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
  24. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
  25. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
  26. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
  27. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
  28. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
  29. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
  30. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
  31. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
  32. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
  33. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
  34. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
  35. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
  36. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
  37. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
  38. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
  39. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
  40. package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
  41. package/dist/entries/app-rsc-entry.js +17 -49
  42. package/dist/entries/app-rsc-manifest.js +3 -4
  43. package/dist/entries/app-ssr-entry.js +1 -0
  44. package/dist/entries/pages-server-entry.js +36 -9
  45. package/dist/index.js +112 -90
  46. package/dist/init-cloudflare.d.ts +1 -3
  47. package/dist/init-cloudflare.js +10 -48
  48. package/dist/init-platform.d.ts +2 -0
  49. package/dist/init-platform.js +4 -0
  50. package/dist/plugins/extensionless-dynamic-import.js +6 -2
  51. package/dist/plugins/next-intl-catalog.d.ts +12 -0
  52. package/dist/plugins/next-intl-catalog.js +85 -0
  53. package/dist/plugins/pages-node-externals.d.ts +1 -0
  54. package/dist/plugins/pages-node-externals.js +1 -1
  55. package/dist/plugins/strip-server-exports.js +2 -1
  56. package/dist/plugins/use-cache-callable.d.ts +1 -1
  57. package/dist/plugins/use-cache-callable.js +136 -94
  58. package/dist/routing/app-route-graph.d.ts +6 -0
  59. package/dist/routing/app-route-graph.js +9 -1
  60. package/dist/server/api-handler.js +21 -5
  61. package/dist/server/app-bfcache-identity.js +1 -1
  62. package/dist/server/app-browser-entry.js +86 -66
  63. package/dist/server/app-browser-history-controller.d.ts +5 -4
  64. package/dist/server/app-browser-history-controller.js +93 -15
  65. package/dist/server/app-browser-navigation-controller.d.ts +2 -2
  66. package/dist/server/app-browser-navigation-controller.js +1 -2
  67. package/dist/server/app-browser-rsc-redirect.js +7 -7
  68. package/dist/server/app-browser-server-action-client.d.ts +2 -0
  69. package/dist/server/app-browser-server-action-client.js +5 -4
  70. package/dist/server/app-browser-state.d.ts +2 -4
  71. package/dist/server/app-browser-state.js +9 -4
  72. package/dist/server/app-browser-supplemental-refresh.js +16 -1
  73. package/dist/server/app-browser-visible-commit.d.ts +1 -1
  74. package/dist/server/app-browser-visible-commit.js +4 -14
  75. package/dist/server/app-elements-wire.d.ts +6 -38
  76. package/dist/server/app-elements-wire.js +4 -41
  77. package/dist/server/app-elements.d.ts +2 -2
  78. package/dist/server/app-elements.js +2 -2
  79. package/dist/server/app-history-state.d.ts +2 -2
  80. package/dist/server/app-history-state.js +5 -2
  81. package/dist/server/app-mounted-layouts.d.ts +21 -0
  82. package/dist/server/app-mounted-layouts.js +67 -0
  83. package/dist/server/app-optimistic-routing.d.ts +19 -1
  84. package/dist/server/app-optimistic-routing.js +43 -4
  85. package/dist/server/app-page-boundary-render.js +10 -14
  86. package/dist/server/app-page-boundary.js +2 -2
  87. package/dist/server/app-page-cache-finalizer.d.ts +12 -1
  88. package/dist/server/app-page-cache-finalizer.js +70 -29
  89. package/dist/server/app-page-cache.d.ts +13 -1
  90. package/dist/server/app-page-cache.js +31 -9
  91. package/dist/server/app-page-dispatch.d.ts +5 -11
  92. package/dist/server/app-page-dispatch.js +84 -155
  93. package/dist/server/app-page-element-builder.d.ts +2 -2
  94. package/dist/server/app-page-element-builder.js +13 -12
  95. package/dist/server/app-page-execution.d.ts +17 -52
  96. package/dist/server/app-page-execution.js +102 -95
  97. package/dist/server/app-page-head.d.ts +13 -0
  98. package/dist/server/app-page-head.js +44 -16
  99. package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
  100. package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
  101. package/dist/server/app-page-layout-gate.d.ts +35 -0
  102. package/dist/server/app-page-layout-gate.js +50 -0
  103. package/dist/server/app-page-params.d.ts +0 -1
  104. package/dist/server/app-page-params.js +1 -14
  105. package/dist/server/app-page-probe.d.ts +3 -21
  106. package/dist/server/app-page-probe.js +4 -37
  107. package/dist/server/app-page-render.d.ts +2 -13
  108. package/dist/server/app-page-render.js +103 -234
  109. package/dist/server/app-page-request.d.ts +1 -3
  110. package/dist/server/app-page-request.js +1 -1
  111. package/dist/server/app-page-response.js +3 -3
  112. package/dist/server/app-page-route-wiring.d.ts +13 -6
  113. package/dist/server/app-page-route-wiring.js +86 -63
  114. package/dist/server/app-page-rsc-render-status.d.ts +27 -1
  115. package/dist/server/app-page-rsc-render-status.js +121 -13
  116. package/dist/server/app-page-stream.d.ts +12 -8
  117. package/dist/server/app-page-stream.js +4 -3
  118. package/dist/server/app-pages-bridge.d.ts +4 -0
  119. package/dist/server/app-pages-bridge.js +7 -3
  120. package/dist/server/app-render-dependency.d.ts +11 -4
  121. package/dist/server/app-render-dependency.js +86 -38
  122. package/dist/server/app-request-stage-dispatch.js +1 -1
  123. package/dist/server/app-request-stage-independent-entry.js +1 -1
  124. package/dist/server/app-route-handler-cache.js +2 -2
  125. package/dist/server/app-route-handler-dispatch.js +14 -9
  126. package/dist/server/app-route-handler-execution.js +11 -5
  127. package/dist/server/app-route-handler-policy.d.ts +1 -1
  128. package/dist/server/app-route-handler-policy.js +3 -3
  129. package/dist/server/app-route-handler-response.js +1 -1
  130. package/dist/server/app-route-handler-runtime.d.ts +1 -1
  131. package/dist/server/app-route-handler-runtime.js +28 -11
  132. package/dist/server/app-router-entry.js +1 -1
  133. package/dist/server/app-rsc-cache-busting.d.ts +12 -12
  134. package/dist/server/app-rsc-cache-busting.js +31 -72
  135. package/dist/server/app-rsc-error-handler.d.ts +2 -1
  136. package/dist/server/app-rsc-error-handler.js +10 -2
  137. package/dist/server/app-rsc-errors.d.ts +8 -0
  138. package/dist/server/app-rsc-errors.js +11 -1
  139. package/dist/server/app-rsc-handler.d.ts +5 -5
  140. package/dist/server/app-rsc-handler.js +80 -83
  141. package/dist/server/app-rsc-request-normalization.d.ts +10 -16
  142. package/dist/server/app-rsc-request-normalization.js +12 -18
  143. package/dist/server/app-rsc-response-finalizer.js +2 -2
  144. package/dist/server/app-rsc-response-stage.js +9 -15
  145. package/dist/server/app-server-action-execution.d.ts +3 -1
  146. package/dist/server/app-server-action-execution.js +15 -8
  147. package/dist/server/app-ssr-entry.d.ts +8 -0
  148. package/dist/server/app-ssr-entry.js +22 -16
  149. package/dist/server/app-ssr-stream.js +1 -1
  150. package/dist/server/app-visited-response-cache.d.ts +36 -1
  151. package/dist/server/app-visited-response-cache.js +46 -5
  152. package/dist/server/app-worker-stages.d.ts +37 -6
  153. package/dist/server/app-worker-stages.js +81 -9
  154. package/dist/server/artifact-compatibility.d.ts +0 -1
  155. package/dist/server/artifact-compatibility.js +1 -10
  156. package/dist/server/bfcache-identity.d.ts +7 -0
  157. package/dist/server/bfcache-identity.js +10 -1
  158. package/dist/server/cache-proof.d.ts +1 -115
  159. package/dist/server/cache-proof.js +1 -544
  160. package/dist/server/cacheability-manifest.js +1 -2
  161. package/dist/server/cacheability-request.js +13 -8
  162. package/dist/server/dev-origin-check.d.ts +2 -1
  163. package/dist/server/dev-origin-check.js +2 -1
  164. package/dist/server/dev-server.js +6 -4
  165. package/dist/server/headers.d.ts +6 -3
  166. package/dist/server/headers.js +9 -5
  167. package/dist/server/image-optimization.d.ts +5 -0
  168. package/dist/server/image-optimization.js +6 -1
  169. package/dist/server/isr-cache.d.ts +8 -2
  170. package/dist/server/isr-cache.js +30 -2
  171. package/dist/server/metadata-route-response.js +32 -15
  172. package/dist/server/middleware-matcher.js +19 -6
  173. package/dist/server/middleware-runtime.js +6 -2
  174. package/dist/server/multi-stage.d.ts +57 -12
  175. package/dist/server/multi-stage.js +13 -1
  176. package/dist/server/navigation-planner.js +1 -1
  177. package/dist/server/pages-api-route.js +28 -19
  178. package/dist/server/pages-media-type.d.ts +21 -1
  179. package/dist/server/pages-media-type.js +69 -5
  180. package/dist/server/pages-node-compat.d.ts +1 -1
  181. package/dist/server/pages-node-compat.js +54 -27
  182. package/dist/server/pages-page-data.js +2 -1
  183. package/dist/server/pages-page-handler.js +28 -26
  184. package/dist/server/pages-page-response.d.ts +9 -0
  185. package/dist/server/pages-page-response.js +18 -4
  186. package/dist/server/pages-request-pipeline.d.ts +8 -0
  187. package/dist/server/pages-request-pipeline.js +2 -2
  188. package/dist/server/pages-request-stage-entry.js +36 -14
  189. package/dist/server/pages-response-stage-entry.js +9 -3
  190. package/dist/server/pages-router-entry.js +3 -2
  191. package/dist/server/prod-server.d.ts +2 -2
  192. package/dist/server/prod-server.js +47 -9
  193. package/dist/server/request-error-log.d.ts +9 -0
  194. package/dist/server/request-error-log.js +13 -0
  195. package/dist/server/request-pipeline.d.ts +15 -4
  196. package/dist/server/request-pipeline.js +43 -15
  197. package/dist/server/rsc-completion-metadata.js +3 -0
  198. package/dist/server/shared-cache-identity.d.ts +23 -0
  199. package/dist/server/shared-cache-identity.js +36 -0
  200. package/dist/server/static-file-cache.d.ts +9 -0
  201. package/dist/server/static-file-cache.js +13 -2
  202. package/dist/server/worker-stages.d.ts +16 -3
  203. package/dist/server/worker-stages.js +23 -4
  204. package/dist/shims/cache-handler.js +2 -2
  205. package/dist/shims/cache-request-state.d.ts +23 -26
  206. package/dist/shims/cache-request-state.js +22 -57
  207. package/dist/shims/cache-runtime.d.ts +3 -1
  208. package/dist/shims/cache-runtime.js +94 -48
  209. package/dist/shims/cache.d.ts +16 -10
  210. package/dist/shims/cache.js +47 -36
  211. package/dist/shims/cacheability-classification.d.ts +2 -0
  212. package/dist/shims/cdn-cache.d.ts +22 -5
  213. package/dist/shims/client-hook-error.d.ts +2 -0
  214. package/dist/shims/client-hook-error.js +16 -1
  215. package/dist/shims/client-page-root.js +2 -2
  216. package/dist/shims/dynamic.js +9 -6
  217. package/dist/shims/error-boundary.js +2 -2
  218. package/dist/shims/fetch-cache-state.d.ts +5 -1
  219. package/dist/shims/fetch-cache-state.js +1 -3
  220. package/dist/shims/fetch-cache.d.ts +2 -1
  221. package/dist/shims/fetch-cache.js +39 -25
  222. package/dist/shims/form.js +2 -2
  223. package/dist/shims/headers.d.ts +10 -24
  224. package/dist/shims/headers.js +22 -70
  225. package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
  226. package/dist/shims/internal/navigation-untracked.js +1 -1
  227. package/dist/shims/link.js +8 -11
  228. package/dist/shims/metadata.d.ts +23 -21
  229. package/dist/shims/metadata.js +62 -24
  230. package/dist/shims/navigation-server.js +1 -1
  231. package/dist/shims/navigation.d.ts +74 -7
  232. package/dist/shims/navigation.js +184 -31
  233. package/dist/shims/navigation.react-server.js +2 -2
  234. package/dist/shims/request-state-types.d.ts +3 -2
  235. package/dist/shims/slot.d.ts +16 -0
  236. package/dist/shims/slot.js +44 -9
  237. package/dist/shims/unified-request-context.d.ts +7 -1
  238. package/dist/shims/unified-request-context.js +3 -3
  239. package/dist/utils/cache-control-metadata.d.ts +5 -0
  240. package/dist/utils/cache-control-metadata.js +9 -1
  241. package/dist/utils/cache-life-profiles.d.ts +33 -0
  242. package/dist/utils/cache-life-profiles.js +111 -0
  243. package/dist/utils/middleware-request-headers.d.ts +14 -3
  244. package/dist/utils/middleware-request-headers.js +54 -7
  245. package/dist/utils/project.d.ts +2 -2
  246. package/dist/utils/project.js +3 -16
  247. package/dist/utils/regex.d.ts +5 -0
  248. package/dist/utils/regex.js +11 -1
  249. package/dist/utils/text-stream.d.ts +10 -5
  250. package/dist/utils/text-stream.js +6 -6
  251. package/package.json +2 -1
  252. package/dist/build/layout-classification-types.d.ts +0 -60
  253. package/dist/build/layout-classification-types.js +0 -1
  254. package/dist/build/layout-classification.d.ts +0 -62
  255. package/dist/build/layout-classification.js +0 -98
  256. package/dist/build/route-classification-injector.d.ts +0 -33
  257. package/dist/build/route-classification-injector.js +0 -59
  258. package/dist/build/route-classification-manifest.d.ts +0 -54
  259. package/dist/build/route-classification-manifest.js +0 -143
  260. package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
  261. package/dist/server/app-browser-client-reuse-manifest.js +0 -101
  262. package/dist/server/app-layout-param-observation.d.ts +0 -42
  263. package/dist/server/app-layout-param-observation.js +0 -168
  264. package/dist/server/client-reuse-manifest.d.ts +0 -103
  265. package/dist/server/client-reuse-manifest.js +0 -209
  266. package/dist/server/skip-cache-proof.d.ts +0 -60
  267. package/dist/server/skip-cache-proof.js +0 -168
  268. package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
  269. package/dist/server/static-layout-client-reuse-proof.js +0 -33
  270. package/dist/utils/sorted-array.d.ts +0 -8
  271. package/dist/utils/sorted-array.js +0 -20
@@ -89,9 +89,11 @@ function createElementWithProps(Component, props) {
89
89
  }
90
90
  /**
91
91
  * Lightweight error boundary that renders the loading component with the error
92
- * when a dynamic() loader rejects. Without this, loader failures would propagate
93
- * uncaught through React's rendering — this preserves the Next.js behavior where
94
- * the `loading` component can display errors.
92
+ * when a dynamic() loader rejects, as the Pages Router's react-loadable does by
93
+ * passing `error` to `loading`. App Router trees never get it: Next.js's App
94
+ * Router next/dynamic is React.lazy inside Suspense with no boundary of its own,
95
+ * so loader and render errors reach the nearest error.tsx.
96
+ * https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/lazy-dynamic/loadable.tsx
95
97
  *
96
98
  * Lazily created because React.Component is not available in the RSC environment
97
99
  * (server components use a slimmed-down React that doesn't include class components).
@@ -202,6 +204,7 @@ function dynamic(dynamicInput, options) {
202
204
  }
203
205
  const InitialLazyComponent = createLazyComponent(loader);
204
206
  const ClientSSRFalse = (props) => {
207
+ const isAppRouterTree = useIsAppRouterTree();
205
208
  const [mounted, setMounted] = React.useState(false);
206
209
  const { LazyComponent, retry, retryKey } = useRetryableLazyComponent(loader, InitialLazyComponent);
207
210
  React.useEffect(() => setMounted(true), []);
@@ -209,7 +212,7 @@ function dynamic(dynamicInput, options) {
209
212
  const fallback = LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps({ retry })) : null;
210
213
  const lazyElement = createElementWithProps(LazyComponent, props);
211
214
  let content = lazyElement;
212
- if (LoadingComponent) {
215
+ if (LoadingComponent && !isAppRouterTree) {
213
216
  const ErrorBoundary = getDynamicErrorBoundary();
214
217
  if (ErrorBoundary) content = React.createElement(ErrorBoundary, {
215
218
  fallback: LoadingComponent,
@@ -237,7 +240,7 @@ function dynamic(dynamicInput, options) {
237
240
  const fallback = LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps()) : null;
238
241
  const lazyElement = createElementWithProps(LazyServer, props);
239
242
  let content = lazyElement;
240
- if (LoadingComponent) {
243
+ if (LoadingComponent && !isAppRouterTree) {
241
244
  const ErrorBoundary = getDynamicErrorBoundary();
242
245
  if (ErrorBoundary) content = React.createElement(ErrorBoundary, {
243
246
  fallback: LoadingComponent,
@@ -257,7 +260,7 @@ function dynamic(dynamicInput, options) {
257
260
  const fallback = LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps({ retry })) : null;
258
261
  const lazyElement = createElementWithProps(LazyComponent, props);
259
262
  let content = lazyElement;
260
- if (LoadingComponent) {
263
+ if (LoadingComponent && !isAppRouterTree) {
261
264
  const ErrorBoundary = getDynamicErrorBoundary();
262
265
  if (ErrorBoundary) content = React.createElement(ErrorBoundary, {
263
266
  fallback: LoadingComponent,
@@ -1,11 +1,11 @@
1
1
  "use client";
2
2
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
3
+ import { handleAppNavigationFailure } from "../client/app-nav-failure-handler.js";
4
+ import { VINEXT_DEV_ERROR_RECOVERY_EVENT } from "../utils/dev-error-recovery-event.js";
3
5
  import { decodeRedirectError, forbidden, isRedirectError, notFound, unauthorized } from "./navigation-errors.js";
4
6
  import "./navigation-server.js";
5
7
  import { isRedirectToCurrentUrl, useErrorBoundaryPathname, useErrorBoundaryRouter } from "./error-boundary-navigation.js";
6
8
  import DefaultGlobalError from "./default-global-error.js";
7
- import { handleAppNavigationFailure } from "../client/app-nav-failure-handler.js";
8
- import { VINEXT_DEV_ERROR_RECOVERY_EVENT } from "../utils/dev-error-recovery-event.js";
9
9
  import { consumeCaughtNotFoundBoundary, useCaughtNotFoundBoundary } from "./caught-not-found-boundaries.js";
10
10
  import React from "react";
11
11
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -11,12 +11,16 @@ export type FetchDedupeEntry = {
11
11
  response: Response | null;
12
12
  };
13
13
  export type FetchCacheState = {
14
- cacheableFetchUrls: Set<string>;
15
14
  currentRequestTags: string[];
16
15
  currentFetchSoftTags: string[];
17
16
  currentFetchCacheMode: FetchCacheMode | null;
18
17
  currentFetchRevalidate: number | null;
19
18
  currentForceDynamicFetchDefault: boolean;
19
+ /**
20
+ * Pages Router preview/draft render. App Router draft state is read from the
21
+ * headers context instead; Pages renders don't have one.
22
+ */
23
+ isDraftMode: boolean;
20
24
  dynamicFetchUrls: Set<string>;
21
25
  refreshStaleFetchesInForeground: boolean;
22
26
  isFetchDedupeActive: boolean;
@@ -11,12 +11,12 @@ const _FALLBACK_KEY = Symbol.for("vinext.fetchCache.fallback");
11
11
  const fetchCacheAls = getOrCreateAls("vinext.fetchCache.als");
12
12
  function createFetchCacheState() {
13
13
  return {
14
- cacheableFetchUrls: /* @__PURE__ */ new Set(),
15
14
  currentRequestTags: [],
16
15
  currentFetchSoftTags: [],
17
16
  currentFetchCacheMode: null,
18
17
  currentFetchRevalidate: null,
19
18
  currentForceDynamicFetchDefault: false,
19
+ isDraftMode: false,
20
20
  dynamicFetchUrls: /* @__PURE__ */ new Set(),
21
21
  refreshStaleFetchesInForeground: false,
22
22
  isFetchDedupeActive: false,
@@ -77,13 +77,11 @@ function getCurrentFetchSoftTags() {
77
77
  */
78
78
  function runWithDetachedFetchObservations(fn) {
79
79
  if (isInsideUnifiedScope()) return runWithUnifiedStateMutation((uCtx) => {
80
- uCtx.cacheableFetchUrls = /* @__PURE__ */ new Set();
81
80
  uCtx.currentRequestTags = [];
82
81
  uCtx.dynamicFetchUrls = /* @__PURE__ */ new Set();
83
82
  }, fn);
84
83
  return fetchCacheAls.run({
85
84
  ...getFetchCacheState(),
86
- cacheableFetchUrls: /* @__PURE__ */ new Set(),
87
85
  currentRequestTags: [],
88
86
  dynamicFetchUrls: /* @__PURE__ */ new Set()
89
87
  }, fn);
@@ -11,7 +11,6 @@ declare global {
11
11
  }
12
12
  /** @internal Reset dedup state — exposed for test isolation only. */
13
13
  export declare function _resetPendingRefetches(): void;
14
- export declare function peekCacheableFetchObservations(): string[];
15
14
  export declare function peekDynamicFetchObservations(): string[];
16
15
  export declare function consumeDynamicFetchObservations(): string[];
17
16
  /**
@@ -31,6 +30,8 @@ export declare function setCurrentFetchSoftTags(tags: string[]): void;
31
30
  export declare function setCurrentFetchCacheMode(mode: FetchCacheMode | null): void;
32
31
  export declare function setCurrentFetchRevalidate(revalidate: number | null): void;
33
32
  export declare function setCurrentForceDynamicFetchDefault(enabled: boolean): void;
33
+ /** Mark the current Pages Router render as a preview/draft render. */
34
+ export declare function setCurrentFetchDraftMode(enabled: boolean): void;
34
35
  export declare function setRefreshStaleFetchesInForeground(enabled: boolean): void;
35
36
  /**
36
37
  * Install the patched fetch and reset per-request tag state.
@@ -6,8 +6,8 @@ import { sha256Hex } from "../utils/hash.js";
6
6
  import { traceAppFetch } from "../server/app-fetch-tracing.js";
7
7
  import { addCollectedRequestTags, fallbackFetchCacheState, fetchCacheAls, getCurrentFetchSoftTags, getFetchCacheState, resetFallbackFetchCacheState, runWithDetachedFetchObservations } from "./fetch-cache-state.js";
8
8
  import { isInsideAnyCacheScope, markDynamicUsage } from "./internal/headers-state.js";
9
- import { getHeadersContext } from "./headers.js";
10
- import { _hasPendingRevalidatedTag, _setRequestScopedCacheLife } from "./cache-request-state.js";
9
+ import { getHeadersContext, isDraftModeEnabled } from "./headers.js";
10
+ import { _hasPendingRevalidatedTag, _isOnDemandRevalidate, _setRequestScopedCacheLife } from "./cache-request-state.js";
11
11
  import { Buffer } from "node:buffer";
12
12
  //#region src/shims/fetch-cache.ts
13
13
  /**
@@ -463,9 +463,6 @@ function markUncachedFetchForPageOutput(input) {
463
463
  if (getHeadersContext()?.forceStatic !== true) getFetchCacheState().currentFetchRevalidate = 0;
464
464
  markDynamicUsage();
465
465
  }
466
- function recordCacheableFetchObservation(input) {
467
- getFetchCacheState().cacheableFetchUrls.add(getFetchObservationUrl(input));
468
- }
469
466
  function recordFiniteFetchRevalidate(revalidateSeconds) {
470
467
  if (Number.isFinite(revalidateSeconds) && revalidateSeconds > 0) _setRequestScopedCacheLife({ revalidate: revalidateSeconds });
471
468
  }
@@ -503,7 +500,8 @@ async function writeFetchCacheResponse(handler, cacheKey, response, tags, revali
503
500
  await handler.set(cacheKey, cacheValue, {
504
501
  fetchCache: true,
505
502
  tags,
506
- revalidate: revalidateSeconds
503
+ revalidate: revalidateSeconds,
504
+ ...options?.staleEntry ? { staleEntry: options.staleEntry } : {}
507
505
  });
508
506
  }
509
507
  async function lowerFetchCacheRevalidateIfNeeded(handler, cacheKey, cachedValue, tags, revalidateSeconds) {
@@ -520,9 +518,6 @@ async function lowerFetchCacheRevalidateIfNeeded(handler, cacheKey, cachedValue,
520
518
  revalidate: revalidateSeconds
521
519
  });
522
520
  }
523
- function peekCacheableFetchObservations() {
524
- return [...getFetchCacheState().cacheableFetchUrls].sort();
525
- }
526
521
  function peekDynamicFetchObservations() {
527
522
  return [...getFetchCacheState().dynamicFetchUrls].sort();
528
523
  }
@@ -559,6 +554,10 @@ function setCurrentFetchRevalidate(revalidate) {
559
554
  function setCurrentForceDynamicFetchDefault(enabled) {
560
555
  getFetchCacheState().currentForceDynamicFetchDefault = enabled;
561
556
  }
557
+ /** Mark the current Pages Router render as a preview/draft render. */
558
+ function setCurrentFetchDraftMode(enabled) {
559
+ getFetchCacheState().isDraftMode = enabled;
560
+ }
562
561
  function setRefreshStaleFetchesInForeground(enabled) {
563
562
  getFetchCacheState().refreshStaleFetchesInForeground = enabled;
564
563
  }
@@ -705,8 +704,12 @@ function dedupeFetch(input, init) {
705
704
  */
706
705
  function createPatchedFetch() {
707
706
  const patchedFetch = async function patchedFetch(input, init, span) {
708
- const nextOpts = init?.next;
709
707
  const state = getFetchCacheState();
708
+ if (state.isDraftMode || isDraftModeEnabled()) {
709
+ recordDynamicFetchObservation(input);
710
+ return dedupeFetch(input, init);
711
+ }
712
+ const nextOpts = init?.next;
710
713
  const fetchIdx = isInsideUnifiedScope() || fetchCacheAls.getStore() !== void 0 || fallbackFetchCacheState.isFetchDedupeActive ? (state.nextFetchId ?? 1) + 1 : void 0;
711
714
  if (fetchIdx !== void 0) state.nextFetchId = fetchIdx;
712
715
  const recordFetchOutcome = (response, cacheStatus, cacheReason) => {
@@ -753,7 +756,6 @@ function createPatchedFetch() {
753
756
  return recordFetchOutcome(await dedupeFetch(input, cleanInit), "skip", "auto no cache");
754
757
  }
755
758
  const cacheReason = fetchCacheMode === "force-cache" || fetchCacheMode === "default-cache" ? `fetchCache = ${fetchCacheMode}` : `revalidate: ${nextOpts?.revalidate === false || cacheDirective === "force-cache" ? 4294967294 : revalidateSeconds}`;
756
- recordCacheableFetchObservation(input);
757
759
  if (typeof nextOpts?.revalidate === "number" && nextOpts.revalidate > 0) {
758
760
  lowerCurrentFetchRevalidate(nextOpts.revalidate);
759
761
  recordFiniteFetchRevalidate(nextOpts.revalidate);
@@ -785,8 +787,9 @@ function createPatchedFetch() {
785
787
  }
786
788
  const handler = getDataCacheHandler();
787
789
  let mustBypassPendingRevalidation = _hasPendingRevalidatedTag([...tags, ...softTags]);
790
+ let staleEntry;
788
791
  try {
789
- let cached = mustBypassPendingRevalidation ? null : await handler.get(cacheKey, {
792
+ let cached = mustBypassPendingRevalidation || _isOnDemandRevalidate() ? null : await handler.get(cacheKey, {
790
793
  kind: "FETCH",
791
794
  tags,
792
795
  softTags,
@@ -801,20 +804,28 @@ function createPatchedFetch() {
801
804
  cached = null;
802
805
  }
803
806
  if (cached?.value && cached.value.kind === "FETCH" && cached.cacheState !== "stale") {
804
- await lowerFetchCacheRevalidateIfNeeded(handler, cacheKey, cached.value, tags, revalidateSeconds);
807
+ await lowerFetchCacheRevalidateIfNeeded(handler, cacheKey, cached.value, tags, revalidateSeconds).catch((err) => {
808
+ console.error("[vinext] fetch cache write error:", err);
809
+ });
805
810
  const cachedData = cached.value.data;
806
811
  return recordFetchOutcome(buildCachedFetchResponse(cachedData, input), "hit", cacheReason);
807
812
  }
808
813
  if (cached?.value && cached.value.kind === "FETCH" && cached.cacheState === "stale") {
814
+ staleEntry = cached;
809
815
  if (shouldRefreshStaleFetchInForeground()) {
810
816
  const freshResponse = await dedupeFetch(input, fetchInit);
811
- await writeFetchCacheResponse(handler, cacheKey, freshResponse, tags, revalidateSeconds);
817
+ await writeFetchCacheResponse(handler, cacheKey, freshResponse, tags, revalidateSeconds, { staleEntry: cached }).catch((err) => {
818
+ console.error("[vinext] fetch cache write error:", err);
819
+ });
812
820
  return recordFetchOutcome(freshResponse, "miss", cacheReason);
813
821
  }
814
822
  const staleData = cached.value.data;
815
823
  if (!pendingRefetches.has(cacheKey)) {
816
824
  const refetchPromise = originalFetch(input, fetchInit).then(async (freshResp) => {
817
- await writeFetchCacheResponse(handler, cacheKey, freshResp, tags, revalidateSeconds, { cloneForReturn: false });
825
+ await writeFetchCacheResponse(handler, cacheKey, freshResp, tags, revalidateSeconds, {
826
+ cloneForReturn: false,
827
+ staleEntry: cached
828
+ });
818
829
  }).catch((err) => {
819
830
  const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
820
831
  console.error(`[vinext] fetch cache background revalidation failed for ${url} (key=${cacheKey.slice(0, 12)}...):`, err);
@@ -835,13 +846,17 @@ function createPatchedFetch() {
835
846
  }
836
847
  const response = await (mustBypassPendingRevalidation ? originalFetch(input, fetchInit) : dedupeFetch(input, fetchInit));
837
848
  const cacheValue = await buildFetchCacheValue(response, tags, revalidateSeconds);
838
- if (cacheValue) handler.set(cacheKey, cacheValue, {
839
- fetchCache: true,
840
- tags,
841
- revalidate: revalidateSeconds
842
- }).catch((err) => {
843
- console.error("[vinext] fetch cache write error:", err);
844
- });
849
+ if (cacheValue) {
850
+ const write = handler.set(cacheKey, cacheValue, {
851
+ fetchCache: true,
852
+ tags,
853
+ revalidate: revalidateSeconds,
854
+ ...staleEntry ? { staleEntry } : {}
855
+ }).catch((err) => {
856
+ console.error("[vinext] fetch cache write error:", err);
857
+ });
858
+ getRequestExecutionContext()?.waitUntil(write);
859
+ }
845
860
  return recordFetchOutcome(response, "miss", cacheReason);
846
861
  };
847
862
  return ((input, init) => {
@@ -894,7 +909,6 @@ function withFetchCache() {
894
909
  async function runWithFetchCache(fn) {
895
910
  _ensurePatchInstalled();
896
911
  if (isInsideUnifiedScope()) return await runWithUnifiedStateMutation((uCtx) => {
897
- uCtx.cacheableFetchUrls = /* @__PURE__ */ new Set();
898
912
  uCtx.currentRequestTags = [];
899
913
  uCtx.currentFetchSoftTags = [];
900
914
  uCtx.dynamicFetchUrls = /* @__PURE__ */ new Set();
@@ -904,12 +918,12 @@ async function runWithFetchCache(fn) {
904
918
  uCtx.nextFetchId = 1;
905
919
  }, fn);
906
920
  return fetchCacheAls.run({
907
- cacheableFetchUrls: /* @__PURE__ */ new Set(),
908
921
  currentRequestTags: [],
909
922
  currentFetchSoftTags: [],
910
923
  currentFetchCacheMode: null,
911
924
  currentFetchRevalidate: null,
912
925
  currentForceDynamicFetchDefault: false,
926
+ isDraftMode: false,
913
927
  dynamicFetchUrls: /* @__PURE__ */ new Set(),
914
928
  refreshStaleFetchesInForeground: false,
915
929
  isFetchDedupeActive: true,
@@ -950,4 +964,4 @@ function getOriginalFetch() {
950
964
  return originalFetch;
951
965
  }
952
966
  //#endregion
953
- export { _resetPendingRefetches, addCollectedRequestTags, consumeDynamicFetchObservations, ensureFetchPatch, getCollectedFetchTags, getCurrentFetchSoftTags, getOriginalFetch, peekCacheableFetchObservations, peekDynamicFetchObservations, runWithDetachedFetchObservations, runWithFetchCache, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground, withFetchCache };
967
+ export { _resetPendingRefetches, addCollectedRequestTags, consumeDynamicFetchObservations, ensureFetchPatch, getCollectedFetchTags, getCurrentFetchSoftTags, getOriginalFetch, peekDynamicFetchObservations, runWithDetachedFetchObservations, runWithFetchCache, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchDraftMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground, withFetchCache };
@@ -5,10 +5,10 @@ import "../server/headers.js";
5
5
  import { assertSafeNavigationUrl } from "./url-safety.js";
6
6
  import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "../server/app-rsc-render-mode.js";
7
7
  import { withBasePath } from "./url-utils.js";
8
- import { AppElementsWire } from "../server/app-elements-wire.js";
9
- import "../server/app-elements.js";
10
8
  import { createRscRequestHeaders, createRscRequestUrl } from "../server/app-rsc-cache-busting.js";
11
9
  import { hasAppNavigationRuntime, loadNavigationRuntimeRouteManifest } from "../client/navigation-runtime.js";
10
+ import { AppElementsWire } from "../server/app-elements-wire.js";
11
+ import "../server/app-elements.js";
12
12
  import { getMountedSlotsHeader, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, navigateClientSide, prefetchRscResponse } from "./navigation.js";
13
13
  import { useMergedRef } from "./use-merged-ref.js";
14
14
  import { forwardRef, useActionState, useCallback, useEffect, useRef } from "react";
@@ -1,5 +1,4 @@
1
1
  import { RenderRequestApiKind } from "../server/cache-proof.js";
2
- import { CacheLifeConfig } from "./cache-request-state.js";
3
2
  import { ConnectionProbeResult, HeadersAccessPhase, RenderDynamicLatch, VinextHeadersShimState, createRenderDynamicLatch, getHeadersAccessPhase, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, throwIfInsideCacheScope, throwIfStaticGenerationAccessError } from "./internal/headers-state.js";
4
3
  import { ReadonlyRequestCookies } from "@vinext/types/next/upstream/dist/server/web/spec-extension/adapters/request-cookies";
5
4
  import { ResponseCookie } from "@vinext/types/next/upstream/dist/compiled/@edge-runtime/cookies/index";
@@ -19,27 +18,11 @@ type HeadersContextFromRequestOptions = {
19
18
  draftModeSecret?: string;
20
19
  };
21
20
  /**
22
- * Measure dynamic usage in a child async scope without clearing the parent.
23
- * Concurrent work that already belongs to the request (such as deferred
24
- * metadata) keeps writing to the parent state and therefore remains visible
25
- * to the final cache policy.
26
- */
27
- export declare function runWithIsolatedDynamicUsage<T>(fn: () => T | Promise<T>): Promise<{
28
- result: T;
29
- dynamicDetected: boolean;
30
- }>;
31
- /**
32
- * Run a pre-render probe without letting its dynamic API usage classify the
33
- * request. Next.js has no probe: only the render decides whether a page is
34
- * dynamic, and the render runs the probed layouts and page again. Returns the
35
- * probe's own usage and cacheLife for a caller whose probe response replaces
36
- * the render.
37
- */
38
- export declare function runWithDetachedDynamicUsage<T>(fn: () => T | Promise<T>): Promise<{
39
- result: T;
40
- dynamicDetected: boolean;
41
- cacheLife: CacheLifeConfig | null;
42
- }>;
21
+ * Run a layout probe without letting its dynamic API usage, fetch tags or
22
+ * cacheLife reach the request. Next.js has no probe: only the render decides
23
+ * whether a page is dynamic and how long it is cached.
24
+ */
25
+ export declare function runWithDetachedDynamicUsage<T>(fn: () => T | Promise<T>): Promise<T>;
43
26
  export declare function runWithConnectionProbe<T>(fn: () => T | Promise<T>): Promise<ConnectionProbeResult<T>>;
44
27
  export declare function suspendConnectionProbe(): Promise<never> | null;
45
28
  export declare function peekRenderRequestApiUsage(): RenderRequestApiKind[];
@@ -185,7 +168,8 @@ export declare function getActiveDraftModeState(): boolean | null;
185
168
  /**
186
169
  * Read the active request's draft-mode state without recording request API usage.
187
170
  * Internal cache implementations use this to bypass persistent reads and writes,
188
- * matching Next.js's request-level `workStore.isDraftMode` guard.
171
+ * matching Next.js's request-level `workStore.isDraftMode` guard. Once the
172
+ * headers context is cleared, the request keeps the state it had then.
189
173
  */
190
174
  export declare function isDraftModeEnabled(): boolean;
191
175
  type DraftModeResult = {
@@ -214,7 +198,9 @@ declare class RequestCookies {
214
198
  private _cookies;
215
199
  private _responseCookies;
216
200
  constructor(cookies: Map<string, string>, mutable?: boolean);
217
- get(name: string): ResponseCookie | undefined;
201
+ get(nameOrOptions: string | {
202
+ name: string;
203
+ }): ResponseCookie | undefined;
218
204
  getAll(nameOrOptions?: string | {
219
205
  name: string;
220
206
  }): ResponseCookie[];
@@ -1,4 +1,4 @@
1
- import { ensureRenderDynamicLatch, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
1
+ import { ensureRenderDynamicLatch, getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
2
2
  import { MIDDLEWARE_SET_COOKIE_HEADER } from "../utils/protocol-headers.js";
3
3
  import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
4
4
  import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
@@ -84,78 +84,27 @@ function mergeMiddlewareSetCookies(ctx, rawHeader) {
84
84
  return merged;
85
85
  }
86
86
  /**
87
- * Measure dynamic usage in a child async scope without clearing the parent.
88
- * Concurrent work that already belongs to the request (such as deferred
89
- * metadata) keeps writing to the parent state and therefore remains visible
90
- * to the final cache policy.
91
- */
92
- async function runWithIsolatedDynamicUsage(fn) {
93
- const runInChildState = async (childState) => {
94
- return {
95
- result: await fn(),
96
- dynamicDetected: childState.dynamicUsageDetected
97
- };
98
- };
99
- if (isInsideUnifiedScope()) {
100
- let childState = null;
101
- return await runWithUnifiedStateMutation((context) => {
102
- context.dynamicUsageDetected = false;
103
- childState = context;
104
- }, () => {
105
- if (!childState) throw new Error("Dynamic usage scope was not initialized");
106
- return runInChildState(childState);
107
- });
108
- }
109
- const parentState = getHeadersShimState();
110
- const childState = {
111
- ...parentState,
112
- renderDynamicLatch: ensureRenderDynamicLatch(parentState),
113
- dynamicUsageDetected: false
114
- };
115
- return await headersShimAls.run(childState, () => runInChildState(childState));
116
- }
117
- /**
118
- * Run a pre-render probe without letting its dynamic API usage classify the
119
- * request. Next.js has no probe: only the render decides whether a page is
120
- * dynamic, and the render runs the probed layouts and page again. Returns the
121
- * probe's own usage and cacheLife for a caller whose probe response replaces
122
- * the render.
87
+ * Run a layout probe without letting its dynamic API usage, fetch tags or
88
+ * cacheLife reach the request. Next.js has no probe: only the render decides
89
+ * whether a page is dynamic and how long it is cached.
123
90
  */
124
91
  async function runWithDetachedDynamicUsage(fn) {
125
- const runInChildState = async (childState, cacheLifeSink) => {
126
- return {
127
- result: await fn(),
128
- cacheLife: cacheLifeSink?.cacheLife ?? null,
129
- dynamicDetected: childState.dynamicUsageDetected || childState.renderDynamicLatch.dynamic
130
- };
131
- };
132
- if (isInsideUnifiedScope()) {
133
- let childState = null;
134
- const cacheLifeSink = { cacheLife: null };
135
- return await runWithUnifiedStateMutation((context) => {
136
- context.cacheLifeSink = cacheLifeSink;
137
- context.dynamicUsageDetected = false;
138
- context.renderDynamicLatch = createRenderDynamicLatch();
139
- context.renderRequestApiUsage = /* @__PURE__ */ new Set();
140
- context.requestCache = /* @__PURE__ */ new WeakMap();
141
- context.cacheableFetchUrls = /* @__PURE__ */ new Set();
142
- context.currentRequestTags = [];
143
- context.dynamicFetchUrls = /* @__PURE__ */ new Set();
144
- context.requestScopedCacheLife = null;
145
- context.unstableCacheObservations = /* @__PURE__ */ new Map();
146
- childState = context;
147
- }, () => {
148
- if (!childState) throw new Error("Dynamic usage scope was not initialized");
149
- return runInChildState(childState, cacheLifeSink);
150
- });
151
- }
92
+ if (isInsideUnifiedScope()) return await runWithUnifiedStateMutation((context) => {
93
+ context.dynamicUsageDetected = false;
94
+ context.renderDynamicLatch = createRenderDynamicLatch();
95
+ context.renderRequestApiUsage = /* @__PURE__ */ new Set();
96
+ context.requestCache = /* @__PURE__ */ new WeakMap();
97
+ context.currentRequestTags = [];
98
+ context.dynamicFetchUrls = /* @__PURE__ */ new Set();
99
+ context.requestScopedCacheLife = null;
100
+ }, fn);
152
101
  const childState = {
153
102
  ...getHeadersShimState(),
154
103
  dynamicUsageDetected: false,
155
104
  renderDynamicLatch: createRenderDynamicLatch(),
156
105
  renderRequestApiUsage: /* @__PURE__ */ new Set()
157
106
  };
158
- return await headersShimAls.run(childState, () => runInChildState(childState, null));
107
+ return await headersShimAls.run(childState, fn);
159
108
  }
160
109
  async function runWithConnectionProbe(fn) {
161
110
  const parentState = getHeadersShimState();
@@ -343,6 +292,7 @@ function setHeadersContext(ctx) {
343
292
  state.draftModeCookieHeader = null;
344
293
  state.phase = "render";
345
294
  } else {
295
+ if (state.headersContext && isInsideUnifiedScope()) getRequestContext().draftModeAtHeadersClear = getActiveDraftModeState() === true;
346
296
  state.headersContext = null;
347
297
  state.phase = "render";
348
298
  }
@@ -513,7 +463,7 @@ function _wrapMutableCookies(cookies) {
513
463
  }
514
464
  function _sealCookies(cookies) {
515
465
  return new Proxy(cookies, { get(target, prop) {
516
- if (prop === "set" || prop === "delete") throw new ReadonlyRequestCookiesError();
466
+ if (prop === "set" || prop === "delete" || prop === "clear") return ReadonlyRequestCookiesError.callable;
517
467
  const value = Reflect.get(target, prop, target);
518
468
  return typeof value === "function" ? value.bind(target) : value;
519
469
  } });
@@ -689,10 +639,11 @@ function getActiveDraftModeState() {
689
639
  /**
690
640
  * Read the active request's draft-mode state without recording request API usage.
691
641
  * Internal cache implementations use this to bypass persistent reads and writes,
692
- * matching Next.js's request-level `workStore.isDraftMode` guard.
642
+ * matching Next.js's request-level `workStore.isDraftMode` guard. Once the
643
+ * headers context is cleared, the request keeps the state it had then.
693
644
  */
694
645
  function isDraftModeEnabled() {
695
- return getActiveDraftModeState() ?? false;
646
+ return getActiveDraftModeState() ?? (isInsideUnifiedScope() && getRequestContext().draftModeAtHeadersClear === true);
696
647
  }
697
648
  function createDraftModeScopeError(expression) {
698
649
  return /* @__PURE__ */ new Error(`${expression} can only be called from a Server Component, Route Handler, or Server Action.`);
@@ -761,7 +712,8 @@ var RequestCookies = class {
761
712
  value
762
713
  })])) : null;
763
714
  }
764
- get(name) {
715
+ get(nameOrOptions) {
716
+ const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions.name;
765
717
  if (this._responseCookies) return this._responseCookies.get(name);
766
718
  const value = this._cookies.get(name);
767
719
  if (value === void 0) return void 0;
@@ -877,4 +829,4 @@ function serializeMutableCookie(cookie) {
877
829
  });
878
830
  }
879
831
  //#endregion
880
- export { applyEffectiveRequestCookieHeader, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, createRenderDynamicLatch, draftMode, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, getEffectiveRequestCookieHeader, getHeadersAccessPhase, getHeadersContext, hasDraftModeCookieHeader, hasEffectiveRequestCookieChanges, headers, headersContextFromRequest, isDraftModeEnabled, isDraftModeRequest, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, peekDynamicUsage, peekRenderRequestApiUsage, replaceHeadersContext, restoreDraftModeTransition, runWithConnectionProbe, runWithDetachedDynamicUsage, runWithHeadersContext, runWithIsolatedDynamicUsage, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
832
+ export { applyEffectiveRequestCookieHeader, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, createRenderDynamicLatch, draftMode, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, getEffectiveRequestCookieHeader, getHeadersAccessPhase, getHeadersContext, hasDraftModeCookieHeader, hasEffectiveRequestCookieChanges, headers, headersContextFromRequest, isDraftModeEnabled, isDraftModeRequest, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, peekDynamicUsage, peekRenderRequestApiUsage, replaceHeadersContext, restoreDraftModeTransition, runWithConnectionProbe, runWithDetachedDynamicUsage, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
@@ -1,4 +1,4 @@
1
- import { CacheLifeConfig } from "../cache-request-state.js";
1
+ import { CacheLifeConfig } from "../../utils/cache-life-profiles.js";
2
2
  //#region src/shims/internal/cache-context-accessor.d.ts
3
3
  type CacheContextLike = {
4
4
  tags: string[];
@@ -1,5 +1,5 @@
1
- import { getNavigationContext } from "../navigation-context-state.js";
2
1
  import { getPagesNavigationContext } from "./pages-router-accessor.js";
2
+ import { getNavigationContext } from "../navigation-context-state.js";
3
3
  import { getClientNavigationState, useClientNavigationRenderSnapshot } from "../navigation.js";
4
4
  //#region src/shims/internal/navigation-untracked.ts
5
5
  /**
@@ -149,7 +149,7 @@ function getLinkPrefetchRouterMode() {
149
149
  /**
150
150
  * Prefetch a URL for faster navigation.
151
151
  *
152
- * For App Router (RSC): fetches the .rsc payload in the background and
152
+ * For App Router (RSC): fetches the RSC payload in the background and
153
153
  * stores it in an in-memory cache for instant use during navigation.
154
154
  * For Pages Router: warms the page chunk, prefetches data only for SSG pages,
155
155
  * and falls back to a document prefetch hint when no page loader matches.
@@ -192,7 +192,7 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale, owner
192
192
  ]);
193
193
  if (routeManifestLoaded === false) return;
194
194
  if (navigationEpoch !== linkPrefetchNavigationEpoch) return;
195
- const { getPrefetchInterceptionContext, getPrefetchCache, getPrefetchedUrls, getMountedSlotsHeader, createAppPrefetchRequestHeaders, discardLearningOnlyPrefetchCacheEntry, fetchRouteTreeGatedPrefetch, hasFreshLearningOnlyPrefetchCacheEntry, hasSearchAgnosticPrefetchShellForRoute, hasPrefetchCacheEntryForNavigation, prefetchRscResponse, prepareNavigationPrefetchSnapshot, promotePrefetchCacheEntryForNavigation, DYNAMIC_NAVIGATION_CACHE_TTL, PREFETCH_CACHE_TTL } = navigation;
195
+ const { getPrefetchInterceptionContext, getPrefetchCache, getPrefetchedUrls, getMountedSlotsHeader, createAppPrefetchRequestHeaders, discardLearningOnlyPrefetchCacheEntry, fetchRouteTreeGatedPrefetch, hasFreshLearningOnlyPrefetchCacheEntry, hasSearchAgnosticPrefetchShellForRoute, hasPrefetchCacheEntryForNavigation, prefetchRscResponse, prepareNavigationPrefetchSnapshot, promotePrefetchCacheEntryForNavigation, seedFullPrefetchFromVisitedResponse, hasNavigationFreshVisitedResponse, DYNAMIC_NAVIGATION_CACHE_TTL, PREFETCH_CACHE_TTL } = navigation;
196
196
  const { createRscRequestUrl } = rscCacheBusting;
197
197
  const { NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, VINEXT_MOUNTED_SLOTS_HEADER } = headersModule;
198
198
  const hybridOwner = HAS_PAGES_ROUTER ? hybridRouteOwner.resolveHybridClientRouteOwner(prefetchHref, __basePath) : null;
@@ -314,6 +314,8 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale, owner
314
314
  }
315
315
  return;
316
316
  }
317
+ if (autoPrefetch.dynamicStaleTime === "full-prefetch" && seedFullPrefetchFromVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, additionalRscUrls)) return;
318
+ if (autoPrefetch.dynamicStaleTime !== "full-prefetch" && hasNavigationFreshVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, additionalRscUrls)) return;
317
319
  prefetched.add(cacheKey);
318
320
  const gateViaRouteTree = (__prefetchInlining || requiresRouteTreePrefetch) && mode === "auto" && autoPrefetch.prefetchShellFirst;
319
321
  const gateViaExplicitSearchShell = mode === "full" && hasSearchParams && autoPrefetch.prefetchShellFirst && mountedSlotsHeader === null;
@@ -379,7 +381,7 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale, owner
379
381
  async function promotePrefetchEntriesForNavigation(href) {
380
382
  if (typeof window === "undefined") return;
381
383
  if (!hasLinkAppNavigationRuntime()) return;
382
- const [{ getMountedSlotsHeader, getPrefetchCache, getPrefetchInterceptionContext, promotePrefetchCacheEntryForNavigation }, { parseRscRequestPath, stripRscCacheBustingSearchParam, stripRscSuffix }] = await Promise.all([loadNavigationModule(), loadAppRscCacheBustingModule()]);
384
+ const [{ getMountedSlotsHeader, getPrefetchCache, getPrefetchInterceptionContext, promotePrefetchCacheEntryForNavigation }, { parseRscRequestPath, stripRscCacheBustingSearchParam }] = await Promise.all([loadNavigationModule(), loadAppRscCacheBustingModule()]);
383
385
  let target;
384
386
  const fullHref = toCanonicalBrowserNavigationHref(href, window.location.href, __basePath, __trailingSlash);
385
387
  try {
@@ -403,7 +405,7 @@ async function promotePrefetchEntriesForNavigation(href) {
403
405
  continue;
404
406
  }
405
407
  stripRscCacheBustingSearchParam(cached);
406
- if (stripRscSuffix(cached.pathname) === target.pathname && cached.search === target.search) promotePrefetchCacheEntryForNavigation(cacheKey, entry);
408
+ if (cached.pathname === target.pathname && cached.search === target.search) promotePrefetchCacheEntryForNavigation(cacheKey, entry);
407
409
  }
408
410
  }
409
411
  /**
@@ -625,16 +627,11 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
625
627
  })
626
628
  });
627
629
  const [pending, setPending] = useState(false);
628
- const mountedRef = useRef(true);
629
630
  const pendingPagesIntentPrefetchRef = useRef(null);
630
- const setPendingRef = useRef((next) => {
631
- if (mountedRef.current) setPending(next);
632
- });
631
+ const setPendingRef = useRef(setPending);
633
632
  useEffect(() => {
634
- mountedRef.current = true;
635
633
  const setter = setPendingRef.current;
636
634
  return () => {
637
- mountedRef.current = false;
638
635
  pendingPagesIntentPrefetchRef.current?.();
639
636
  pendingPagesIntentPrefetchRef.current = null;
640
637
  if (setter) clearLinkForCurrentNavigation(setter);
@@ -800,7 +797,7 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
800
797
  setPending(true);
801
798
  React.startTransition(() => {
802
799
  navigateClientSide(navigateHref, replace ? "replace" : "push", scroll, false).finally(() => {
803
- if (mountedRef.current) setPending(false);
800
+ setPending(false);
804
801
  if (setter) clearLinkForCurrentNavigation(setter);
805
802
  });
806
803
  });