vinext 1.3.1 → 1.4.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 (234) hide show
  1. package/README.md +5 -2
  2. package/THIRD_PARTY_LICENSES.md +47 -0
  3. package/dist/_virtual/_rolldown/runtime.js +3 -2
  4. package/dist/build/prerender.js +1 -1
  5. package/dist/build/report.d.ts +0 -14
  6. package/dist/build/report.js +1 -51
  7. package/dist/check.js +1 -1
  8. package/dist/cli.js +3 -0
  9. package/dist/client/dev-error-overlay.js +1 -1
  10. package/dist/client/navigation-runtime.d.ts +13 -1
  11. package/dist/client/navigation-runtime.js +1 -1
  12. package/dist/config/next-config.d.ts +19 -0
  13. package/dist/config/next-config.js +64 -1
  14. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
  15. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
  16. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
  17. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
  18. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
  19. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
  20. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
  21. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
  22. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
  23. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
  24. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
  25. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
  26. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
  27. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
  28. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
  29. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
  30. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
  31. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
  32. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
  33. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
  34. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
  35. package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
  36. package/dist/entries/app-rsc-entry.js +17 -48
  37. package/dist/entries/app-rsc-manifest.js +3 -4
  38. package/dist/entries/app-ssr-entry.js +1 -0
  39. package/dist/entries/pages-server-entry.js +33 -8
  40. package/dist/index.js +83 -70
  41. package/dist/init-cloudflare.d.ts +1 -3
  42. package/dist/init-cloudflare.js +10 -48
  43. package/dist/init-platform.d.ts +2 -0
  44. package/dist/init-platform.js +4 -0
  45. package/dist/plugins/extensionless-dynamic-import.js +6 -2
  46. package/dist/plugins/next-intl-catalog.d.ts +12 -0
  47. package/dist/plugins/next-intl-catalog.js +85 -0
  48. package/dist/plugins/pages-node-externals.d.ts +1 -0
  49. package/dist/plugins/pages-node-externals.js +1 -1
  50. package/dist/plugins/use-cache-callable.d.ts +1 -1
  51. package/dist/plugins/use-cache-callable.js +136 -94
  52. package/dist/routing/app-route-graph.d.ts +6 -0
  53. package/dist/routing/app-route-graph.js +9 -1
  54. package/dist/server/api-handler.js +19 -4
  55. package/dist/server/app-bfcache-identity.js +1 -1
  56. package/dist/server/app-browser-entry.js +79 -63
  57. package/dist/server/app-browser-history-controller.d.ts +5 -4
  58. package/dist/server/app-browser-history-controller.js +93 -15
  59. package/dist/server/app-browser-navigation-controller.d.ts +2 -2
  60. package/dist/server/app-browser-navigation-controller.js +1 -2
  61. package/dist/server/app-browser-rsc-redirect.js +4 -4
  62. package/dist/server/app-browser-server-action-client.d.ts +2 -0
  63. package/dist/server/app-browser-server-action-client.js +4 -3
  64. package/dist/server/app-browser-state.d.ts +2 -4
  65. package/dist/server/app-browser-state.js +9 -4
  66. package/dist/server/app-browser-supplemental-refresh.js +16 -1
  67. package/dist/server/app-browser-visible-commit.d.ts +1 -1
  68. package/dist/server/app-browser-visible-commit.js +2 -12
  69. package/dist/server/app-elements-wire.d.ts +6 -38
  70. package/dist/server/app-elements-wire.js +4 -41
  71. package/dist/server/app-elements.d.ts +2 -2
  72. package/dist/server/app-elements.js +2 -2
  73. package/dist/server/app-history-state.d.ts +2 -2
  74. package/dist/server/app-history-state.js +5 -2
  75. package/dist/server/app-mounted-layouts.d.ts +21 -0
  76. package/dist/server/app-mounted-layouts.js +67 -0
  77. package/dist/server/app-optimistic-routing.d.ts +19 -1
  78. package/dist/server/app-optimistic-routing.js +42 -2
  79. package/dist/server/app-page-boundary-render.js +7 -6
  80. package/dist/server/app-page-boundary.js +2 -2
  81. package/dist/server/app-page-cache-finalizer.d.ts +12 -1
  82. package/dist/server/app-page-cache-finalizer.js +70 -29
  83. package/dist/server/app-page-cache.d.ts +13 -1
  84. package/dist/server/app-page-cache.js +31 -9
  85. package/dist/server/app-page-dispatch.d.ts +5 -10
  86. package/dist/server/app-page-dispatch.js +84 -154
  87. package/dist/server/app-page-element-builder.d.ts +2 -2
  88. package/dist/server/app-page-element-builder.js +10 -9
  89. package/dist/server/app-page-execution.d.ts +17 -52
  90. package/dist/server/app-page-execution.js +99 -95
  91. package/dist/server/app-page-head.d.ts +13 -0
  92. package/dist/server/app-page-head.js +44 -16
  93. package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
  94. package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
  95. package/dist/server/app-page-layout-gate.d.ts +35 -0
  96. package/dist/server/app-page-layout-gate.js +50 -0
  97. package/dist/server/app-page-params.d.ts +0 -1
  98. package/dist/server/app-page-params.js +1 -14
  99. package/dist/server/app-page-probe.d.ts +3 -21
  100. package/dist/server/app-page-probe.js +4 -37
  101. package/dist/server/app-page-render.d.ts +2 -12
  102. package/dist/server/app-page-render.js +89 -220
  103. package/dist/server/app-page-request.d.ts +1 -3
  104. package/dist/server/app-page-request.js +1 -1
  105. package/dist/server/app-page-response.js +3 -3
  106. package/dist/server/app-page-route-wiring.d.ts +13 -6
  107. package/dist/server/app-page-route-wiring.js +67 -61
  108. package/dist/server/app-page-rsc-render-status.d.ts +27 -1
  109. package/dist/server/app-page-rsc-render-status.js +121 -13
  110. package/dist/server/app-page-stream.d.ts +2 -0
  111. package/dist/server/app-page-stream.js +2 -2
  112. package/dist/server/app-pages-bridge.d.ts +4 -0
  113. package/dist/server/app-pages-bridge.js +7 -3
  114. package/dist/server/app-render-dependency.d.ts +11 -4
  115. package/dist/server/app-render-dependency.js +86 -38
  116. package/dist/server/app-request-stage-dispatch.js +1 -1
  117. package/dist/server/app-route-handler-cache.js +2 -2
  118. package/dist/server/app-route-handler-dispatch.js +14 -9
  119. package/dist/server/app-route-handler-execution.js +8 -3
  120. package/dist/server/app-route-handler-policy.d.ts +1 -1
  121. package/dist/server/app-route-handler-policy.js +3 -3
  122. package/dist/server/app-route-handler-response.js +1 -1
  123. package/dist/server/app-route-handler-runtime.js +17 -4
  124. package/dist/server/app-rsc-cache-busting.d.ts +2 -2
  125. package/dist/server/app-rsc-cache-busting.js +4 -4
  126. package/dist/server/app-rsc-error-handler.d.ts +2 -1
  127. package/dist/server/app-rsc-error-handler.js +9 -1
  128. package/dist/server/app-rsc-errors.d.ts +8 -0
  129. package/dist/server/app-rsc-errors.js +8 -1
  130. package/dist/server/app-rsc-handler.d.ts +5 -5
  131. package/dist/server/app-rsc-handler.js +30 -24
  132. package/dist/server/app-rsc-request-normalization.d.ts +0 -4
  133. package/dist/server/app-rsc-request-normalization.js +1 -4
  134. package/dist/server/app-rsc-response-finalizer.js +2 -2
  135. package/dist/server/app-rsc-response-stage.js +5 -3
  136. package/dist/server/app-server-action-execution.d.ts +3 -1
  137. package/dist/server/app-server-action-execution.js +7 -4
  138. package/dist/server/app-ssr-entry.d.ts +2 -0
  139. package/dist/server/app-ssr-entry.js +9 -8
  140. package/dist/server/app-ssr-stream.js +1 -1
  141. package/dist/server/app-visited-response-cache.d.ts +36 -1
  142. package/dist/server/app-visited-response-cache.js +46 -5
  143. package/dist/server/app-worker-stages.d.ts +25 -3
  144. package/dist/server/app-worker-stages.js +45 -6
  145. package/dist/server/artifact-compatibility.d.ts +0 -1
  146. package/dist/server/artifact-compatibility.js +1 -10
  147. package/dist/server/cache-proof.d.ts +1 -115
  148. package/dist/server/cache-proof.js +1 -544
  149. package/dist/server/cacheability-request.js +13 -8
  150. package/dist/server/dev-server.js +4 -3
  151. package/dist/server/headers.d.ts +6 -3
  152. package/dist/server/headers.js +9 -5
  153. package/dist/server/isr-cache.d.ts +8 -2
  154. package/dist/server/isr-cache.js +26 -1
  155. package/dist/server/metadata-route-response.js +32 -15
  156. package/dist/server/multi-stage.d.ts +52 -11
  157. package/dist/server/multi-stage.js +13 -1
  158. package/dist/server/navigation-planner.js +1 -1
  159. package/dist/server/pages-api-route.js +28 -19
  160. package/dist/server/pages-media-type.d.ts +21 -1
  161. package/dist/server/pages-media-type.js +69 -5
  162. package/dist/server/pages-node-compat.js +52 -27
  163. package/dist/server/pages-page-handler.js +11 -20
  164. package/dist/server/pages-request-pipeline.d.ts +8 -0
  165. package/dist/server/pages-request-pipeline.js +2 -2
  166. package/dist/server/pages-request-stage-entry.js +14 -12
  167. package/dist/server/pages-response-stage-entry.js +9 -3
  168. package/dist/server/prod-server.js +5 -1
  169. package/dist/server/request-pipeline.d.ts +6 -0
  170. package/dist/server/request-pipeline.js +21 -1
  171. package/dist/server/shared-cache-identity.d.ts +23 -0
  172. package/dist/server/shared-cache-identity.js +36 -0
  173. package/dist/server/worker-stages.d.ts +16 -3
  174. package/dist/server/worker-stages.js +23 -4
  175. package/dist/shims/cache-handler.js +2 -2
  176. package/dist/shims/cache-request-state.d.ts +17 -20
  177. package/dist/shims/cache-request-state.js +16 -21
  178. package/dist/shims/cache-runtime.js +27 -11
  179. package/dist/shims/cache.d.ts +8 -7
  180. package/dist/shims/cache.js +17 -19
  181. package/dist/shims/cacheability-classification.d.ts +2 -0
  182. package/dist/shims/cdn-cache.d.ts +22 -5
  183. package/dist/shims/client-page-root.js +2 -2
  184. package/dist/shims/dynamic.js +9 -6
  185. package/dist/shims/error-boundary.js +2 -2
  186. package/dist/shims/fetch-cache-state.d.ts +5 -1
  187. package/dist/shims/fetch-cache-state.js +1 -3
  188. package/dist/shims/fetch-cache.d.ts +2 -1
  189. package/dist/shims/fetch-cache.js +34 -24
  190. package/dist/shims/form.js +2 -2
  191. package/dist/shims/headers.d.ts +8 -23
  192. package/dist/shims/headers.js +17 -67
  193. package/dist/shims/internal/navigation-untracked.js +1 -1
  194. package/dist/shims/link.js +3 -1
  195. package/dist/shims/metadata.d.ts +23 -21
  196. package/dist/shims/metadata.js +62 -24
  197. package/dist/shims/navigation-server.js +1 -1
  198. package/dist/shims/navigation.d.ts +74 -7
  199. package/dist/shims/navigation.js +183 -29
  200. package/dist/shims/navigation.react-server.js +2 -2
  201. package/dist/shims/request-state-types.d.ts +2 -2
  202. package/dist/shims/slot.d.ts +12 -0
  203. package/dist/shims/slot.js +37 -9
  204. package/dist/shims/unified-request-context.d.ts +1 -1
  205. package/dist/shims/unified-request-context.js +2 -3
  206. package/dist/utils/cache-control-metadata.d.ts +5 -0
  207. package/dist/utils/cache-control-metadata.js +9 -1
  208. package/dist/utils/project.d.ts +2 -2
  209. package/dist/utils/project.js +3 -16
  210. package/dist/utils/regex.d.ts +5 -0
  211. package/dist/utils/regex.js +11 -1
  212. package/dist/utils/text-stream.d.ts +10 -5
  213. package/dist/utils/text-stream.js +6 -6
  214. package/package.json +2 -1
  215. package/dist/build/layout-classification-types.d.ts +0 -60
  216. package/dist/build/layout-classification-types.js +0 -1
  217. package/dist/build/layout-classification.d.ts +0 -62
  218. package/dist/build/layout-classification.js +0 -98
  219. package/dist/build/route-classification-injector.d.ts +0 -33
  220. package/dist/build/route-classification-injector.js +0 -59
  221. package/dist/build/route-classification-manifest.d.ts +0 -54
  222. package/dist/build/route-classification-manifest.js +0 -143
  223. package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
  224. package/dist/server/app-browser-client-reuse-manifest.js +0 -101
  225. package/dist/server/app-layout-param-observation.d.ts +0 -42
  226. package/dist/server/app-layout-param-observation.js +0 -168
  227. package/dist/server/client-reuse-manifest.d.ts +0 -103
  228. package/dist/server/client-reuse-manifest.js +0 -209
  229. package/dist/server/skip-cache-proof.d.ts +0 -60
  230. package/dist/server/skip-cache-proof.js +0 -168
  231. package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
  232. package/dist/server/static-layout-client-reuse-proof.js +0 -33
  233. package/dist/utils/sorted-array.d.ts +0 -8
  234. package/dist/utils/sorted-array.js +0 -20
@@ -11,24 +11,24 @@ import { resolveDirectHybridClientRouteOwner } from "./internal/hybrid-client-ro
11
11
  import { isHashOnlyBrowserUrlChange, toCanonicalBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
12
12
  import { disableSmoothScrollDuringRouteTransition } from "./disable-smooth-scroll.js";
13
13
  import { retryScrollTo, scrollToHashTarget } from "./hash-scroll.js";
14
- import { AppElementsWire } from "../server/app-elements-wire.js";
15
- import "../server/app-elements.js";
16
- import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearClientHydrationContext, clearServerInsertedHTML, flushServerInsertedHTML, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getLayoutSegmentContext, getNavigationContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
17
- import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
18
- import { clearAppNavigationFailureTarget, stageAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
19
- import { beginAppRouterScrollIntent, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, isLatestAppRouterScrollIntent } from "./app-router-scroll-state.js";
20
14
  import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, formatRscRequestPath, parseRscRequestPath, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
15
+ import { clearAppNavigationFailureTarget, stageAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
21
16
  import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
22
17
  import { getNavigationRuntime, hasAppNavigationRuntime, loadNavigationRuntimeRouteManifest } from "../client/navigation-runtime.js";
23
18
  import { UnrecognizedActionError, unstable_isUnrecognizedActionError } from "./unrecognized-action-error.js";
19
+ import { AppElementsWire } from "../server/app-elements-wire.js";
20
+ import "../server/app-elements.js";
24
21
  import { PUBLIC_INITIAL_BFCACHE_ID } from "../server/app-bfcache-id.js";
25
22
  import { resolveManifestNavigationInterceptionContext } from "../server/app-browser-interception-context.js";
26
- import { createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, isAppOwnedHistoryState } from "../server/app-history-state.js";
23
+ import { createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, isAppOwnedHistoryState, readHistoryStateTraversalIndex } from "../server/app-history-state.js";
27
24
  import { hasPendingAppRouterPageRedirect } from "../server/app-browser-mpa-navigation.js";
28
25
  import { extractRscCompletionMetadata } from "../server/rsc-completion-metadata.js";
29
26
  import { navigationPlanner } from "../server/navigation-planner.js";
30
27
  import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
28
+ import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
31
29
  import { getPagesNavigationContext } from "./internal/pages-router-accessor.js";
30
+ import { beginAppRouterScrollIntent, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, isLatestAppRouterScrollIntent } from "./app-router-scroll-state.js";
31
+ import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearClientHydrationContext, clearServerInsertedHTML, flushServerInsertedHTML, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getLayoutSegmentContext, getNavigationContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
32
32
  import { cancelAppPrefetchFetch, promoteAppPrefetchFetch, releaseAppPrefetchFetchSlot, scheduleAppPrefetchFetch } from "./internal/app-prefetch-fetch-queue.js";
33
33
  import * as React$1 from "react";
34
34
  //#region src/shims/navigation.ts
@@ -467,9 +467,13 @@ const retainedPrefetchInvalidations = /* @__PURE__ */ new Set();
467
467
  function retainPrefetchInvalidationAfterConsume(entry) {
468
468
  const callbacks = entry.onInvalidateCallbacks;
469
469
  if (callbacks === void 0 || callbacks.size === 0) return;
470
- const delay = Math.max(0, resolvePrefetchCacheEntryExpiresAt(entry) - Date.now());
470
+ retainPrefetchInvalidation(callbacks, resolvePrefetchCacheEntryExpiresAt(entry));
471
+ }
472
+ function retainPrefetchInvalidation(callbacks, expiresAt, forVisitedResponse = false) {
473
+ const delay = Math.max(0, expiresAt - Date.now());
471
474
  const retained = {
472
475
  callbacks,
476
+ ...forVisitedResponse ? { forVisitedResponse: true } : {},
473
477
  timer: setTimeout(() => fireRetainedPrefetchInvalidation(retained), delay)
474
478
  };
475
479
  retainedPrefetchInvalidations.add(retained);
@@ -570,14 +574,37 @@ function attachPrefetchInvalidationCallback(cacheKey, onInvalidate) {
570
574
  if (!entry) return;
571
575
  attachPrefetchInvalidationToEntry(cacheKey, entry, onInvalidate);
572
576
  }
573
- function invalidatePrefetchCache() {
577
+ function invalidatePrefetchCache(options = {}) {
574
578
  cancelPendingPrefetchSetups(null);
575
579
  const cache = getPrefetchCache();
576
580
  const prefetched = getPrefetchedUrls();
577
581
  for (const [cacheKey, entry] of cache) deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, true);
578
582
  prefetched.clear();
579
583
  for (const retained of retainedPrefetchInvalidations) fireRetainedPrefetchInvalidation(retained);
580
- if (!isServer) getNavigationRuntime()?.functions.pingVisibleLinks?.();
584
+ if (!isServer && options.pingVisibleLinks !== false) getNavigationRuntime()?.functions.pingVisibleLinks?.();
585
+ }
586
+ /**
587
+ * Evict the prefetch entries that may hold dynamic data, for a Server Action
588
+ * that called `refresh()`. Like Next.js's dynamic-only revalidation, which
589
+ * evicts its BFCache but keeps its prefetch cache, this keeps route trees,
590
+ * static prefetches and full prefetches. It drops navigation responses, and
591
+ * automatic prefetches whose page rendered dynamically or hasn't finished
592
+ * rendering, including those only kept to learn a route: Next.js's automatic
593
+ * prefetches never hold dynamic data.
594
+ */
595
+ function invalidateDynamicPrefetchCache() {
596
+ const cache = getPrefetchCache();
597
+ const prefetched = getPrefetchedUrls();
598
+ const evicted = [];
599
+ for (const [cacheKey, entry] of cache) if (!(entry.prefetchKind === "route-tree" || entry.prefetchKind !== void 0 && (entry.dynamicStaleTime === "full-prefetch" || entry.snapshot !== void 0 && !isStaleTimeSeconds(entry.snapshot.dynamicStaleTimeSeconds)))) evicted.push([cacheKey, entry]);
600
+ for (const [cacheKey, entry] of evicted) deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, true);
601
+ }
602
+ /**
603
+ * Notify the prefetches that stood in for a visited response (see
604
+ * `hasNavigationFreshVisitedResponse`), as the visited responses are cleared.
605
+ */
606
+ function invalidateVisitedResponsePrefetches() {
607
+ for (const retained of retainedPrefetchInvalidations) if (retained.forVisitedResponse === true) fireRetainedPrefetchInvalidation(retained);
581
608
  }
582
609
  /**
583
610
  * Prevent completed navigation responses from becoming authoritative again
@@ -593,7 +620,7 @@ function disableNavigationResponsePrefetchCacheReuse() {
593
620
  }
594
621
  if (didDemote && !isServer) getNavigationRuntime()?.functions.pingVisibleLinks?.();
595
622
  }
596
- function seedPrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext = null, mountedSlotsHeader = null, fallbackTtlMs = DYNAMIC_NAVIGATION_CACHE_TTL, reuseAfterHistoryRestore = false) {
623
+ function seedPrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext = null, mountedSlotsHeader = null, fallbackTtlMs = DYNAMIC_NAVIGATION_CACHE_TTL, reuseAfterHistoryRestore = false, expiresAt = resolveCachedRscResponseExpiresAt(Date.now(), snapshot, fallbackTtlMs)) {
597
624
  const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
598
625
  const cache = getPrefetchCache();
599
626
  const existing = cache.get(cacheKey);
@@ -602,7 +629,7 @@ function seedPrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext = nu
602
629
  const entry = {
603
630
  cacheForNavigation: true,
604
631
  cacheKeys: /* @__PURE__ */ new Set([cacheKey]),
605
- expiresAt: resolveCachedRscResponseExpiresAt(timestamp, snapshot, fallbackTtlMs),
632
+ expiresAt,
606
633
  mountedSlotsHeader,
607
634
  outcome: "cache-seeded",
608
635
  reuseAfterHistoryRestore,
@@ -616,6 +643,35 @@ function seedPrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext = nu
616
643
  schedulePrefetchInvalidation(cacheKey, entry);
617
644
  evictPrefetchCacheIfNeeded();
618
645
  }
646
+ /**
647
+ * Fulfill a full prefetch from the visited response of an earlier navigation,
648
+ * as Next.js does from its BFCache, instead of issuing a request. The data is
649
+ * fresh for the static stale time from the navigation, not the dynamic one
650
+ * (`attemptToFulfillDynamicSegmentFromBFCache`).
651
+ */
652
+ function seedFullPrefetchFromVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, additionalRscUrls = [], onInvalidate) {
653
+ const visited = getNavigationRuntime()?.functions.readVisitedResponseForFullPrefetch?.([rscUrl, ...additionalRscUrls], interceptionContext, mountedSlotsHeader);
654
+ if (!visited) return false;
655
+ const expiresAt = visited.navigatedAt + Math.max(PREFETCH_CACHE_TTL, MIN_PREFETCH_STALE_TIME_MS);
656
+ if (expiresAt <= Date.now()) return false;
657
+ seedPrefetchResponseSnapshot(rscUrl, visited.response, interceptionContext, mountedSlotsHeader, void 0, true, expiresAt);
658
+ const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
659
+ if (getPrefetchCache().get(cacheKey)?.snapshot !== visited.response) return false;
660
+ attachPrefetchInvalidationCallback(cacheKey, onInvalidate);
661
+ return true;
662
+ }
663
+ /**
664
+ * Whether a navigation to the URL would reuse the response of an earlier one,
665
+ * so a prefetch has nothing to fetch. Like Next.js, whose navigation keeps the
666
+ * route and its segments for `staleTimes.dynamic`. `onInvalidate` fires when
667
+ * that reuse ends.
668
+ */
669
+ function hasNavigationFreshVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, additionalRscUrls = [], onInvalidate) {
670
+ const freshUntil = getNavigationRuntime()?.functions.readVisitedResponseForFullPrefetch?.([rscUrl, ...additionalRscUrls], interceptionContext, mountedSlotsHeader)?.navigationFreshUntil;
671
+ if (freshUntil === void 0 || freshUntil === null) return false;
672
+ if (onInvalidate !== void 0) retainPrefetchInvalidation(/* @__PURE__ */ new Set([onInvalidate]), freshUntil, true);
673
+ return true;
674
+ }
619
675
  function deletePrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext = null) {
620
676
  const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
621
677
  const cache = getPrefetchCache();
@@ -694,6 +750,7 @@ function createCachedRscResponseSnapshot(response, buffer, responseUrl = null) {
694
750
  ...dynamicStaleTimeSeconds !== void 0 ? { dynamicStaleTimeSeconds } : {},
695
751
  mountedSlotsHeader: response.headers.get(VINEXT_MOUNTED_SLOTS_HEADER),
696
752
  paramsHeader: response.headers.get(VINEXT_PARAMS_HEADER),
753
+ receivedAt: Date.now(),
697
754
  ...redirectHeader === null ? {} : { redirectHeader },
698
755
  ...redirectTypeHeader === null ? {} : { redirectTypeHeader },
699
756
  renderedPathAndSearch: parseRenderedPathAndSearchHeader(response.headers.get(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER)),
@@ -862,7 +919,7 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
862
919
  if (behavior.dynamicStaleTime === "learning-only" && behavior.searchAgnosticShell !== true) {
863
920
  entry.dynamicStaleTime = "learning-only";
864
921
  entry.fallbackTtlMs = behavior.fallbackTtlMs ?? PREFETCH_CACHE_TTL;
865
- }
922
+ } else if (behavior.dynamicStaleTime === "full-prefetch") entry.dynamicStaleTime = "full-prefetch";
866
923
  addPrefetchInvalidationCallback(entry, options?.onInvalidate);
867
924
  entry.fetchPromise = fetchPromise;
868
925
  entry.pending = fetchPromise.then(async (response) => {
@@ -1022,6 +1079,8 @@ function getClientNavigationState() {
1022
1079
  originalPushState: window.history.pushState.bind(window.history),
1023
1080
  originalReplaceState: window.history.replaceState.bind(window.history),
1024
1081
  patchInstalled: false,
1082
+ routerHistoryWriteDepth: 0,
1083
+ routerHistoryWrite: null,
1025
1084
  hasPendingNavigationUpdate: false,
1026
1085
  suppressUrlNotifyCount: 0,
1027
1086
  navigationSnapshotActiveCount: 0
@@ -1365,16 +1424,80 @@ function commitClientNavigationState(navId, options) {
1365
1424
  if (urlChanged || paramsChanged) clearClientHydrationContext();
1366
1425
  if (shouldNotify) notifyNavigationListeners();
1367
1426
  }
1368
- function pushHistoryStateWithoutNotify(data, unused, url) {
1369
- withSuppressedUrlNotifications(() => {
1370
- getClientNavigationState()?.originalPushState.call(window.history, data, unused, url);
1371
- });
1427
+ /** Whether a history entry's state is the data written to it, cloned by the browser. */
1428
+ function isSameHistoryStateData(historyState, data) {
1429
+ try {
1430
+ return JSON.stringify(historyState) === JSON.stringify(data);
1431
+ } catch {
1432
+ return false;
1433
+ }
1434
+ }
1435
+ /** Writes the in-progress router write if this call is it, consuming its marker. */
1436
+ function forwardRouterHistoryWrite(state, method, data, unused, url) {
1437
+ const write = state.routerHistoryWrite;
1438
+ if (write?.method !== method) return false;
1439
+ if (write.threw) {
1440
+ if (url == null || new URL(url, window.location.href).href !== write.href) return false;
1441
+ if (write.data !== data && !(isAppOwnedHistoryState(data) && readHistoryStateTraversalIndex(data) === readHistoryStateTraversalIndex(write.data))) return false;
1442
+ } else if (write.data !== data || write.url !== url) return false;
1443
+ if (write.landed) return true;
1444
+ state.routerHistoryWrite = null;
1445
+ const landing = write.land?.(data);
1446
+ const original = method === "pushState" ? state.originalPushState : state.originalReplaceState;
1447
+ const writtenData = landing ? landing.data : data;
1448
+ const historyStateBeforeWrite = window.history.state;
1449
+ try {
1450
+ original.call(window.history, writtenData, unused, url);
1451
+ } catch (error) {
1452
+ const landed = window.history.state !== historyStateBeforeWrite && window.location.href === write.href && isSameHistoryStateData(window.history.state, writtenData);
1453
+ if (landed) landing?.commit();
1454
+ state.routerHistoryWrite = {
1455
+ ...write,
1456
+ threw: true,
1457
+ landed
1458
+ };
1459
+ throw error;
1460
+ }
1461
+ landing?.commit();
1462
+ if (write.threw) state.routerHistoryWrite = {
1463
+ ...write,
1464
+ landed: true
1465
+ };
1466
+ return true;
1372
1467
  }
1373
- function replaceHistoryStateWithoutNotify(data, unused, url) {
1468
+ function writeRouterHistoryState(method, data, unused, url, land) {
1374
1469
  withSuppressedUrlNotifications(() => {
1375
- getClientNavigationState()?.originalReplaceState.call(window.history, data, unused, url);
1470
+ const state = getClientNavigationState();
1471
+ if (!state) return;
1472
+ if (url == null) {
1473
+ (method === "pushState" ? state.originalPushState : state.originalReplaceState).call(window.history, data, unused, url);
1474
+ return;
1475
+ }
1476
+ const previousWrite = state.routerHistoryWrite;
1477
+ state.routerHistoryWriteDepth += 1;
1478
+ state.routerHistoryWrite = {
1479
+ method,
1480
+ data,
1481
+ url,
1482
+ href: new URL(url, window.location.href).href,
1483
+ land,
1484
+ threw: false,
1485
+ landed: false
1486
+ };
1487
+ try {
1488
+ window.history[method](data, unused, url);
1489
+ } finally {
1490
+ state.routerHistoryWriteDepth -= 1;
1491
+ state.routerHistoryWrite = previousWrite;
1492
+ }
1376
1493
  });
1377
1494
  }
1495
+ function pushHistoryStateWithoutNotify(data, unused, url, land) {
1496
+ writeRouterHistoryState("pushState", data, unused, url, land);
1497
+ }
1498
+ function replaceHistoryStateWithoutNotify(data, unused, url, land) {
1499
+ writeRouterHistoryState("replaceState", data, unused, url, land);
1500
+ }
1378
1501
  /**
1379
1502
  * Save the current scroll position into the current history state.
1380
1503
  * Called before every navigation to enable scroll restoration on back/forward.
@@ -1590,6 +1713,32 @@ function hasScheduledAppRouterNavigation() {
1590
1713
  function releaseScheduledAppRouterNavigationAfterCurrentTask(release) {
1591
1714
  queueMicrotask(release);
1592
1715
  }
1716
+ let inFlightAppRouterNavigationCount = 0;
1717
+ let visibleLinkPingAwaitsNavigations = false;
1718
+ /**
1719
+ * Called by the App Router browser entry for each RSC navigation it runs.
1720
+ * Returns a release callback for the navigation's settlement.
1721
+ */
1722
+ function trackAppRouterNavigationInFlight() {
1723
+ inFlightAppRouterNavigationCount += 1;
1724
+ let released = false;
1725
+ return () => {
1726
+ if (released) return;
1727
+ released = true;
1728
+ inFlightAppRouterNavigationCount = Math.max(0, inFlightAppRouterNavigationCount - 1);
1729
+ if (inFlightAppRouterNavigationCount === 0 && visibleLinkPingAwaitsNavigations) {
1730
+ visibleLinkPingAwaitsNavigations = false;
1731
+ getNavigationRuntime()?.functions.pingVisibleLinks?.();
1732
+ }
1733
+ };
1734
+ }
1735
+ function pingVisibleLinksOnceNavigationsSettle() {
1736
+ if (inFlightAppRouterNavigationCount > 0) {
1737
+ visibleLinkPingAwaitsNavigations = true;
1738
+ return;
1739
+ }
1740
+ getNavigationRuntime()?.functions.pingVisibleLinks?.();
1741
+ }
1593
1742
  /**
1594
1743
  * App Router public router instance. Mirrors Next.js's
1595
1744
  * `publicAppRouterInstance` from
@@ -1641,15 +1790,16 @@ const _appRouter = {
1641
1790
  },
1642
1791
  refresh() {
1643
1792
  if (isServer) return;
1644
- getNavigationRuntime()?.functions.clearNavigationCaches?.();
1645
- if (hasScheduledAppRouterNavigation()) return;
1793
+ getNavigationRuntime()?.functions.clearNavigationCaches?.({ pingVisibleLinks: false });
1646
1794
  const rscNavigate = getNavigationRuntime()?.functions.navigate;
1647
- if (rscNavigate) {
1648
- const navigate = () => {
1649
- rscNavigate(window.location.href, 0, "refresh", void 0, void 0, true);
1650
- };
1651
- React$1.startTransition(navigate);
1795
+ if (hasScheduledAppRouterNavigation() || !rscNavigate) {
1796
+ getNavigationRuntime()?.functions.pingVisibleLinks?.();
1797
+ return;
1652
1798
  }
1799
+ const navigate = () => {
1800
+ rscNavigate(window.location.href, 0, "refresh", void 0, void 0, true).finally(pingVisibleLinksOnceNavigationsSettle);
1801
+ };
1802
+ React$1.startTransition(navigate);
1653
1803
  },
1654
1804
  prefetch(href, options) {
1655
1805
  assertSafeNavigationUrl(href);
@@ -1720,7 +1870,9 @@ const _appRouter = {
1720
1870
  onInvalidate: options?.onInvalidate,
1721
1871
  onReuse: policy.dynamicStaleTime === "full-prefetch" ? (entry, matchedCacheKey) => promotePrefetchCacheEntryForNavigation(matchedCacheKey, entry) : void 0
1722
1872
  })) return;
1873
+ if (policy.dynamicStaleTime === "full-prefetch" && seedFullPrefetchFromVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, additionalRscUrls, options?.onInvalidate)) return;
1723
1874
  }
1875
+ if (policy.dynamicStaleTime !== "full-prefetch" && hasNavigationFreshVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, additionalRscUrls, options?.onInvalidate)) return;
1724
1876
  prefetched.add(cacheKey);
1725
1877
  const fetchFullRscPayload = () => scheduleAppPrefetchFetch((signal) => fetch(rscUrl, {
1726
1878
  headers,
@@ -1878,7 +2030,8 @@ if (!isServer) {
1878
2030
  }
1879
2031
  });
1880
2032
  window.history.pushState = function patchedPushState(data, unused, url) {
1881
- getNavigationRuntime()?.functions.flushCommittingNavigationUrl?.();
2033
+ if (forwardRouterHistoryWrite(state, "pushState", data, unused, url)) return;
2034
+ if (state.routerHistoryWriteDepth === 0) getNavigationRuntime()?.functions.flushCommittingNavigationUrl?.();
1882
2035
  if (isAppOwnedHistoryState(data)) {
1883
2036
  const previousHistoryState = window.history.state;
1884
2037
  state.originalPushState.call(window.history, data, unused, url);
@@ -1895,7 +2048,8 @@ if (!isServer) {
1895
2048
  }
1896
2049
  };
1897
2050
  window.history.replaceState = function patchedReplaceState(data, unused, url) {
1898
- getNavigationRuntime()?.functions.flushCommittingNavigationUrl?.();
2051
+ if (forwardRouterHistoryWrite(state, "replaceState", data, unused, url)) return;
2052
+ if (state.routerHistoryWriteDepth === 0) getNavigationRuntime()?.functions.flushCommittingNavigationUrl?.();
1899
2053
  if (isAppOwnedHistoryState(data)) {
1900
2054
  const previousHistoryState = window.history.state;
1901
2055
  state.originalReplaceState.call(window.history, data, unused, url);
@@ -1914,4 +2068,4 @@ if (!isServer) {
1914
2068
  }
1915
2069
  }
1916
2070
  //#endregion
1917
- export { BailoutToCSRError, DYNAMIC_NAVIGATION_CACHE_TTL, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, PREFETCH_CACHE_TTL, ReadonlyURLSearchParams, RedirectType, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, applyAppRouterScrollFallback, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createAppPrefetchRequestHeaders, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, deletePrefetchResponseSnapshot, disableNavigationResponsePrefetchCacheReuse, discardLearningOnlyPrefetchCacheEntry, fetchRouteTreeGatedPrefetch, flushServerInsertedHTML, forbidden, getAccessFallbackHTTPStatus, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getClientNavigationRenderContext, getClientNavigationState, getClientParams, getCurrentInterceptionContext, getCurrentNextUrl, getFreshPrefetchCacheEntry, getLayoutSegmentContext, getMountedSlotsHeader, getNavigationContext, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasFreshLearningOnlyPrefetchCacheEntry, hasPrefetchCacheEntryForNavigation, hasSearchAgnosticPrefetchShellForRoute, invalidatePrefetchCache, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, navigateClientSide, notFound, parseRenderedPathAndSearchHeader, peekPrefetchResponseForNavigation, permanentRedirect, prefetchRscResponse, preloadHybridClientRouteOwner, prepareNavigationPrefetchSnapshot, promotePrefetchCacheEntryForNavigation, pushHistoryStateWithoutNotify, redirect, renderServerInsertedHTML, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveCachedRscResponseExpiresAt, resolveCachedRscResponseTtlMs, resolveLoadedHybridClientRewriteHref, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useClientNavigationRenderSnapshot, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
2071
+ export { BailoutToCSRError, DYNAMIC_NAVIGATION_CACHE_TTL, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, PREFETCH_CACHE_TTL, ReadonlyURLSearchParams, RedirectType, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, applyAppRouterScrollFallback, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createAppPrefetchRequestHeaders, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, deletePrefetchResponseSnapshot, disableNavigationResponsePrefetchCacheReuse, discardLearningOnlyPrefetchCacheEntry, fetchRouteTreeGatedPrefetch, flushServerInsertedHTML, forbidden, getAccessFallbackHTTPStatus, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getClientNavigationRenderContext, getClientNavigationState, getClientParams, getCurrentInterceptionContext, getCurrentNextUrl, getFreshPrefetchCacheEntry, getLayoutSegmentContext, getMountedSlotsHeader, getNavigationContext, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasFreshLearningOnlyPrefetchCacheEntry, hasNavigationFreshVisitedResponse, hasPrefetchCacheEntryForNavigation, hasSearchAgnosticPrefetchShellForRoute, invalidateDynamicPrefetchCache, invalidatePrefetchCache, invalidateVisitedResponsePrefetches, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, navigateClientSide, notFound, parseRenderedPathAndSearchHeader, peekPrefetchResponseForNavigation, permanentRedirect, prefetchRscResponse, preloadHybridClientRouteOwner, prepareNavigationPrefetchSnapshot, promotePrefetchCacheEntryForNavigation, pushHistoryStateWithoutNotify, redirect, renderServerInsertedHTML, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveCachedRscResponseExpiresAt, resolveCachedRscResponseTtlMs, resolveLoadedHybridClientRewriteHref, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedFullPrefetchFromVisitedResponse, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, trackAppRouterNavigationInFlight, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useClientNavigationRenderSnapshot, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
@@ -1,7 +1,7 @@
1
- import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearServerInsertedHTML, flushServerInsertedHTML, getLayoutSegmentContext, getNavigationContext, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
1
+ import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
2
2
  import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
3
+ import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearServerInsertedHTML, flushServerInsertedHTML, getLayoutSegmentContext, getNavigationContext, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
3
4
  import "./navigation-server.js";
4
- import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
5
5
  import { throwClientHookError } from "./client-hook-error.js";
6
6
  //#region src/shims/navigation.react-server.ts
7
7
  function usePathname() {
@@ -1,12 +1,12 @@
1
- import { ExecutionContextLike } from "./request-context.js";
2
1
  import { NavigationContext } from "./navigation-context-state.js";
3
2
  import "./navigation.js";
4
- import { CacheLifeConfig, CacheState } from "./cache-request-state.js";
3
+ import { ExecutionContextLike } from "./request-context.js";
5
4
  import { RootParamsState } from "./root-params.js";
6
5
  import { FetchCacheState } from "./fetch-cache-state.js";
7
6
  import "./fetch-cache.js";
8
7
  import { HeadersAccessPhase, VinextHeadersShimState } from "./internal/headers-state.js";
9
8
  import { HeadersContext } from "./headers.js";
9
+ import { CacheLifeConfig, CacheState } from "./cache-request-state.js";
10
10
  import { RouterState, SSRContext } from "./router-state.js";
11
11
  import { PrivateCacheState } from "./cache-runtime.js";
12
12
  import { HeadState } from "./head-state.js";
@@ -59,6 +59,18 @@ export declare function BfcacheSegmentBoundary({ children, id, stateKey }: {
59
59
  id: string;
60
60
  stateKey: string;
61
61
  }): React$1.JSX.Element;
62
+ /**
63
+ * Retains a layout's children across navigations that change which segment
64
+ * they render. Each child keeps its own wrappers, so a page and a nested layout
65
+ * give the layout's children different element shapes, and a retention list
66
+ * inside the child would remount with them. Next.js keeps this Activity list in
67
+ * the parent's layout router, above the child's boundaries, so a page left for a
68
+ * sibling with its own layout keeps its state when navigating back.
69
+ */
70
+ export declare function BfcacheChildrenBoundary({ children, id }: {
71
+ children: React$1.ReactNode;
72
+ id: string;
73
+ }): React$1.JSX.Element;
62
74
  export declare function getNonCacheComponentsSegmentKey(id: string, activeStateKey: string): string | undefined;
63
75
  export declare function resolveBfcacheSegmentStateKey(id: string, identityMap: Readonly<Record<string, string>>, bfcacheIdMap: Readonly<Record<string, string>> | null): string | undefined;
64
76
  export declare function mergeElements(prev: AppElements, next: AppElements, options?: MergeElementsOptions | boolean): AppElements;
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import { APP_BFCACHE_SEGMENT_IDENTITIES_KEY, AppElementsWire, UNMATCHED_SLOT } from "../server/app-elements-wire.js";
3
3
  import "../server/app-elements.js";
4
- import { getBfcacheIdMapContext, getBfcacheSegmentIdContext } from "./navigation-context-state.js";
4
+ import { isNestedBfcacheSlotSegmentId, isNestedBfcacheSlotSegmentIdFor } from "../server/bfcache-identity.js";
5
5
  import { notFound } from "./navigation-errors.js";
6
+ import { getBfcacheIdMapContext, getBfcacheSegmentIdContext } from "./navigation-context-state.js";
6
7
  import "./navigation-server.js";
7
- import { isNestedBfcacheSlotSegmentId, isNestedBfcacheSlotSegmentIdFor } from "../server/bfcache-identity.js";
8
8
  import * as React$1 from "react";
9
9
  import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
10
10
  //#region src/shims/slot.tsx
@@ -92,11 +92,6 @@ function stageBfcacheSlotEntryForRender(committedSnapshots, committedOrder, acti
92
92
  snapshots
93
93
  };
94
94
  }
95
- function isLayoutFlagsValue(value) {
96
- if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
97
- const entries = Object.values(value);
98
- return entries.length > 0 && entries.every((entry) => entry === "s" || entry === "d");
99
- }
100
95
  function isArtifactCompatibilityEnvelopeValue(value) {
101
96
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
102
97
  return "schemaVersion" in value && "appElementsSchemaVersion" in value && "rscPayloadSchemaVersion" in value && "graphVersion" in value && "deploymentVersion" in value && "rootBoundaryId" in value && "renderEpoch" in value;
@@ -127,7 +122,7 @@ function isCacheEntryReuseProofValue(value) {
127
122
  return "kind" in value && value.kind === "runtime-cache-entry" && "decision" in value;
128
123
  }
129
124
  function isTransportMetadataValue(id, value) {
130
- return isLayoutFlagsValue(value) || isBfcacheSegmentIdentitiesMetadataValue(id, value) || isArtifactCompatibilityEnvelopeValue(value) || isCacheEntryReuseProofValue(value) || isInterceptionMetadataValue(value) || isSkippedLayoutIdsMetadataValue(id, value) || isSlotBindingListValue(value);
125
+ return isBfcacheSegmentIdentitiesMetadataValue(id, value) || isArtifactCompatibilityEnvelopeValue(value) || isCacheEntryReuseProofValue(value) || isInterceptionMetadataValue(value) || isSkippedLayoutIdsMetadataValue(id, value) || isSlotBindingListValue(value);
131
126
  }
132
127
  function warnTransportMetadataEntry(id) {
133
128
  if (process.env.NODE_ENV === "production") return;
@@ -210,6 +205,39 @@ function BfcacheSegmentBoundary({ children, id, stateKey }) {
210
205
  stateKeyMap: identityMap
211
206
  });
212
207
  }
208
+ /**
209
+ * Retains a layout's children across navigations that change which segment
210
+ * they render. Each child keeps its own wrappers, so a page and a nested layout
211
+ * give the layout's children different element shapes, and a retention list
212
+ * inside the child would remount with them. Next.js keeps this Activity list in
213
+ * the parent's layout router, above the child's boundaries, so a page left for a
214
+ * sibling with its own layout keeps its state when navigating back.
215
+ */
216
+ function BfcacheChildrenBoundary({ children, id }) {
217
+ if (!BfcacheIdMapContext || !BfcacheSegmentIdContext || !isCacheComponentsEnabled()) return /* @__PURE__ */ jsx(Fragment$1, { children });
218
+ return /* @__PURE__ */ jsx(BfcacheChildrenActivityBoundary, {
219
+ id,
220
+ IdMapContext: BfcacheIdMapContext,
221
+ SegmentContext: BfcacheSegmentIdContext,
222
+ children
223
+ });
224
+ }
225
+ function BfcacheChildrenActivityBoundary({ children, id, IdMapContext, SegmentContext }) {
226
+ const elements = React$1.useContext(ElementsContext);
227
+ const identityMap = React$1.useContext(BfcacheIdentityMapContext);
228
+ const bfcacheIdMap = React$1.useContext(IdMapContext);
229
+ const segmentId = React$1.useContext(SegmentContext);
230
+ const activeStateKey = resolveBfcacheSegmentStateKey(id, identityMap, bfcacheIdMap);
231
+ if (segmentId === null || activeStateKey === void 0) return /* @__PURE__ */ jsx(Fragment$1, { children });
232
+ return /* @__PURE__ */ jsx(BfcacheActivitySlotBoundary, {
233
+ activeStateKey,
234
+ content: children,
235
+ elements,
236
+ id: segmentId,
237
+ SegmentContext,
238
+ stateKeyMap: identityMap
239
+ });
240
+ }
213
241
  function getNonCacheComponentsSegmentKey(id, activeStateKey) {
214
242
  const parsed = AppElementsWire.parseElementKey(id);
215
243
  return parsed !== null && parsed.kind !== "route" ? activeStateKey : void 0;
@@ -340,4 +368,4 @@ function ParallelSlot({ name }) {
340
368
  return React$1.useContext(ParallelSlotsContext)?.[name] ?? null;
341
369
  }
342
370
  //#endregion
343
- export { BfcacheIdentityMapContext, BfcacheSegmentBoundary, Children, ChildrenContext, ElementsContext, ParallelSlot, ParallelSlotsContext, RenderedSearchContext, Slot, UNMATCHED_SLOT, bindAppElementsRenderedSearch, getNonCacheComponentsSegmentKey, mergeElements, resolveBfcacheSegmentStateKey, setAppElementsRenderedSearch, stageBfcacheSlotEntryForRender, updateBfcacheSlotEntryOrder };
371
+ export { BfcacheChildrenBoundary, BfcacheIdentityMapContext, BfcacheSegmentBoundary, Children, ChildrenContext, ElementsContext, ParallelSlot, ParallelSlotsContext, RenderedSearchContext, Slot, UNMATCHED_SLOT, bindAppElementsRenderedSearch, getNonCacheComponentsSegmentKey, mergeElements, resolveBfcacheSegmentStateKey, setAppElementsRenderedSearch, stageBfcacheSlotEntryForRender, updateBfcacheSlotEntryOrder };
@@ -1,8 +1,8 @@
1
1
  import { ExecutionContextLike } from "./request-context.js";
2
- import { CacheState } from "./cache-request-state.js";
3
2
  import { RootParamsState } from "./root-params.js";
4
3
  import { FetchCacheState } from "./fetch-cache-state.js";
5
4
  import { VinextHeadersShimState } from "./internal/headers-state.js";
5
+ import { CacheState } from "./cache-request-state.js";
6
6
  import { RouterState } from "./router-state.js";
7
7
  import { markFullyBufferedBody, preserveFullyBufferedBodyMetadata } from "../server/fully-buffered-response.js";
8
8
  import { PrivateCacheState } from "./cache-runtime.js";
@@ -18,7 +18,7 @@ function createRequestContext(opts) {
18
18
  return {
19
19
  headersContext: null,
20
20
  actionRevalidationKind: 0,
21
- cacheLifeSink: null,
21
+ isOnDemandRevalidate: false,
22
22
  pendingCdnTagInvalidations: [],
23
23
  pendingRevalidatedTags: /* @__PURE__ */ new Set(),
24
24
  pendingRevalidations: /* @__PURE__ */ new Set(),
@@ -37,15 +37,14 @@ function createRequestContext(opts) {
37
37
  serverContext: null,
38
38
  serverInsertedHTMLCallbacks: [],
39
39
  requestScopedCacheLife: null,
40
- unstableCacheObservations: /* @__PURE__ */ new Map(),
41
40
  unstableCacheRevalidation: "foreground",
42
41
  _privateCache: null,
43
- cacheableFetchUrls: /* @__PURE__ */ new Set(),
44
42
  currentRequestTags: [],
45
43
  currentFetchSoftTags: [],
46
44
  currentFetchCacheMode: null,
47
45
  currentFetchRevalidate: null,
48
46
  currentForceDynamicFetchDefault: false,
47
+ isDraftMode: false,
49
48
  dynamicFetchUrls: /* @__PURE__ */ new Set(),
50
49
  refreshStaleFetchesInForeground: false,
51
50
  isFetchDedupeActive: false,
@@ -1,5 +1,10 @@
1
1
  //#region src/utils/cache-control-metadata.d.ts
2
2
  export declare function readCacheControlNumberField(ctx: Record<string, unknown> | undefined, field: string): number | undefined;
3
+ /**
4
+ * When a `"use cache"` entry's generation started (`ctx.timestamp`), which dates
5
+ * the entry like Next.js does. Absent, malformed or future values fall back to `now`.
6
+ */
7
+ export declare function readCacheTimestamp(ctx: Record<string, unknown> | undefined, now: number): number;
3
8
  export declare function readCacheControlRevalidateField(ctx: Record<string, unknown> | undefined): number | false | undefined;
4
9
  /**
5
10
  * Client-reuse seconds from a resolved `cacheLife`. Shared by every emitter
@@ -8,6 +8,14 @@ function readCacheControlNumberField(ctx, field) {
8
8
  const value = readRecordField(ctx, "cacheControl")?.[field] ?? ctx?.[field];
9
9
  return typeof value === "number" ? value : void 0;
10
10
  }
11
+ /**
12
+ * When a `"use cache"` entry's generation started (`ctx.timestamp`), which dates
13
+ * the entry like Next.js does. Absent, malformed or future values fall back to `now`.
14
+ */
15
+ function readCacheTimestamp(ctx, now) {
16
+ const value = ctx?.timestamp;
17
+ return typeof value === "number" && Number.isFinite(value) && value > 0 && value <= now ? value : now;
18
+ }
11
19
  function readCacheControlRevalidateField(ctx) {
12
20
  const value = readRecordField(ctx, "cacheControl")?.revalidate ?? ctx?.revalidate;
13
21
  return typeof value === "number" || value === false ? value : void 0;
@@ -29,4 +37,4 @@ function resolveClientStaleTimeSeconds(cacheLife) {
29
37
  return isFiniteNonNegative(stale) ? stale : void 0;
30
38
  }
31
39
  //#endregion
32
- export { readCacheControlNumberField, readCacheControlRevalidateField, resolveClientStaleTimeSeconds };
40
+ export { readCacheControlNumberField, readCacheControlRevalidateField, readCacheTimestamp, resolveClientStaleTimeSeconds };
@@ -58,6 +58,8 @@ export declare function findViteConfigPath(root: string): string | undefined;
58
58
  export declare function formatMissingCloudflarePluginError(options: {
59
59
  isAppRouter: boolean;
60
60
  configFile?: string;
61
+ /** False when configFile is not the root vite.config.* that `vinext init` updates. */
62
+ initUpdatesConfig?: boolean;
61
63
  }): string;
62
64
  export type ProjectInfo = {
63
65
  root: string;
@@ -78,8 +80,6 @@ export type ProjectInfo = {
78
80
  hasMDX: boolean;
79
81
  /** CodeHike is a dependency */
80
82
  hasCodeHike: boolean;
81
- /** Native Node modules that need stubbing for Workers */
82
- nativeModulesToStub: string[];
83
83
  };
84
84
  /** Check whether a wrangler config file exists in the given directory. */
85
85
  export declare function hasWranglerConfig(root: string): boolean;
@@ -196,7 +196,7 @@ function findViteConfigPath(root) {
196
196
  function formatMissingCloudflarePluginError(options) {
197
197
  const cfArg = options.isAppRouter ? "{\n viteEnvironment: { name: \"rsc\", childEnvironments: [\"ssr\"] },\n }" : "";
198
198
  const configRef = options.configFile ? options.configFile : "your Vite config";
199
- return `[vinext] Missing @cloudflare/vite-plugin in ${configRef}.\n\n Cloudflare Workers builds require the cloudflare() plugin.\n Run \`vinext init --platform=cloudflare\` to update ${configRef}.\n\n Expected plugin shape:\n\n cloudflare(${cfArg})`;
199
+ return `[vinext] Missing @cloudflare/vite-plugin in ${configRef}.\n\n Cloudflare Workers builds require the cloudflare() plugin.\n ${options.initUpdatesConfig === false ? `Add it to ${configRef}.` : `Run \`vinext init --platform=cloudflare\` to update ${configRef}.`}\n\n Expected plugin shape:\n\n cloudflare(${cfArg})`;
200
200
  }
201
201
  /** Check whether a wrangler config file exists in the given directory. */
202
202
  function hasWranglerConfig(root) {
@@ -251,12 +251,10 @@ function detectProject(root) {
251
251
  }
252
252
  }
253
253
  hasISR = hasISR || detectCacheComponents(root);
254
- const allDeps = {
254
+ const hasCodeHike = "codehike" in {
255
255
  ...pkg?.dependencies,
256
256
  ...pkg?.devDependencies
257
257
  };
258
- const hasCodeHike = "codehike" in allDeps;
259
- const nativeModulesToStub = detectNativeModules(allDeps);
260
258
  return {
261
259
  root,
262
260
  isAppRouter,
@@ -271,8 +269,7 @@ function detectProject(root) {
271
269
  hasISR,
272
270
  hasTypeModule,
273
271
  hasMDX,
274
- hasCodeHike,
275
- nativeModulesToStub
272
+ hasCodeHike
276
273
  };
277
274
  }
278
275
  const ISR_PATTERN = /export\s+(?:const\s+revalidate\s*=|(?:async\s+)?function\s+getStaticProps\b|const\s+getStaticProps\s*=|\{[^}]*\bgetStaticProps\b[^}]*\})/;
@@ -357,16 +354,6 @@ function detectCacheComponents(root) {
357
354
  }
358
355
  return false;
359
356
  }
360
- const NATIVE_MODULES_TO_STUB = [
361
- "@resvg/resvg-js",
362
- "satori",
363
- "lightningcss",
364
- "@napi-rs/canvas",
365
- "sharp"
366
- ];
367
- function detectNativeModules(allDeps) {
368
- return NATIVE_MODULES_TO_STUB.filter((mod) => mod in allDeps);
369
- }
370
357
  /**
371
358
  * Check if a package is resolvable from a given root directory using Node's
372
359
  * module resolution. Handles hoisting, pnpm symlinks, monorepos, and Yarn PnP.
@@ -1,3 +1,8 @@
1
1
  //#region src/utils/regex.d.ts
2
2
  export declare function escapeRegExp(value: string): string;
3
+ /**
4
+ * Return the literal a RegExp matches when it is just `^literal$` (as built
5
+ * from `escapeRegExp`), or null for any other pattern.
6
+ */
7
+ export declare function exactRegExpLiteral(pattern: RegExp): string | null;
3
8
  //#endregion
@@ -2,5 +2,15 @@
2
2
  function escapeRegExp(value) {
3
3
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4
4
  }
5
+ const EXACT_REGEXP_SOURCE_RE = /^\^((?:\\[.*+?^${}()|[\]\\/]|[^.*+?^${}()|[\]\\])*)\$$/;
6
+ /**
7
+ * Return the literal a RegExp matches when it is just `^literal$` (as built
8
+ * from `escapeRegExp`), or null for any other pattern.
9
+ */
10
+ function exactRegExpLiteral(pattern) {
11
+ if (pattern.flags !== "") return null;
12
+ const body = EXACT_REGEXP_SOURCE_RE.exec(pattern.source)?.[1];
13
+ return body === void 0 ? null : body.replace(/\\(.)/g, "$1");
14
+ }
5
15
  //#endregion
6
- export { escapeRegExp };
16
+ export { escapeRegExp, exactRegExpLiteral };