vinext 1.0.1 → 1.2.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 (334) hide show
  1. package/README.md +93 -10
  2. package/dist/build/app-page-static-eligibility.d.ts +15 -0
  3. package/dist/build/app-page-static-eligibility.js +82 -0
  4. package/dist/build/client-build-config.d.ts +10 -0
  5. package/dist/build/client-build-config.js +18 -2
  6. package/dist/build/pages-client-assets-module.d.ts +8 -0
  7. package/dist/build/pages-client-assets-module.js +21 -1
  8. package/dist/build/prerender-paths.js +8 -81
  9. package/dist/build/prerender.js +33 -8
  10. package/dist/build/run-prerender.js +1 -1
  11. package/dist/build/server-manifest.d.ts +7 -0
  12. package/dist/build/server-manifest.js +11 -1
  13. package/dist/build/ssr-manifest.d.ts +2 -0
  14. package/dist/build/ssr-manifest.js +6 -2
  15. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  16. package/dist/cache/cache-adapters-virtual.js +3 -3
  17. package/dist/check.js +7 -6
  18. package/dist/cli.js +2 -1
  19. package/dist/client/client-redirect-matcher.d.ts +14 -0
  20. package/dist/client/client-redirect-matcher.js +37 -0
  21. package/dist/client/client-redirects.d.ts +27 -0
  22. package/dist/client/client-redirects.js +28 -0
  23. package/dist/client/client-rewrites.d.ts +2 -1
  24. package/dist/client/client-rewrites.js +1 -1
  25. package/dist/client/navigation-runtime.d.ts +11 -0
  26. package/dist/client/navigation-runtime.js +1 -1
  27. package/dist/config/config-matchers.d.ts +26 -11
  28. package/dist/config/config-matchers.js +81 -82
  29. package/dist/config/destination-params.d.ts +47 -0
  30. package/dist/config/destination-params.js +116 -0
  31. package/dist/config/next-config.d.ts +14 -0
  32. package/dist/config/next-config.js +21 -3
  33. package/dist/entries/app-rsc-entry.d.ts +6 -0
  34. package/dist/entries/app-rsc-entry.js +84 -49
  35. package/dist/entries/pages-client-entry.js +3 -1
  36. package/dist/entries/pages-server-entry.js +13 -37
  37. package/dist/index.d.ts +7 -2
  38. package/dist/index.js +193 -73
  39. package/dist/init-cloudflare.d.ts +9 -0
  40. package/dist/init-cloudflare.js +107 -31
  41. package/dist/init-platform.d.ts +4 -0
  42. package/dist/init-platform.js +27 -2
  43. package/dist/init.d.ts +1 -0
  44. package/dist/init.js +67 -3
  45. package/dist/plugins/ast-scope.d.ts +7 -0
  46. package/dist/plugins/ast-scope.js +59 -3
  47. package/dist/plugins/cache-flight-codec.d.ts +19 -0
  48. package/dist/plugins/cache-flight-codec.js +68 -0
  49. package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
  50. package/dist/plugins/commonjs-esm-facade.js +80 -0
  51. package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
  52. package/dist/plugins/dynamic-preload-metadata.js +9 -8
  53. package/dist/plugins/fonts.d.ts +8 -11
  54. package/dist/plugins/fonts.js +71 -34
  55. package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
  56. package/dist/plugins/ignore-dynamic-requests.js +3 -4
  57. package/dist/plugins/middleware-server-only.d.ts +5 -4
  58. package/dist/plugins/middleware-server-only.js +8 -5
  59. package/dist/plugins/pages-node-externals.js +1 -1
  60. package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
  61. package/dist/plugins/rsc-scan-glob-imports.js +50 -0
  62. package/dist/plugins/strip-server-exports.js +262 -98
  63. package/dist/plugins/transform-result.d.ts +9 -5
  64. package/dist/plugins/transitive-externals.js +1 -1
  65. package/dist/plugins/typeof-window.d.ts +2 -2
  66. package/dist/plugins/use-cache-callable.js +8 -2
  67. package/dist/plugins/worker-server-only-imports.d.ts +20 -0
  68. package/dist/plugins/worker-server-only-imports.js +31 -0
  69. package/dist/plugins/worker-use-server.d.ts +25 -0
  70. package/dist/plugins/worker-use-server.js +129 -0
  71. package/dist/routing/file-matcher.d.ts +1 -0
  72. package/dist/routing/file-matcher.js +1 -1
  73. package/dist/server/api-handler.d.ts +1 -0
  74. package/dist/server/api-handler.js +19 -8
  75. package/dist/server/app-browser-action-result.d.ts +1 -1
  76. package/dist/server/app-browser-action-result.js +9 -2
  77. package/dist/server/app-browser-entry.js +11 -7
  78. package/dist/server/app-browser-history-controller.d.ts +2 -0
  79. package/dist/server/app-browser-history-controller.js +8 -0
  80. package/dist/server/app-browser-interception-context.js +26 -2
  81. package/dist/server/app-browser-navigation-controller.d.ts +7 -1
  82. package/dist/server/app-browser-navigation-controller.js +94 -11
  83. package/dist/server/app-browser-server-action-client.js +1 -1
  84. package/dist/server/app-fallback-renderer.d.ts +2 -0
  85. package/dist/server/app-fallback-renderer.js +1 -0
  86. package/dist/server/app-history-state.d.ts +3 -0
  87. package/dist/server/app-history-state.js +7 -0
  88. package/dist/server/app-middleware.d.ts +11 -0
  89. package/dist/server/app-middleware.js +19 -3
  90. package/dist/server/app-optimistic-routing.js +1 -1
  91. package/dist/server/app-page-boundary-render.d.ts +5 -0
  92. package/dist/server/app-page-boundary-render.js +6 -4
  93. package/dist/server/app-page-cache-finalizer.d.ts +11 -0
  94. package/dist/server/app-page-cache-finalizer.js +41 -7
  95. package/dist/server/app-page-cache-render.d.ts +18 -0
  96. package/dist/server/app-page-cache-render.js +63 -43
  97. package/dist/server/app-page-cache.d.ts +6 -1
  98. package/dist/server/app-page-cache.js +28 -8
  99. package/dist/server/app-page-dispatch.d.ts +12 -2
  100. package/dist/server/app-page-dispatch.js +51 -33
  101. package/dist/server/app-page-element-builder.d.ts +7 -0
  102. package/dist/server/app-page-element-builder.js +27 -42
  103. package/dist/server/app-page-execution.d.ts +15 -12
  104. package/dist/server/app-page-execution.js +30 -40
  105. package/dist/server/app-page-head.d.ts +5 -0
  106. package/dist/server/app-page-head.js +9 -3
  107. package/dist/server/app-page-ppr-runtime.js +1 -1
  108. package/dist/server/app-page-probe.d.ts +0 -109
  109. package/dist/server/app-page-probe.js +3 -136
  110. package/dist/server/app-page-render-identity.d.ts +0 -1
  111. package/dist/server/app-page-render-identity.js +1 -1
  112. package/dist/server/app-page-render-observation.js +3 -3
  113. package/dist/server/app-page-render.d.ts +13 -5
  114. package/dist/server/app-page-render.js +219 -119
  115. package/dist/server/app-page-request.d.ts +0 -1
  116. package/dist/server/app-page-request.js +54 -17
  117. package/dist/server/app-page-response.d.ts +4 -3
  118. package/dist/server/app-page-response.js +4 -3
  119. package/dist/server/app-page-route-wiring.d.ts +17 -5
  120. package/dist/server/app-page-route-wiring.js +57 -35
  121. package/dist/server/app-page-rsc-render-status.d.ts +48 -0
  122. package/dist/server/app-page-rsc-render-status.js +54 -0
  123. package/dist/server/app-page-stream.d.ts +15 -8
  124. package/dist/server/app-page-stream.js +6 -0
  125. package/dist/server/app-pages-bridge.d.ts +1 -1
  126. package/dist/server/app-pages-bridge.js +2 -3
  127. package/dist/server/app-prerender-endpoints.js +9 -6
  128. package/dist/server/app-request-stage-dispatch.js +7 -3
  129. package/dist/server/app-request-stage-independent-entry.js +29 -9
  130. package/dist/server/app-response-header-provenance.d.ts +2 -0
  131. package/dist/server/app-response-header-provenance.js +10 -4
  132. package/dist/server/app-response-stage-entry.js +10 -2
  133. package/dist/server/app-route-handler-cache.d.ts +1 -0
  134. package/dist/server/app-route-handler-cache.js +1 -0
  135. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  136. package/dist/server/app-route-handler-dispatch.js +6 -3
  137. package/dist/server/app-route-handler-execution.d.ts +1 -0
  138. package/dist/server/app-route-handler-execution.js +1 -0
  139. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  140. package/dist/server/app-route-handler-runtime.js +45 -24
  141. package/dist/server/app-router-entry.js +27 -8
  142. package/dist/server/app-rsc-cache-busting.js +1 -1
  143. package/dist/server/app-rsc-errors.js +20 -16
  144. package/dist/server/app-rsc-handler.d.ts +11 -0
  145. package/dist/server/app-rsc-handler.js +291 -125
  146. package/dist/server/app-rsc-request-normalization.d.ts +3 -1
  147. package/dist/server/app-rsc-request-normalization.js +4 -2
  148. package/dist/server/app-rsc-response-stage.d.ts +1 -1
  149. package/dist/server/app-rsc-response-stage.js +10 -6
  150. package/dist/server/app-rsc-route-matching.d.ts +9 -1
  151. package/dist/server/app-rsc-route-matching.js +36 -19
  152. package/dist/server/app-segment-config.d.ts +2 -1
  153. package/dist/server/app-server-action-execution.d.ts +2 -1
  154. package/dist/server/app-server-action-execution.js +62 -23
  155. package/dist/server/app-ssr-entry.d.ts +3 -2
  156. package/dist/server/app-ssr-entry.js +8 -5
  157. package/dist/server/app-ssr-stream.d.ts +6 -1
  158. package/dist/server/app-ssr-stream.js +34 -15
  159. package/dist/server/app-worker-stages.d.ts +7 -2
  160. package/dist/server/app-worker-stages.js +4 -4
  161. package/dist/server/cacheability-request.js +11 -7
  162. package/dist/server/client-build-files.d.ts +16 -0
  163. package/dist/server/client-build-files.js +36 -0
  164. package/dist/server/client-reuse-manifest.js +1 -1
  165. package/dist/server/config-headers.js +2 -0
  166. package/dist/server/dev-server.js +50 -29
  167. package/dist/server/dev-stack-sourcemap.js +18 -23
  168. package/dist/server/document-initial-head.d.ts +0 -11
  169. package/dist/server/document-initial-head.js +1 -1
  170. package/dist/server/forwarded-middleware-context.d.ts +5 -0
  171. package/dist/server/forwarded-middleware-context.js +22 -0
  172. package/dist/server/headers.d.ts +18 -1
  173. package/dist/server/headers.js +19 -2
  174. package/dist/server/http-conditional.d.ts +11 -0
  175. package/dist/server/http-conditional.js +10 -1
  176. package/dist/server/http-error-responses.d.ts +1 -1
  177. package/dist/server/image-optimization.d.ts +54 -0
  178. package/dist/server/image-optimization.js +118 -9
  179. package/dist/server/isr-cache.d.ts +10 -0
  180. package/dist/server/isr-cache.js +43 -8
  181. package/dist/server/metadata-route-response.js +9 -8
  182. package/dist/server/middleware-matcher-pattern.js +8 -4
  183. package/dist/server/middleware-matcher.d.ts +2 -0
  184. package/dist/server/middleware-matcher.js +23 -2
  185. package/dist/server/middleware-response-headers.js +2 -0
  186. package/dist/server/middleware-runtime.d.ts +13 -0
  187. package/dist/server/middleware-runtime.js +33 -20
  188. package/dist/server/middleware.d.ts +1 -1
  189. package/dist/server/middleware.js +3 -1
  190. package/dist/server/multi-stage.d.ts +19 -0
  191. package/dist/server/navigation-planner.js +1 -1
  192. package/dist/server/node-response-signal.d.ts +16 -0
  193. package/dist/server/node-response-signal.js +26 -0
  194. package/dist/server/normalize-path.d.ts +0 -13
  195. package/dist/server/normalize-path.js +1 -34
  196. package/dist/server/open-redirect.d.ts +47 -0
  197. package/dist/server/open-redirect.js +74 -1
  198. package/dist/server/pages-api-route.d.ts +3 -2
  199. package/dist/server/pages-api-route.js +4 -3
  200. package/dist/server/pages-cache-tag.d.ts +12 -0
  201. package/dist/server/pages-cache-tag.js +19 -0
  202. package/dist/server/pages-client-assets.d.ts +2 -0
  203. package/dist/server/pages-data-route.d.ts +10 -0
  204. package/dist/server/pages-data-route.js +19 -2
  205. package/dist/server/pages-document-asset-props.d.ts +5 -1
  206. package/dist/server/pages-document-asset-props.js +13 -5
  207. package/dist/server/pages-document-splice.d.ts +19 -0
  208. package/dist/server/pages-document-splice.js +55 -0
  209. package/dist/server/pages-i18n.d.ts +12 -1
  210. package/dist/server/pages-i18n.js +18 -4
  211. package/dist/server/pages-node-compat.d.ts +16 -5
  212. package/dist/server/pages-node-compat.js +20 -12
  213. package/dist/server/pages-page-data.d.ts +32 -24
  214. package/dist/server/pages-page-data.js +50 -120
  215. package/dist/server/pages-page-handler.d.ts +0 -6
  216. package/dist/server/pages-page-handler.js +209 -130
  217. package/dist/server/pages-page-response.d.ts +12 -6
  218. package/dist/server/pages-page-response.js +41 -34
  219. package/dist/server/pages-request-pipeline.d.ts +10 -2
  220. package/dist/server/pages-request-pipeline.js +37 -18
  221. package/dist/server/pages-request-stage-entry.d.ts +6 -0
  222. package/dist/server/pages-request-stage-entry.js +79 -16
  223. package/dist/server/pages-response-stage-entry.js +4 -0
  224. package/dist/server/pages-revalidate.js +1 -1
  225. package/dist/server/pages-router-entry.js +4 -3
  226. package/dist/server/prerender-manifest.d.ts +3 -3
  227. package/dist/server/prerender-manifest.js +4 -3
  228. package/dist/server/prerender-work-unit-setup.js +4 -0
  229. package/dist/server/prod-server.d.ts +20 -7
  230. package/dist/server/prod-server.js +343 -129
  231. package/dist/server/proper-error.d.ts +4 -0
  232. package/dist/server/proper-error.js +31 -0
  233. package/dist/server/request-pipeline.d.ts +24 -9
  234. package/dist/server/request-pipeline.js +24 -9
  235. package/dist/server/response-compression.d.ts +43 -0
  236. package/dist/server/response-compression.js +111 -0
  237. package/dist/server/revalidation-request.d.ts +1 -0
  238. package/dist/server/revalidation-request.js +1 -1
  239. package/dist/server/rsc-stream-hints.js +31 -2
  240. package/dist/server/seed-cache.d.ts +1 -0
  241. package/dist/server/seed-cache.js +15 -11
  242. package/dist/server/server-reference-loader.d.ts +4 -0
  243. package/dist/server/server-reference-loader.js +29 -0
  244. package/dist/server/socket-error-backstop.d.ts +23 -1
  245. package/dist/server/socket-error-backstop.js +69 -17
  246. package/dist/server/static-file-signal.d.ts +15 -4
  247. package/dist/server/static-file-signal.js +46 -12
  248. package/dist/server/worker-image-optimization.d.ts +34 -0
  249. package/dist/server/worker-image-optimization.js +86 -0
  250. package/dist/server/worker-stages.d.ts +1 -1
  251. package/dist/server/worker-stages.js +2 -2
  252. package/dist/server/worker-utils.d.ts +8 -3
  253. package/dist/server/worker-utils.js +12 -7
  254. package/dist/shims/app-router-scroll.js +4 -1
  255. package/dist/shims/app-router-tree-context.d.ts +5 -0
  256. package/dist/shims/app-router-tree-context.js +27 -0
  257. package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
  258. package/dist/shims/cache-adapter-instantiate.js +118 -0
  259. package/dist/shims/cache-callable-runtime.d.ts +6 -42
  260. package/dist/shims/cache-callable-runtime.js +65 -174
  261. package/dist/shims/cache-flight-arguments.d.ts +22 -0
  262. package/dist/shims/cache-flight-arguments.js +56 -0
  263. package/dist/shims/cache-handler.js +1 -9
  264. package/dist/shims/cache-request-state.d.ts +15 -0
  265. package/dist/shims/cache-request-state.js +31 -8
  266. package/dist/shims/cache-runtime.d.ts +12 -20
  267. package/dist/shims/cache-runtime.js +166 -225
  268. package/dist/shims/cache.d.ts +4 -4
  269. package/dist/shims/cache.js +44 -16
  270. package/dist/shims/cacheability-classification.d.ts +7 -0
  271. package/dist/shims/cdn-cache.d.ts +8 -0
  272. package/dist/shims/cdn-cache.js +17 -1
  273. package/dist/shims/disable-smooth-scroll.d.ts +3 -0
  274. package/dist/shims/disable-smooth-scroll.js +36 -0
  275. package/dist/shims/document-placeholders.d.ts +19 -0
  276. package/dist/shims/document-placeholders.js +45 -0
  277. package/dist/shims/document.js +21 -5
  278. package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
  279. package/dist/shims/dynamic-preload-chunks.js +13 -9
  280. package/dist/shims/dynamic.d.ts +1 -1
  281. package/dist/shims/dynamic.js +60 -8
  282. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  283. package/dist/shims/error-boundary-navigation.js +19 -1
  284. package/dist/shims/error-boundary.d.ts +10 -10
  285. package/dist/shims/error-boundary.js +26 -7
  286. package/dist/shims/fetch-cache-state.d.ts +66 -0
  287. package/dist/shims/fetch-cache-state.js +92 -0
  288. package/dist/shims/fetch-cache.d.ts +3 -61
  289. package/dist/shims/fetch-cache.js +161 -108
  290. package/dist/shims/form.js +1 -1
  291. package/dist/shims/head.d.ts +10 -6
  292. package/dist/shims/head.js +15 -13
  293. package/dist/shims/headers.d.ts +13 -0
  294. package/dist/shims/headers.js +47 -4
  295. package/dist/shims/image.js +2 -1
  296. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
  297. package/dist/shims/internal/app-page-props-cache-key.js +24 -15
  298. package/dist/shims/internal/headers-state.d.ts +0 -1
  299. package/dist/shims/internal/work-store-scope.d.ts +5 -0
  300. package/dist/shims/internal/work-store-scope.js +24 -0
  301. package/dist/shims/metadata.js +3 -3
  302. package/dist/shims/navigation-errors.d.ts +6 -0
  303. package/dist/shims/navigation-errors.js +11 -1
  304. package/dist/shims/navigation.d.ts +7 -0
  305. package/dist/shims/navigation.js +45 -9
  306. package/dist/shims/request-context.d.ts +11 -0
  307. package/dist/shims/request-state-types.d.ts +2 -1
  308. package/dist/shims/router.js +12 -20
  309. package/dist/shims/server.d.ts +16 -0
  310. package/dist/shims/server.js +24 -4
  311. package/dist/shims/thenable-params.d.ts +4 -0
  312. package/dist/shims/thenable-params.js +25 -3
  313. package/dist/shims/unified-request-context.d.ts +1 -1
  314. package/dist/shims/unified-request-context.js +1 -0
  315. package/dist/shims/url-utils.d.ts +2 -0
  316. package/dist/shims/url-utils.js +3 -1
  317. package/dist/utils/client-runtime-metadata.js +1 -1
  318. package/dist/utils/hash.d.ts +7 -0
  319. package/dist/utils/hash.js +11 -1
  320. package/dist/utils/mdx-scan.d.ts +5 -0
  321. package/dist/utils/mdx-scan.js +8 -1
  322. package/dist/utils/package-name.d.ts +6 -0
  323. package/dist/utils/package-name.js +12 -1
  324. package/dist/utils/plugin-rsc-version.d.ts +4 -0
  325. package/dist/utils/plugin-rsc-version.js +15 -0
  326. package/dist/utils/prerender-output-paths.js +15 -4
  327. package/dist/utils/public-file-path.d.ts +10 -2
  328. package/dist/utils/public-file-path.js +13 -9
  329. package/dist/utils/public-routes.js +2 -2
  330. package/dist/utils/react-version.d.ts +3 -0
  331. package/dist/utils/react-version.js +1 -1
  332. package/dist/utils/regex-safety.d.ts +10 -0
  333. package/dist/utils/regex-safety.js +70 -18
  334. package/package.json +9 -5
@@ -1,6 +1,7 @@
1
1
  import { CacheLifeConfig } from "./cache-request-state.js";
2
- import { markAppPagePropsForUseCache } from "./internal/app-page-props-cache-key.js";
2
+ import { CacheFlightArguments } from "./cache-flight-arguments.js";
3
3
  //#region src/shims/cache-runtime.d.ts
4
+ export declare function replayCachedFunction(fn: object, args: CacheFlightArguments): Promise<unknown>;
4
5
  /**
5
6
  * Used purely as `cause` for the nested-dynamic cache error: its captured stack
6
7
  * points at the inner "use cache" invocation that propagated a dynamic cache
@@ -52,15 +53,6 @@ export declare function getCacheContext(): CacheContext | null;
52
53
  * Exported for testing.
53
54
  */
54
55
  export declare function buildUseCacheKey(id: string, keySeed: string | undefined, argsKey?: string): string;
55
- /**
56
- * Convert an encodeReply result (string | FormData) to a cache key string.
57
- * For FormData (binary args), produces a deterministic SHA-256 hash over
58
- * the sorted entries. We can't hash `new Response(formData).arrayBuffer()`
59
- * because multipart boundaries are non-deterministic across serializations.
60
- *
61
- * Exported for testing.
62
- */
63
- export declare function replyToCacheKey(reply: string | FormData): Promise<string>;
64
56
  export type PrivateCacheState = {
65
57
  _privateCache: Map<string, unknown> | null;
66
58
  };
@@ -85,8 +77,13 @@ export type RegisterCachedFunctionOptions = {
85
77
  acceptsSecondArgument?: boolean;
86
78
  /** Number of declared arguments supplied by the directive transform. */
87
79
  argumentCount?: number;
88
- decryptCaptures?: (value: unknown) => Promise<unknown[] | undefined>;
89
- encodeInvocationArgs?: (args: unknown[]) => Promise<string>;
80
+ /**
81
+ * Set only for an inline function that closes over values. It decrypts the
82
+ * capture envelope bound ahead of the call arguments and must reject any
83
+ * other first argument.
84
+ */
85
+ decryptCaptures?: (value: unknown) => Promise<unknown[]>;
86
+ encodeInvocation?: (args: CacheFlightArguments) => Promise<string>;
90
87
  serverReferenceId?: string;
91
88
  };
92
89
  /**
@@ -99,13 +96,8 @@ export type RegisterCachedFunctionOptions = {
99
96
  * @returns A wrapper function that checks cache before calling the original
100
97
  */
101
98
  export declare function registerCachedFunction<TArgs extends unknown[], TResult>(fn: (...args: TArgs) => Promise<TResult>, id: string, variant?: string, options?: RegisterCachedFunctionOptions): (...args: TArgs) => Promise<TResult>;
99
+ /** Memoize in one React render without skipping cache guards or scoped serialization. */
100
+ export declare function memoizeInCacheScope<TArgs extends unknown[], TResult>(fn: (...args: TArgs) => TResult): (...args: TArgs) => TResult;
102
101
  /** Whether a loaded server reference is a transformed `"use cache"` function. */
103
102
  export declare function isUseCacheFunction(value: unknown): value is (...args: unknown[]) => Promise<unknown>;
104
- /**
105
- * A thenable (not an array) with own enumerable properties — the
106
- * `Object.assign(Promise.resolve(obj), obj)` pattern Next.js params use. The
107
- * cache key is built from its fields instead of the promise.
108
- */
109
- export declare function isThenableObject(value: object): value is PromiseLike<unknown>;
110
- //#endregion
111
- export { markAppPagePropsForUseCache };
103
+ //#endregion
@@ -4,16 +4,19 @@ import { VINEXT_RSC_MARKER_HEADER } from "../server/headers.js";
4
4
  import { workUnitAsyncStorage } from "./internal/work-unit-async-storage.js";
5
5
  import { isRouteCacheabilityProbe, recordRouteCacheabilityProbeBailout } from "./cacheability-classification.js";
6
6
  import { getDataCacheHandler } from "./cache-handler.js";
7
+ import { addCollectedRequestTags, getCurrentFetchSoftTags, runWithDetachedFetchObservations } from "./fetch-cache-state.js";
7
8
  import { suppressHangingPromiseAbortRejections } from "./internal/make-hanging-promise.js";
8
9
  import { createPprFallbackShellSuspensePromise, trackPprFallbackShellCacheTask } from "./ppr-fallback-shell.js";
9
10
  import { markDynamicUsage, throwIfInsideCacheScope } from "./internal/headers-state.js";
10
11
  import { isDraftModeEnabled } from "./headers.js";
11
12
  import { _registerCacheContextAccessor } from "./internal/cache-context-accessor.js";
12
- import { _hasPendingRevalidatedTag, _setRequestScopedCacheLife, cacheLifeProfiles } from "./cache-request-state.js";
13
- import { addCollectedRequestTags, getCurrentFetchSoftTags } from "./fetch-cache.js";
14
- import { makeThenableParams } from "./thenable-params.js";
15
- import { APP_PAGE_USE_CACHE_MARKER, hasUseCachePageMarker, isMarkedAppPagePropsObject, isUseCacheFunctionReference, markAppPagePropsForUseCache } from "./internal/app-page-props-cache-key.js";
13
+ import { _hasPendingRevalidatedTag, _setRequestScopedCacheLife, cacheLifeProfiles, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
14
+ import "./fetch-cache.js";
15
+ import { hasUseCacheLayoutMarker, hasUseCachePageMarker, isUseCacheFunctionReference, withoutUseCacheSegmentMarker } from "./internal/app-page-props-cache-key.js";
16
+ import { getFallbackParamsSnapshot, makeThenableParams, restoreThenableParams } from "./thenable-params.js";
16
17
  import { getCurrentRootParams } from "./root-params.js";
18
+ import { flightArgumentsKey, restoreFlightReply, snapshotFlightReply } from "./cache-flight-arguments.js";
19
+ import { cache } from "react";
17
20
  //#region src/shims/cache-runtime.ts
18
21
  /**
19
22
  * "use cache" runtime
@@ -36,14 +39,17 @@ import { getCurrentRootParams } from "./root-params.js";
36
39
  * and all RSC-serializable types — unlike JSON.stringify which silently
37
40
  * drops $$typeof Symbols and function values.
38
41
  *
39
- * When RSC APIs are unavailable (e.g. in unit tests), falls back to
40
- * JSON.stringify/parse with the same stableStringify cache key generation.
41
- *
42
42
  * Cache variants:
43
43
  * - "use cache" — shared cache (default profile)
44
44
  * - "use cache: remote" — shared cache (explicit)
45
45
  * - "use cache: private" — per-request cache (not shared across requests)
46
46
  */
47
+ const replayableFunctions = /* @__PURE__ */ new WeakMap();
48
+ function replayCachedFunction(fn, args) {
49
+ const replay = replayableFunctions.get(fn);
50
+ if (!replay || args.version !== 1) throw new Error("Invalid cache function arguments");
51
+ return replay(args);
52
+ }
47
53
  /** Threshold below which expire is considered "dynamic" (5 minutes in seconds). */
48
54
  const DYNAMIC_EXPIRE = 300;
49
55
  /**
@@ -124,16 +130,9 @@ function buildUseCacheKey(id, keySeed, argsKey) {
124
130
  const scopedId = keySeed ? `build:${encodeURIComponent(keySeed)}:${id}` : id;
125
131
  return argsKey === void 0 ? `use-cache:${scopedId}` : `use-cache:${scopedId}:${argsKey}`;
126
132
  }
127
- const NOT_LOADED = Symbol("not-loaded");
128
- let _rscModule = NOT_LOADED;
129
- async function getRscModule() {
130
- if (_rscModule !== NOT_LOADED) return _rscModule;
131
- try {
132
- _rscModule = await import("@vitejs/plugin-rsc/react/rsc");
133
- } catch {
134
- _rscModule = null;
135
- }
136
- return _rscModule;
133
+ let _rscModule;
134
+ function getRscModule() {
135
+ return _rscModule ??= import("@vitejs/plugin-rsc/react/rsc");
137
136
  }
138
137
  /** Collect a ReadableStream<Uint8Array> into a single Uint8Array. */
139
138
  async function collectStream(stream) {
@@ -171,55 +170,22 @@ function uint8ToStream(bytes) {
171
170
  } });
172
171
  }
173
172
  async function serializeCacheResult(result, rsc) {
174
- if (rsc) {
175
- let serializationError;
176
- const [returnStream, savedStream] = rsc.renderToReadableStream(result, { onError(error) {
177
- serializationError ??= { value: error };
178
- } }).tee();
179
- try {
180
- const [deserializedResult, bytes] = await Promise.all([rsc.createFromReadableStream(returnStream, {}, { preserveServerReferences: true }), collectStream(savedStream)]);
181
- return {
182
- result: deserializedResult,
183
- cacheEntry: serializationError ? null : {
184
- body: uint8ToBase64(bytes),
185
- headers: { [VINEXT_RSC_MARKER_HEADER]: "1" }
186
- }
187
- };
188
- } catch (error) {
189
- throw serializationError?.value ?? error;
190
- }
191
- }
192
- const body = JSON.stringify(result);
193
- return body === void 0 ? null : {
194
- result,
195
- cacheEntry: {
196
- body,
197
- headers: {}
198
- }
199
- };
200
- }
201
- /**
202
- * Convert an encodeReply result (string | FormData) to a cache key string.
203
- * For FormData (binary args), produces a deterministic SHA-256 hash over
204
- * the sorted entries. We can't hash `new Response(formData).arrayBuffer()`
205
- * because multipart boundaries are non-deterministic across serializations.
206
- *
207
- * Exported for testing.
208
- */
209
- async function replyToCacheKey(reply) {
210
- if (typeof reply === "string") return reply;
211
- const entries = [...reply.entries()];
212
- const valStr = (v) => typeof v === "string" ? v : v.name;
213
- entries.sort((a, b) => a[0].localeCompare(b[0]) || valStr(a[1]).localeCompare(valStr(b[1])));
214
- const parts = [];
215
- for (const [name, value] of entries) if (typeof value === "string") parts.push(`${name}=s:${value}`);
216
- else {
217
- const bytes = new Uint8Array(await value.arrayBuffer());
218
- parts.push(`${name}=b:${value.type}:${value.size}:${Buffer.from(bytes).toString("base64")}`);
173
+ let serializationError;
174
+ const [returnStream, savedStream] = rsc.renderToReadableStream(result, { onError(error) {
175
+ serializationError ??= { value: error };
176
+ } }).tee();
177
+ try {
178
+ const [deserializedResult, bytes] = await Promise.all([rsc.createFromReadableStream(returnStream, {}, { preserveServerReferences: true }), collectStream(savedStream)]);
179
+ return {
180
+ result: deserializedResult,
181
+ cacheEntry: serializationError ? null : {
182
+ body: uint8ToBase64(bytes),
183
+ headers: { [VINEXT_RSC_MARKER_HEADER]: "1" }
184
+ }
185
+ };
186
+ } catch (error) {
187
+ throw serializationError?.value ?? error;
219
188
  }
220
- const payload = new TextEncoder().encode(parts.join("\0"));
221
- const hashBuffer = await crypto.subtle.digest("SHA-256", payload);
222
- return Buffer.from(new Uint8Array(hashBuffer)).toString("base64url");
223
189
  }
224
190
  /**
225
191
  * Resolve collected cacheLife configs into a single effective config.
@@ -301,6 +267,17 @@ function propagateRootParamNamesToParent(names) {
301
267
  if (!parent || parent.variant === "private") return;
302
268
  for (const name of names) parent.readRootParamNames?.add(name);
303
269
  }
270
+ function isServableCacheState(cacheState) {
271
+ if (cacheState === "expired") return false;
272
+ if (cacheState !== "stale") return true;
273
+ return shouldServeStaleUnstableCacheEntry() && process.env.VINEXT_PRERENDER !== "1" && !isRouteCacheabilityProbe();
274
+ }
275
+ function regenerateInBackground(id, regenerate) {
276
+ const regeneration = runWithDetachedCacheObservations(() => runWithDetachedFetchObservations(() => cacheContextStorage.exit(regenerate))).then(() => void 0, (error) => {
277
+ console.error(`[vinext] use cache: background regeneration failed for ${id}:`, error);
278
+ });
279
+ if (isInsideUnifiedScope()) getRequestContext().executionContext?.waitUntil(regeneration);
280
+ }
304
281
  /**
305
282
  * Register a function as a cached function. This is called by the Vite
306
283
  * transform for each "use cache" function.
@@ -315,7 +292,7 @@ function registerCachedFunction(fn, id, variant, options = {}) {
315
292
  const omitAppPageSearchParams = cacheVariant !== "private";
316
293
  const cacheFunctionId = options.serverReferenceId ? JSON.stringify([id, options.serverReferenceId]) : id;
317
294
  const isDev = typeof process !== "undefined" && process.env.NODE_ENV === "development";
318
- const cachedFn = (...args) => {
295
+ const invoke = (args, replay) => {
319
296
  if (cacheVariant === "private") {
320
297
  const parentCtx = cacheContextStorage.getStore();
321
298
  if (parentCtx && parentCtx.variant !== "private") throwPrivateUseCacheInsidePublicUseCacheError();
@@ -346,40 +323,60 @@ function registerCachedFunction(fn, id, variant, options = {}) {
346
323
  }
347
324
  }
348
325
  return trackPprFallbackShellCacheTask(async () => {
349
- const rsc = await getRscModule();
326
+ const codec = await getRscModule();
327
+ const clientReferences = codec.createClientTemporaryReferenceSet();
328
+ const serverReferences = codec.createTemporaryReferenceSet();
329
+ const rsc = {
330
+ ...codec,
331
+ renderToReadableStream: (value, options) => codec.renderToReadableStream(value, {
332
+ ...options,
333
+ temporaryReferences: serverReferences
334
+ }),
335
+ createFromReadableStream: (stream, options, context) => codec.createFromReadableStream(stream, {
336
+ ...options,
337
+ temporaryReferences: clientReferences
338
+ }, context)
339
+ };
350
340
  const keySeed = getUseCacheKeySeed();
351
- const captures = options.decryptCaptures ? await options.decryptCaptures(args[0]) : void 0;
341
+ const captures = !replay && options.decryptCaptures ? await options.decryptCaptures(args[0]) : void 0;
352
342
  const hasCaptureEnvelope = captures !== void 0;
353
- const pagePropsArgIndex = args.findIndex(hasUseCachePageMarker);
343
+ const limitedArgs = options.argumentCount === void 0 ? args : hasCaptureEnvelope ? [args[0], ...args.slice(1, 1 + options.argumentCount)] : args.slice(0, options.argumentCount);
344
+ const pagePropsArgIndex = replay?.pagePropsIndex ?? limitedArgs.findIndex(hasUseCachePageMarker);
345
+ const layoutPropsArgIndex = replay?.layoutPropsIndex ?? limitedArgs.findIndex(hasUseCacheLayoutMarker);
354
346
  const isPageInvocation = pagePropsArgIndex !== -1;
355
- const invocationArgs = isPageInvocation ? replaceArgument(args, pagePropsArgIndex, withoutUseCachePageMarker(args[pagePropsArgIndex])) : args;
356
- const admittedArgs = options.argumentCount === void 0 ? invocationArgs : hasCaptureEnvelope ? [invocationArgs[0], ...invocationArgs.slice(1, 1 + options.argumentCount)] : invocationArgs.slice(0, options.argumentCount);
347
+ const segmentPropsIndex = isPageInvocation ? pagePropsArgIndex : layoutPropsArgIndex;
348
+ const admittedArgs = segmentPropsIndex !== -1 && !replay ? replaceArgument(limitedArgs, segmentPropsIndex, withoutUseCacheSegmentMarker(limitedArgs[segmentPropsIndex], isPageInvocation)) : limitedArgs;
357
349
  const executionArgs = hasCaptureEnvelope ? [captures, ...admittedArgs.slice(1)] : admittedArgs;
350
+ const outerParams = !replay && segmentPropsIndex !== -1 ? executionArgs[segmentPropsIndex].params : void 0;
351
+ const fallbackParams = getFallbackParamsSnapshot(outerParams);
352
+ const serializationArgs = fallbackParams ? replaceArgument(executionArgs, segmentPropsIndex, {
353
+ ...executionArgs[segmentPropsIndex],
354
+ params: fallbackParams
355
+ }) : executionArgs;
358
356
  const pagePropsIndex = omitAppPageSearchParams && isPageInvocation ? pagePropsArgIndex : void 0;
359
- const callArgs = pagePropsIndex === void 0 ? executionArgs : withErroringPageSearchParams(executionArgs, pagePropsIndex);
360
- let cacheKey;
361
- try {
362
- const processedArgs = executionArgs.length > 0 ? unwrapThenableObjectArray(executionArgs, {
363
- pagePropsIndex,
364
- omitMarkedAppPageSearchParams: omitAppPageSearchParams
365
- }) : [];
366
- if (rsc && executionArgs.length > 0) {
367
- const tempRefs = rsc.createClientTemporaryReferenceSet();
368
- const encoded = await rsc.encodeReply(processedArgs, { temporaryReferences: tempRefs });
369
- cacheKey = buildUseCacheKey(cacheFunctionId, keySeed, await replyToCacheKey(encoded));
370
- } else {
371
- const argsKey = processedArgs.length > 0 ? stableStringify(processedArgs) : void 0;
372
- cacheKey = buildUseCacheKey(cacheFunctionId, keySeed, argsKey);
373
- }
374
- } catch {
375
- return (await executeWithContext(fn, callArgs, cacheVariant)).result;
357
+ const keyArgs = pagePropsIndex === void 0 ? serializationArgs : toReplayablePageArgs(serializationArgs, pagePropsIndex);
358
+ const flightArguments = replay ?? await snapshotFlightReply(await rsc.encodeReply(keyArgs, { temporaryReferences: clientReferences }), isPageInvocation ? pagePropsArgIndex : void 0);
359
+ if (!replay && layoutPropsArgIndex !== -1) flightArguments.layoutPropsIndex = layoutPropsArgIndex;
360
+ let cacheKey = buildUseCacheKey(cacheFunctionId, keySeed, flightArgumentsKey(flightArguments));
361
+ let callArgs = await rsc.decodeReply(restoreFlightReply(flightArguments), { temporaryReferences: serverReferences });
362
+ if (segmentPropsIndex !== -1) {
363
+ const props = callArgs[segmentPropsIndex];
364
+ callArgs = replaceArgument(callArgs, segmentPropsIndex, {
365
+ ...props,
366
+ params: restoreThenableParams(await props.params, outerParams)
367
+ });
368
+ if (pagePropsIndex !== void 0) callArgs = withErroringPageSearchParams(callArgs, pagePropsIndex);
376
369
  }
370
+ if (fallbackParams) return (await executeWithContext(fn, callArgs, cacheVariant, rsc)).result;
377
371
  if (cacheVariant === "private") {
378
372
  const privateCache = _getPrivateState()._privateCache;
379
373
  const privateHit = privateCache.get(cacheKey);
380
- if (privateHit !== void 0) return privateHit;
374
+ if (privateHit !== void 0) {
375
+ if (privateHit.serialized) return rsc.createFromReadableStream(uint8ToStream(base64ToUint8(privateHit.serialized.body)), {}, { preserveServerReferences: true });
376
+ return privateHit.result;
377
+ }
381
378
  const execution = await executeWithContext(fn, callArgs, cacheVariant, rsc);
382
- if (execution.cacheable) privateCache.set(cacheKey, execution.result);
379
+ if (execution.cacheable) privateCache.set(cacheKey, execution);
383
380
  return execution.result;
384
381
  }
385
382
  if (isDev || isDraftModeEnabled()) return (await executeWithContext(fn, callArgs, cacheVariant, rsc)).result;
@@ -399,7 +396,7 @@ function registerCachedFunction(fn, id, variant, options = {}) {
399
396
  console.error("[vinext] use cache: handler.get failed; treating as a cache miss:", error);
400
397
  }
401
398
  const redirectValue = existing?.value;
402
- if (isRootParamRedirect(existing) && existing?.cacheState !== "stale" && rootParams && redirectValue?.kind === "FETCH" && !_hasPendingRevalidatedTag([...redirectValue.tags ?? [], ...softTags])) {
399
+ if (isRootParamRedirect(existing) && isServableCacheState(existing?.cacheState) && rootParams && redirectValue?.kind === "FETCH" && !_hasPendingRevalidatedTag([...redirectValue.tags ?? [], ...softTags])) {
403
400
  cacheKey = coarseCacheKey + computeRootParamsCacheKeySuffix(rootParams, addKnownRootParamNames(id, rootParamNamesFromTags(redirectValue.tags)));
404
401
  try {
405
402
  existing = await handler.get(cacheKey, {
@@ -411,78 +408,80 @@ function registerCachedFunction(fn, id, variant, options = {}) {
411
408
  existing = null;
412
409
  }
413
410
  }
414
- if (existing?.value && existing.value.kind === "FETCH" && existing.cacheState !== "stale" && !_hasPendingRevalidatedTag([...existing.value.tags ?? [], ...softTags])) try {
415
- propagateRootParamNamesToParent(knownRootParamsByFunctionId.get(id));
416
- propagateCacheTagsToRequest(existing.value.tags);
417
- if (rsc && existing.value.data.headers["x-vinext-rsc"] === "1") {
418
- const stream = uint8ToStream(base64ToUint8(existing.value.data.body));
419
- const result = await rsc.createFromReadableStream(stream, {}, { preserveServerReferences: true });
420
- recordRequestScopedCacheControl(existing.cacheControl);
421
- return result;
411
+ const generate = async (propagate) => {
412
+ const { result, ctx, effectiveLife, collectedResult } = await runCachedFunctionWithContext(fn, callArgs, cacheVariant, (value) => serializeCacheResult(value, rsc));
413
+ const rootParamNames = ctx.readRootParamNames && ctx.readRootParamNames.size > 0 ? addKnownRootParamNames(id, ctx.readRootParamNames) : knownRootParamsByFunctionId.get(id);
414
+ if (propagate) {
415
+ recordRequestScopedCacheLife(effectiveLife);
416
+ propagateCacheTagsToRequest(ctx.tags);
422
417
  }
423
- const result = JSON.parse(existing.value.data.body);
424
- recordRequestScopedCacheControl(existing.cacheControl);
425
- return result;
426
- } catch {}
427
- const { result, ctx, effectiveLife, collectedResult } = await runCachedFunctionWithContext(fn, callArgs, cacheVariant, (value) => serializeCacheResult(value, rsc));
428
- const rootParamNames = ctx.readRootParamNames && ctx.readRootParamNames.size > 0 ? addKnownRootParamNames(id, ctx.readRootParamNames) : knownRootParamsByFunctionId.get(id);
429
- recordRequestScopedCacheLife(effectiveLife);
430
- propagateCacheTagsToRequest(ctx.tags);
431
- const revalidateSeconds = effectiveLife.revalidate ?? cacheLifeProfiles.default.revalidate ?? 900;
432
- if (collectedResult?.cacheEntry) try {
433
- let cacheFunctionInvocation;
434
- if (options.serverReferenceId && options.encodeInvocationArgs) try {
435
- cacheFunctionInvocation = {
436
- encryptedArgs: await options.encodeInvocationArgs(pagePropsIndex === void 0 ? admittedArgs : toReplayablePageArgs(admittedArgs, pagePropsIndex)),
437
- referenceId: options.serverReferenceId,
438
- rootParams: Object.fromEntries(Object.entries(rootParams ?? {}).filter((entry) => entry[1] !== void 0)),
439
- softTags
440
- };
441
- } catch {}
442
- const serialized = collectedResult.cacheEntry;
443
- const cacheValue = {
444
- kind: "FETCH",
445
- data: {
446
- headers: serialized.headers,
447
- body: serialized.body,
448
- url: cacheKey
449
- },
450
- tags: ctx.tags,
451
- revalidate: revalidateSeconds
452
- };
453
- const cacheContext = {
454
- fetchCache: true,
455
- tags: ctx.tags,
456
- ...cacheFunctionInvocation ? { cacheFunctionInvocation } : {},
457
- cacheControl: {
458
- revalidate: revalidateSeconds,
459
- expire: effectiveLife.expire,
460
- stale: effectiveLife.stale
461
- }
462
- };
463
- if (rootParamNames && rootParamNames.size > 0 && rootParams) {
464
- const specificCacheKey = coarseCacheKey + computeRootParamsCacheKeySuffix(rootParams, rootParamNames);
465
- const redirectTags = [...ctx.tags, ...[...rootParamNames].map((name) => ROOT_PARAM_TAG_PREFIX + name)];
466
- await handler.set(coarseCacheKey, {
418
+ const revalidateSeconds = effectiveLife.revalidate ?? cacheLifeProfiles.default.revalidate ?? 900;
419
+ if (collectedResult?.cacheEntry) try {
420
+ let cacheFunctionInvocation;
421
+ if (options.serverReferenceId && options.encodeInvocation) try {
422
+ cacheFunctionInvocation = {
423
+ encryptedArgs: await options.encodeInvocation(flightArguments),
424
+ referenceId: options.serverReferenceId,
425
+ rootParams: Object.fromEntries(Object.entries(rootParams ?? {}).filter((entry) => entry[1] !== void 0)),
426
+ softTags
427
+ };
428
+ } catch {}
429
+ const serialized = collectedResult.cacheEntry;
430
+ const cacheValue = {
467
431
  kind: "FETCH",
468
432
  data: {
469
- headers: { [ROOT_PARAM_REDIRECT_HEADER]: "1" },
470
- body: "",
471
- url: coarseCacheKey
433
+ headers: serialized.headers,
434
+ body: serialized.body,
435
+ url: cacheKey
472
436
  },
473
- tags: redirectTags,
437
+ tags: ctx.tags,
474
438
  revalidate: revalidateSeconds
475
- }, {
476
- ...cacheContext,
477
- tags: redirectTags
478
- });
479
- cacheValue.data.url = specificCacheKey;
480
- await handler.set(specificCacheKey, cacheValue, cacheContext);
481
- } else await handler.set(cacheKey, cacheValue, cacheContext);
439
+ };
440
+ const cacheContext = {
441
+ fetchCache: true,
442
+ tags: ctx.tags,
443
+ ...cacheFunctionInvocation ? { cacheFunctionInvocation } : {},
444
+ cacheControl: {
445
+ revalidate: revalidateSeconds,
446
+ expire: effectiveLife.expire,
447
+ stale: effectiveLife.stale
448
+ }
449
+ };
450
+ if (rootParamNames && rootParamNames.size > 0 && rootParams) {
451
+ const specificCacheKey = coarseCacheKey + computeRootParamsCacheKeySuffix(rootParams, rootParamNames);
452
+ const redirectTags = [...ctx.tags, ...[...rootParamNames].map((name) => ROOT_PARAM_TAG_PREFIX + name)];
453
+ await handler.set(coarseCacheKey, {
454
+ kind: "FETCH",
455
+ data: {
456
+ headers: { [ROOT_PARAM_REDIRECT_HEADER]: "1" },
457
+ body: "",
458
+ url: coarseCacheKey
459
+ },
460
+ tags: redirectTags,
461
+ revalidate: revalidateSeconds
462
+ }, {
463
+ ...cacheContext,
464
+ tags: redirectTags
465
+ });
466
+ cacheValue.data.url = specificCacheKey;
467
+ await handler.set(specificCacheKey, cacheValue, cacheContext);
468
+ } else await handler.set(cacheKey, cacheValue, cacheContext);
469
+ } catch {}
470
+ return collectedResult ? collectedResult.result : result;
471
+ };
472
+ if (existing?.value && existing.value.kind === "FETCH" && existing.value.data.headers["x-vinext-rsc"] === "1" && isServableCacheState(existing.cacheState) && !_hasPendingRevalidatedTag([...existing.value.tags ?? [], ...softTags])) try {
473
+ propagateRootParamNamesToParent(knownRootParamsByFunctionId.get(id));
474
+ propagateCacheTagsToRequest(existing.value.tags);
475
+ const result = await rsc.createFromReadableStream(uint8ToStream(base64ToUint8(existing.value.data.body)), {}, { preserveServerReferences: true });
476
+ recordRequestScopedCacheControl(existing.cacheControl);
477
+ if (existing.cacheState === "stale") regenerateInBackground(id, () => generate(false));
478
+ return result;
482
479
  } catch {}
483
- return collectedResult ? collectedResult.result : result;
480
+ return generate(true);
484
481
  }, cacheVariant);
485
482
  };
483
+ const cachedFn = memoizeInCacheScope((...args) => invoke(args));
484
+ replayableFunctions.set(cachedFn, (data) => invoke([], data));
486
485
  Object.defineProperty(cachedFn, "length", {
487
486
  value: fn.length,
488
487
  configurable: true
@@ -491,6 +490,11 @@ function registerCachedFunction(fn, id, variant, options = {}) {
491
490
  if (options.acceptsSecondArgument !== void 0) Reflect.set(cachedFn, USE_CACHE_ACCEPTS_SECOND_ARGUMENT_SYMBOL, options.acceptsSecondArgument);
492
491
  return cachedFn;
493
492
  }
493
+ /** Memoize in one React render without skipping cache guards or scoped serialization. */
494
+ function memoizeInCacheScope(fn) {
495
+ const memoized = cache((_parent, _workUnit, _unstable, ...args) => fn(...args));
496
+ return (...args) => memoized(cacheContextStorage.getStore(), workUnitAsyncStorage.getStore(), unstableCacheContextStorage.getStore() === true, ...args);
497
+ }
494
498
  /** @internal Symbol used to identify "use cache" wrapper functions. */
495
499
  const USE_CACHE_FUNCTION_SYMBOL = Symbol.for("vinext.useCacheFunction");
496
500
  /** @internal Symbol carrying transform-derived cached function argument metadata. */
@@ -555,11 +559,12 @@ function propagateCacheTagsToRequest(tags) {
555
559
  addCollectedRequestTags(tags);
556
560
  }
557
561
  async function executeWithContext(fn, args, variant, rsc) {
558
- const { result, ctx: _ctx, effectiveLife, collectedResult } = await runCachedFunctionWithContext(fn, args, variant, rsc ? (value) => serializeCacheResult(value, rsc) : void 0);
562
+ const { result, ctx: _ctx, effectiveLife, collectedResult } = await runCachedFunctionWithContext(fn, args, variant, (value) => serializeCacheResult(value, rsc));
559
563
  recordRequestScopedCacheLife(effectiveLife);
560
564
  return {
561
565
  result: collectedResult ? collectedResult.result : result,
562
- cacheable: collectedResult?.cacheEntry !== null
566
+ cacheable: collectedResult?.cacheEntry !== null,
567
+ serialized: collectedResult?.cacheEntry
563
568
  };
564
569
  }
565
570
  async function runCachedFunctionWithContext(fn, args, variant, collectResult) {
@@ -605,31 +610,6 @@ async function runCachedFunctionWithContext(fn, args, variant, collectResult) {
605
610
  collectedResult
606
611
  };
607
612
  }
608
- function unwrapThenableObjects(value, options) {
609
- if (value === null || value === void 0 || typeof value !== "object") return value;
610
- const childOptions = { omitMarkedAppPageSearchParams: options.omitMarkedAppPageSearchParams };
611
- if (Array.isArray(value)) return value.map((item) => unwrapThenableObjects(item, childOptions));
612
- if (isThenableObject(value)) {
613
- const plain = {};
614
- for (const key of Object.keys(value)) plain[key] = unwrapThenableObjects(value[key], childOptions);
615
- return plain;
616
- }
617
- if (typeof value.then === "function") return value;
618
- const result = {};
619
- for (const key of Object.keys(value)) {
620
- if (key === "searchParams" && (options.omitAppPageSearchParamsAtRoot || options.omitMarkedAppPageSearchParams && isMarkedAppPagePropsObject(value))) continue;
621
- result[key] = unwrapThenableObjects(value[key], childOptions);
622
- }
623
- return result;
624
- }
625
- /**
626
- * A thenable (not an array) with own enumerable properties — the
627
- * `Object.assign(Promise.resolve(obj), obj)` pattern Next.js params use. The
628
- * cache key is built from its fields instead of the promise.
629
- */
630
- function isThenableObject(value) {
631
- return !Array.isArray(value) && "then" in value && typeof value.then === "function" && Object.keys(value).length > 0;
632
- }
633
613
  function isPagePropsObject(value) {
634
614
  return value !== null && typeof value === "object" && !Array.isArray(value);
635
615
  }
@@ -638,26 +618,17 @@ function replaceArgument(args, index, value) {
638
618
  result[index] = value;
639
619
  return result;
640
620
  }
641
- /** Remove the `$$isPage` invocation marker before props reach the key or user code. */
642
- function withoutUseCachePageMarker(props) {
643
- const { [APP_PAGE_USE_CACHE_MARKER]: _marker, ...pageProps } = props;
644
- return isMarkedAppPagePropsObject(props) ? markAppPagePropsForUseCache(pageProps) : pageProps;
645
- }
646
621
  /**
647
622
  * Response Store replay args for a public page cache: drop `searchParams` from
648
623
  * the page props at `index` (after a capture envelope, if any), as Next.js does
649
- * for the serialized arguments (use-cache-wrapper.ts, `isPageSegmentFunction`),
650
- * and keep the `$$isPage` marker so a replay regains page semantics, including
651
- * the erroring searchParams fallback.
624
+ * for the serialized arguments (use-cache-wrapper.ts, `isPageSegmentFunction`).
625
+ * The replay regains page semantics from `CacheFlightArguments.pagePropsIndex`.
652
626
  */
653
627
  function toReplayablePageArgs(args, index) {
654
628
  const props = args[index];
655
629
  if (!isPagePropsObject(props)) return [...args];
656
630
  const { searchParams: _searchParams, ...pageProps } = props;
657
- return replaceArgument(args, index, {
658
- ...pageProps,
659
- [APP_PAGE_USE_CACHE_MARKER]: true
660
- });
631
+ return replaceArgument(args, index, pageProps);
661
632
  }
662
633
  /**
663
634
  * Give page props at `index` without `searchParams` (a Response Store replay of
@@ -673,35 +644,5 @@ function withErroringPageSearchParams(args, index) {
673
644
  searchParams: makeThenableParams({}, { observeParamAccess: () => throwIfInsideCacheScope("searchParams") })
674
645
  });
675
646
  }
676
- function unwrapThenableObjectArray(values, options) {
677
- return values.map((value, index) => unwrapThenableObjects(value, {
678
- omitAppPageSearchParamsAtRoot: index === options.pagePropsIndex,
679
- omitMarkedAppPageSearchParams: options.omitMarkedAppPageSearchParams
680
- }));
681
- }
682
- function stableStringify(value, seen) {
683
- if (value === void 0) return "undefined";
684
- if (value === null) return "null";
685
- if (typeof value === "function") throw new Error("Cannot serialize function");
686
- if (typeof value === "symbol") throw new Error("Cannot serialize symbol");
687
- if (Array.isArray(value)) {
688
- if (!seen) seen = /* @__PURE__ */ new Set();
689
- if (seen.has(value)) throw new Error("Circular reference");
690
- seen.add(value);
691
- const result = "[" + value.map((v) => stableStringify(v, seen)).join(",") + "]";
692
- seen.delete(value);
693
- return result;
694
- }
695
- if (typeof value === "object" && value !== null) {
696
- if (value instanceof Date) return `Date(${value.getTime()})`;
697
- if (!seen) seen = /* @__PURE__ */ new Set();
698
- if (seen.has(value)) throw new Error("Circular reference");
699
- seen.add(value);
700
- const result = "{" + Object.keys(value).sort().map((k) => `${JSON.stringify(k)}:${stableStringify(value[k], seen)}`).join(",") + "}";
701
- seen.delete(value);
702
- return result;
703
- }
704
- return JSON.stringify(value);
705
- }
706
647
  //#endregion
707
- export { NestedDynamicUseCacheError, buildUseCacheKey, cacheContextStorage, clearPrivateCache, getCacheContext, isThenableObject, isUseCacheFunction, markAppPagePropsForUseCache, registerCachedFunction, replyToCacheKey, runWithPrivateCache };
648
+ export { NestedDynamicUseCacheError, buildUseCacheKey, cacheContextStorage, clearPrivateCache, getCacheContext, isUseCacheFunction, memoizeInCacheScope, registerCachedFunction, replayCachedFunction, runWithPrivateCache };
@@ -1,6 +1,6 @@
1
1
  import { ExecutionContextLike, getRequestExecutionContext, runWithExecutionContext } from "./request-context.js";
2
2
  import { _recordUseCacheRootParamRead, _registerCacheContextAccessor, getRegisteredCacheContext } from "./internal/cache-context-accessor.js";
3
- import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheLifeConfig, CacheState, UnstableCacheObservation, UnstableCacheRevalidationMode, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
3
+ import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheLifeConfig, CacheLifeSink, CacheState, UnstableCacheObservation, UnstableCacheRevalidationMode, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, markActionRevalidation, recordUnstableCacheObservation, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
4
4
  import { CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getCacheHandler, getDataCacheHandler, registerDataCacheHandler, registerLazyDataCacheHandler, setCacheHandler, setDataCacheHandler } from "./cache-handler.js";
5
5
  //#region src/shims/cache.d.ts
6
6
  /**
@@ -137,9 +137,9 @@ type UnstableCacheOptions = {
137
137
  /**
138
138
  * Wrap an async function with caching.
139
139
  *
140
- * Returns a new function that caches results. The cache key is derived
141
- * from keyParts + serialized arguments.
140
+ * Returns a new function that caches results. The cache key is a SHA-256
141
+ * digest of the callback source, keyParts and serialized arguments.
142
142
  */
143
143
  export declare function unstable_cache<T extends (...args: any[]) => Promise<any>>(fn: T, keyParts?: string[], options?: UnstableCacheOptions): T;
144
144
  //#endregion
145
- export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CacheLifeConfig, CacheState, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, type ExecutionContextLike, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, UnstableCacheObservation, UnstableCacheRevalidationMode, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _recordUseCacheRootParamRead, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, markActionRevalidation, unstable_noStore as noStore, recordUnstableCacheObservation, registerDataCacheHandler, registerLazyDataCacheHandler, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry };
145
+ export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CacheLifeConfig, CacheLifeSink, CacheState, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, type ExecutionContextLike, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, UnstableCacheObservation, UnstableCacheRevalidationMode, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _recordUseCacheRootParamRead, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, markActionRevalidation, unstable_noStore as noStore, recordUnstableCacheObservation, registerDataCacheHandler, registerLazyDataCacheHandler, runWithDetachedCacheObservations, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry };