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
@@ -1,9 +1,9 @@
1
1
  import { stripBasePath } from "../utils/base-path.js";
2
2
  import { withBasePath } from "../shims/url-utils.js";
3
3
  import { clearAppNavigationFailureTarget, getAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
4
- import { claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
5
4
  import { resolveServerActionOperationLane, shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
6
5
  import { resolveActiveRoutePaths } from "./app-history-state.js";
6
+ import { claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
7
7
  import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
8
8
  import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, createPendingNavigationCommit, createPendingNavigationCommitFromElements } from "./app-browser-state.js";
9
9
  import { applyApprovedVisibleCommit, approveHmrVisibleCommit, approvePendingNavigationCommit, resolveAndClassifyNavigationCommit } from "./app-browser-visible-commit.js";
@@ -408,7 +408,6 @@ function createAppBrowserNavigationController(deps = {}) {
408
408
  elements: options.restoredState.elements,
409
409
  interception: options.restoredState.interception,
410
410
  interceptionContext: options.restoredState.interceptionContext,
411
- layoutFlags: options.restoredState.layoutFlags,
412
411
  layoutIds: options.restoredState.layoutIds,
413
412
  navigationSnapshot: options.restoredState.navigationSnapshot,
414
413
  operation,
@@ -13,8 +13,7 @@ function toVisibleAppHref(href, origin) {
13
13
  stripRscCacheBustingSearchParam(url);
14
14
  return `${stripRscSuffix(url.pathname)}${url.search}${url.hash}`;
15
15
  }
16
- function toStreamedRedirectVisibleAppHref(href, origin) {
17
- const url = new URL(href, origin);
16
+ function toStreamedRedirectVisibleAppHref(url) {
18
17
  return `${url.pathname}${url.search}${url.hash}`;
19
18
  }
20
19
  function resolveRedirectLifecycleHopFromTarget(options) {
@@ -53,10 +52,11 @@ function resolveRscRedirectLifecycleHop(options) {
53
52
  });
54
53
  }
55
54
  function resolveStreamedRscRedirectLifecycleHop(options) {
56
- const streamedRedirectUrl = new URL(options.streamedRedirectTarget, options.origin);
55
+ const requestedUrl = new URL(options.currentHref, options.origin);
56
+ const streamedRedirectUrl = new URL(options.streamedRedirectTarget, requestedUrl);
57
57
  return resolveRedirectLifecycleHopFromTarget({
58
58
  ...options,
59
- redirectedHref: toStreamedRedirectVisibleAppHref(options.streamedRedirectTarget, options.origin),
59
+ redirectedHref: toStreamedRedirectVisibleAppHref(streamedRedirectUrl),
60
60
  targetUrl: streamedRedirectUrl
61
61
  });
62
62
  }
@@ -21,6 +21,8 @@ type ActionRedirectTarget = {
21
21
  export type ClientServerActionDeps = {
22
22
  basePath: string;
23
23
  clearClientNavigationCaches(): void;
24
+ /** Evict only the cached navigation data that may be dynamic. */
25
+ clearDynamicClientNavigationCaches(): void;
24
26
  clientRscCompatibilityId: string | null;
25
27
  commitSameUrlNavigatePayload(elements: Promise<AppElements>, actionInitiation: ClientServerActionInitiation, returnValue: ServerActionResult["returnValue"] | undefined, revalidation: ServerActionRevalidationKind, renderedPathAndSearch: string | null): Promise<unknown>;
26
28
  navigationPlanner: typeof navigationPlanner;
@@ -1,10 +1,10 @@
1
1
  import { hasBasePath } from "../utils/base-path.js";
2
2
  import { ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
3
3
  import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
4
- import { AppElementsWire } from "./app-elements-wire.js";
5
- import "./app-elements.js";
6
4
  import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createServerActionRequestUrl } from "./app-rsc-cache-busting.js";
7
5
  import { throwOnServerActionNotFound } from "./server-action-not-found.js";
6
+ import { AppElementsWire } from "./app-elements-wire.js";
7
+ import "./app-elements.js";
8
8
  import { createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult, shouldSyncServerActionHttpFallbackHead } from "./app-browser-action-result.js";
9
9
  import { parseRenderedPathAndSearchHeader } from "../shims/navigation.js";
10
10
  import { resolveServerActionRequestState } from "./app-browser-state.js";
@@ -89,7 +89,8 @@ async function invokeClientServerAction(id, args, actionInitiation, deps) {
89
89
  const actionResultDecision = deps.navigationPlanner.classifyServerActionResult(actionResultFacts);
90
90
  if (applyServerActionResultDecision(actionResultDecision, () => deps.clearClientNavigationCaches(), (url, historyMode) => deps.performHardNavigation(url, historyMode))) return;
91
91
  const revalidation = parseServerActionRevalidationHeader(fetchResponse.headers);
92
- if (revalidation !== "none") deps.clearClientNavigationCaches();
92
+ if (revalidation === "staticAndDynamic") deps.clearClientNavigationCaches();
93
+ else if (revalidation === "dynamicOnly") deps.clearDynamicClientNavigationCaches();
93
94
  const invalidResponseError = await readInvalidServerActionResponseError(fetchResponse.clone(), actionRedirectTarget !== null);
94
95
  if (invalidResponseError) throw invalidResponseError;
95
96
  if (actionRedirectTarget && !fetchResponseIsRsc) {
@@ -1,13 +1,13 @@
1
1
  import { BrowserRouteManifest } from "../routing/browser-route-manifest.js";
2
2
  import { CacheEntryReuseProof } from "./cache-proof.js";
3
- import { AppElements, AppElementsInterception, AppElementsSlotBinding, LayoutFlags } from "./app-elements-wire.js";
3
+ import { AppElements, AppElementsInterception, AppElementsSlotBinding } from "./app-elements-wire.js";
4
4
  import "./app-elements.js";
5
+ import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
5
6
  import { NavigationTrace } from "./navigation-trace.js";
6
7
  import { OperationLane } from "./operation-token.js";
7
8
  import "./navigation-planner.js";
8
9
  import { BfcacheIdMap, HistoryTraversalIntent, createAppOwnedHistoryState, createExternalHistoryStatePreservingMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createHistoryStateWithTreeSnapshotId, isExternalHistoryState, isHistoryStateBfcacheVersionCurrent, readHistoryStateActiveRoutePaths, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveActiveRoutePaths, resolveHistoryTraversalIntent } from "./app-history-state.js";
9
10
  import { createBfcacheSegmentIdentityMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
10
- import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
11
11
  //#region src/server/app-browser-state.d.ts
12
12
  type OperationRecordBase = {
13
13
  id: number;
@@ -30,7 +30,6 @@ export type AppRouterState = {
30
30
  elements: AppElements;
31
31
  interception: AppElementsInterception | null;
32
32
  interceptionContext: string | null;
33
- layoutFlags: LayoutFlags;
34
33
  layoutIds: readonly string[];
35
34
  previousNextUrl: string | null;
36
35
  renderId: number;
@@ -46,7 +45,6 @@ export type AppRouterAction = {
46
45
  elements: AppElements;
47
46
  interception: AppElementsInterception | null;
48
47
  interceptionContext: string | null;
49
- layoutFlags: LayoutFlags;
50
48
  layoutIds: readonly string[];
51
49
  navigationSnapshot: ClientNavigationRenderSnapshot;
52
50
  operation: PendingOperationRecord;
@@ -3,17 +3,18 @@ import { VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER } from
3
3
  import { NEXT_ACTION_HEADER, RSC_ACTION_HEADER } from "./headers.js";
4
4
  import { normalizePathnameForRouteMatch } from "../routing/utils.js";
5
5
  import { normalizePath } from "./normalize-path.js";
6
+ import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
6
7
  import { AppElementsWire } from "./app-elements-wire.js";
7
8
  import { getMountedSlotIds, getMountedSlotIdsHeader } from "./app-elements.js";
8
- import { bindAppElementsRenderedSearch } from "../shims/slot.js";
9
- import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
10
9
  import { createBfcacheSegmentIdentityMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
11
- import { createCacheEntryReuseProof } from "./cache-proof.js";
12
10
  import { createAppOwnedHistoryState, createExternalHistoryStatePreservingMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createHistoryStateWithTreeSnapshotId, isExternalHistoryState, isHistoryStateBfcacheVersionCurrent, readHistoryStateActiveRoutePaths, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveActiveRoutePaths, resolveHistoryTraversalIntent } from "./app-history-state.js";
13
11
  import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
14
12
  import { verifyOperationTokenForCommit } from "./operation-token.js";
15
13
  import { navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts } from "./navigation-planner.js";
16
14
  import { createSnapshotPathAndSearch } from "../shims/navigation.js";
15
+ import { holdsSkippedLayouts } from "./app-mounted-layouts.js";
16
+ import { createCacheEntryReuseProof } from "./cache-proof.js";
17
+ import { bindAppElementsRenderedSearch } from "../shims/slot.js";
17
18
  //#region src/server/app-browser-state.ts
18
19
  const COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "committed-cache" };
19
20
  const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "fresh" };
@@ -239,6 +240,11 @@ function mapNavigationDecisionToPendingDisposition(decision) {
239
240
  function mergeSkippedLayoutPreservation(options) {
240
241
  if (options.decision.disposition !== "dispatch") return options.decision;
241
242
  if (options.pending.skippedLayoutIds.length === 0) return options.decision;
243
+ if (!holdsSkippedLayouts(options.currentState, options.pending.action.elements)) return {
244
+ disposition: "hard-navigate",
245
+ preserveElementIds: [],
246
+ trace: options.decision.trace
247
+ };
242
248
  const currentLayoutIds = new Set(options.currentState.layoutIds);
243
249
  const targetLayoutIds = new Set(options.pending.action.layoutIds);
244
250
  const preserveElementIds = [...options.decision.preserveElementIds];
@@ -303,7 +309,6 @@ function createPendingNavigationCommitFromElements(options) {
303
309
  interception: metadata.interception,
304
310
  interceptionContext: metadata.interceptionContext,
305
311
  layoutIds: metadata.layoutIds,
306
- layoutFlags: metadata.layoutFlags,
307
312
  slotBindings: metadata.slotBindings,
308
313
  navigationSnapshot: options.navigationSnapshot,
309
314
  operation: createOperationRecord({
@@ -1,8 +1,9 @@
1
1
  import { addBasePathToPathname, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
2
2
  import { normalizePathnameForRouteMatch } from "../routing/utils.js";
3
3
  import { normalizePath } from "./normalize-path.js";
4
- import { APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_SLOT_BINDINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
4
+ import { APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_SLOT_BINDINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
5
5
  import "./app-elements.js";
6
+ import { isNestedBfcacheSlotSegmentIdFor } from "./bfcache-identity.js";
6
7
  //#region src/server/app-browser-supplemental-refresh.ts
7
8
  const SUPPLEMENTAL_REFRESH_TIMEOUT_MS = 1e4;
8
9
  var SupplementalRefreshError = class extends Error {
@@ -67,6 +68,7 @@ function mergeRefreshedParallelSlot(currentElements, refreshedElements) {
67
68
  [APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(slotBindings, { layoutIds: refreshedMetadata.layoutIds })
68
69
  };
69
70
  for (const binding of retainedBindings) merged[binding.slotId] = currentElements[binding.slotId];
71
+ copySlotIdentities(merged, refreshedElements, currentElements, retainedBindings.map((binding) => binding.slotId));
70
72
  if (promotedBindings.length === 1) merged[promotedBindings[0].slotId] = refreshedElements[refreshedChildrenBindings[0].slotId];
71
73
  copyRefreshedBranchElements(merged, currentElements, { overwrite: false });
72
74
  return merged;
@@ -79,6 +81,7 @@ function mergeRefreshedParallelSlot(currentElements, refreshedElements) {
79
81
  [APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(slotBindings, { layoutIds: currentMetadata.layoutIds })
80
82
  };
81
83
  for (const binding of refreshedBindings) merged[binding.slotId] = refreshedElements[binding.slotId];
84
+ copySlotIdentities(merged, currentElements, refreshedElements, refreshedBindings.map((binding) => binding.slotId));
82
85
  copyRefreshedBranchElements(merged, refreshedElements);
83
86
  return merged;
84
87
  }
@@ -93,9 +96,21 @@ function mergeRefreshedParallelSlot(currentElements, refreshedElements) {
93
96
  [interception.slotId]: refreshedSlot,
94
97
  [APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(slotBindings, { layoutIds: currentMetadata.layoutIds })
95
98
  };
99
+ copySlotIdentities(merged, currentElements, refreshedElements, [interception.slotId]);
96
100
  copyRefreshedBranchElements(merged, refreshedElements);
97
101
  return merged;
98
102
  }
103
+ function copySlotIdentities(target, baseElements, slotElements, slotIds) {
104
+ const isSlotSegment = (id) => slotIds.some((slotId) => id === slotId || isNestedBfcacheSlotSegmentIdFor(id, slotId));
105
+ const isNestedSegment = (id) => !slotIds.includes(id) && isSlotSegment(id);
106
+ for (const id of Object.keys(baseElements)) if (isNestedSegment(id)) delete target[id];
107
+ for (const [id, element] of Object.entries(slotElements)) if (isNestedSegment(id)) target[id] = element;
108
+ const identities = {};
109
+ for (const [id, identity] of Object.entries(AppElementsWire.readMetadata(baseElements).bfcacheSegmentIdentities)) if (!isSlotSegment(id)) identities[id] = identity;
110
+ for (const [id, identity] of Object.entries(AppElementsWire.readMetadata(slotElements).bfcacheSegmentIdentities)) if (isSlotSegment(id)) identities[id] = identity;
111
+ if (Object.keys(identities).length > 0) target[APP_BFCACHE_SEGMENT_IDENTITIES_KEY] = identities;
112
+ else delete target[APP_BFCACHE_SEGMENT_IDENTITIES_KEY];
113
+ }
99
114
  function copyRefreshedBranchElements(target, refreshedElements, options = {}) {
100
115
  for (const [elementId, element] of Object.entries(refreshedElements)) {
101
116
  const parsed = AppElementsWire.parseElementKey(elementId);
@@ -1,9 +1,9 @@
1
1
  import { BrowserRouteManifest } from "../routing/browser-route-manifest.js";
2
2
  import { AppElements } from "./app-elements-wire.js";
3
3
  import "./app-elements.js";
4
+ import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
4
5
  import { NavigationTrace } from "./navigation-trace.js";
5
6
  import { OperationLane } from "./operation-token.js";
6
- import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
7
7
  import { AppNavigationPayloadOrigin, AppRouterAction, AppRouterState, PendingNavigationCommit } from "./app-browser-state.js";
8
8
  //#region src/server/app-browser-visible-commit.d.ts
9
9
  type VisibleCommitDecision = {
@@ -1,10 +1,10 @@
1
1
  import { AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
2
2
  import "./app-elements.js";
3
- import { mergeElements } from "../shims/slot.js";
4
- import { resolveAppPageRouteStateKey } from "./app-page-segment-state.js";
5
3
  import { createBfcacheSegmentIdentityMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
6
4
  import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
5
+ import { mergeElements } from "../shims/slot.js";
7
6
  import { createPendingNavigationCommit, resolvePendingNavigationCommitDispositionDecision } from "./app-browser-state.js";
7
+ import { resolveAppPageRouteStateKey } from "./app-page-segment-state.js";
8
8
  //#region src/server/app-browser-visible-commit.ts
9
9
  const approvedVisibleCommitBrand = Symbol("ApprovedVisibleCommit");
10
10
  function hasSameServerTemplateSeedIdentity(id, currentSnapshot, nextSnapshot) {
@@ -105,7 +105,6 @@ function reduceApprovedVisibleCommitState(state, commit) {
105
105
  elements: mergedElements,
106
106
  interception: action.interception,
107
107
  interceptionContext: action.interceptionContext,
108
- layoutFlags: mergeLayoutFlags(state.layoutFlags, action.layoutFlags, preserveElementIds),
109
108
  layoutIds: action.layoutIds,
110
109
  navigationSnapshot: action.navigationSnapshot,
111
110
  previousNextUrl: action.previousNextUrl,
@@ -145,15 +144,6 @@ function createVisibleCommitDecision(trace = createNavigationTrace(NavigationTra
145
144
  trace
146
145
  };
147
146
  }
148
- function mergeLayoutFlags(previousFlags, nextFlags, preserveElementIds) {
149
- const merged = { ...nextFlags };
150
- for (const id of preserveElementIds) {
151
- if (Object.hasOwn(merged, id)) continue;
152
- const value = previousFlags[id];
153
- if (value) merged[id] = value;
154
- }
155
- return merged;
156
- }
157
147
  function createApprovedVisibleCommit(options) {
158
148
  return {
159
149
  [approvedVisibleCommitBrand]: true,
@@ -1,6 +1,5 @@
1
1
  import { ArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
2
2
  import { CacheEntryReuseProof } from "./cache-proof.js";
3
- import { ClientReuseManifestSkipDisposition } from "./client-reuse-manifest.js";
4
3
  import { BfcacheSegmentIdentity } from "./bfcache-identity.js";
5
4
  import { compareStrings } from "../utils/compare.js";
6
5
  import { AppElementsWireElementKey } from "./app-elements-wire-key.js";
@@ -12,7 +11,6 @@ export declare const APP_DYNAMIC_STALE_TIME_KEY = "__dynamicStaleTime";
12
11
  export declare const APP_INTERCEPTION_KEY = "__interception";
13
12
  export declare const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
14
13
  export declare const APP_LAYOUT_IDS_KEY = "__layoutIds";
15
- export declare const APP_LAYOUT_FLAGS_KEY = "__layoutFlags";
16
14
  export declare const APP_ROUTE_KEY = "__route";
17
15
  export declare const APP_ROOT_LAYOUT_KEY = "__rootLayout";
18
16
  export declare const APP_SKIPPED_LAYOUT_IDS_KEY = "__skippedLayoutIds";
@@ -51,28 +49,10 @@ export declare const compareAppElementsSlotIds: typeof compareStrings;
51
49
  export declare function normalizeAppElementsSlotBindings(slotBindings: readonly AppElementsSlotBinding[], options?: {
52
50
  layoutIds?: readonly string[];
53
51
  }): readonly AppElementsSlotBinding[];
54
- export type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null | LayoutFlags | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | readonly string[] | readonly AppElementsSlotBinding[];
55
- type AppWireElementValue = ReactNode | string | null | LayoutFlags | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | readonly string[] | readonly AppElementsSlotBinding[];
52
+ export type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | readonly string[] | readonly AppElementsSlotBinding[];
53
+ type AppWireElementValue = ReactNode | string | null | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | readonly string[] | readonly AppElementsSlotBinding[];
56
54
  export type AppElements = Readonly<Record<string, AppElementValue>>;
57
55
  export type AppWireElements = Readonly<Record<string, AppWireElementValue>>;
58
- /**
59
- * Per-layout static/dynamic flags. `"s"` = static (skippable on next nav);
60
- * `"d"` = dynamic (must always render).
61
- *
62
- * Lifecycle (partial — later PRs extend this):
63
- *
64
- * 1. PROBE — probeAppPageLayouts (server/app-page-execution.ts) returns
65
- * LayoutFlags for every layout in the route at render time.
66
- *
67
- * 2. ATTACH — AppElementsWire.encodeOutgoingPayload writes `__layoutFlags`
68
- * into the outgoing App Router payload record.
69
- *
70
- * 3. WIRE — renderToReadableStream serializes the record as RSC row 0.
71
- *
72
- * 4. PARSE — AppElementsWire.readMetadata extracts layoutFlags from the
73
- * wire payload on the client side.
74
- */
75
- export type LayoutFlags = Readonly<Record<string, "s" | "d">>;
76
56
  export type AppElementsBfcacheSegmentIdentities = Readonly<Record<string, BfcacheSegmentIdentity>>;
77
57
  type AppElementsMetadata = {
78
58
  artifactCompatibility: ArtifactCompatibilityEnvelope;
@@ -81,7 +61,6 @@ type AppElementsMetadata = {
81
61
  interception: AppElementsInterception | null;
82
62
  interceptionContext: string | null;
83
63
  layoutIds: readonly string[];
84
- layoutFlags: LayoutFlags;
85
64
  routeId: string;
86
65
  rootLayoutTreePath: string | null;
87
66
  bfcacheSegmentIdentities: AppElementsBfcacheSegmentIdentities;
@@ -113,11 +92,11 @@ type AppElementsWireMetadataEntries = Readonly<{
113
92
  }>;
114
93
  /**
115
94
  * The outgoing wire payload shape. Includes ReactNode values for the
116
- * rendered tree plus metadata values like LayoutFlags attached under
117
- * known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements
95
+ * rendered tree plus metadata values attached under known keys (e.g.
96
+ * __artifactCompatibility). Distinct from AppElements / AppWireElements
118
97
  * which only carry render-time values.
119
98
  */
120
- export type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | number | readonly string[] | readonly AppElementsSlotBinding[]>>;
99
+ export type AppOutgoingElements = Readonly<Record<string, ReactNode | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | number | readonly string[] | readonly AppElementsSlotBinding[]>>;
121
100
  type AppElementsWireKeys = {
122
101
  readonly artifactCompatibility: typeof APP_ARTIFACT_COMPATIBILITY_KEY;
123
102
  readonly cacheEntryReuseProof: typeof APP_CACHE_ENTRY_REUSE_PROOF_KEY;
@@ -125,7 +104,6 @@ type AppElementsWireKeys = {
125
104
  readonly interception: typeof APP_INTERCEPTION_KEY;
126
105
  readonly interceptionContext: typeof APP_INTERCEPTION_CONTEXT_KEY;
127
106
  readonly layoutIds: typeof APP_LAYOUT_IDS_KEY;
128
- readonly layoutFlags: typeof APP_LAYOUT_FLAGS_KEY;
129
107
  readonly rootLayout: typeof APP_ROOT_LAYOUT_KEY;
130
108
  readonly route: typeof APP_ROUTE_KEY;
131
109
  readonly bfcacheSegmentIdentities: typeof APP_BFCACHE_SEGMENT_IDENTITIES_KEY;
@@ -145,8 +123,6 @@ type AppElementsWireCodec = {
145
123
  artifactCompatibility?: ArtifactCompatibilityEnvelope;
146
124
  cacheEntryReuseProof?: CacheEntryReuseProof;
147
125
  dynamicStaleTimeSeconds?: number;
148
- layoutFlags: LayoutFlags;
149
- skipDisposition?: ClientReuseManifestSkipDisposition;
150
126
  }): ReactNode | AppOutgoingElements;
151
127
  encodePageId(routePath: string, interceptionContext: string | null): string;
152
128
  encodeRouteId(routePath: string, interceptionContext: string | null): string;
@@ -155,9 +131,6 @@ type AppElementsWireCodec = {
155
131
  isSlotId(key: string): boolean;
156
132
  parseElementKey(key: string): AppElementsWireElementKey | null;
157
133
  readMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
158
- withLayoutFlags<T extends Record<string, unknown>>(elements: T, layoutFlags: LayoutFlags): T & {
159
- [APP_LAYOUT_FLAGS_KEY]: LayoutFlags;
160
- };
161
134
  };
162
135
  export declare function normalizeAppElements(elements: AppWireElements): AppElements;
163
136
  /**
@@ -165,21 +138,16 @@ export declare function normalizeAppElements(elements: AppWireElements): AppElem
165
138
  * Used to distinguish the App Router payload object from bare React elements at
166
139
  * the render boundary. Narrows to `Readonly<Record<string, unknown>>` because
167
140
  * the outgoing payload carries heterogeneous values (ReactNodes for the rendered
168
- * tree, plus metadata like `__layoutFlags` which is a plain object). Delegates
141
+ * tree, plus metadata like `__artifactCompatibility`, a plain object). Delegates
169
142
  * to React's canonical `isValidElement` so we don't depend on React's internal
170
143
  * `$$typeof` marker scheme.
171
144
  */
172
145
  export declare function isAppElementsRecord(value: unknown): value is Readonly<Record<string, unknown>>;
173
- export declare function withLayoutFlags<T extends Record<string, unknown>>(elements: T, layoutFlags: LayoutFlags): T & {
174
- [APP_LAYOUT_FLAGS_KEY]: LayoutFlags;
175
- };
176
146
  export declare function buildOutgoingAppPayload(input: {
177
147
  element: ReactNode | AppElements;
178
148
  artifactCompatibility?: ArtifactCompatibilityEnvelope;
179
149
  cacheEntryReuseProof?: CacheEntryReuseProof;
180
150
  dynamicStaleTimeSeconds?: number;
181
- layoutFlags: LayoutFlags;
182
- skipDisposition?: ClientReuseManifestSkipDisposition;
183
151
  }): ReactNode | AppOutgoingElements;
184
152
  export declare function readAppElementsMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
185
153
  export declare const AppElementsWire: AppElementsWireCodec;
@@ -3,7 +3,6 @@ import { compareStrings } from "../utils/compare.js";
3
3
  import { isInterceptionMatchedUrlPath } from "./normalize-path.js";
4
4
  import { createAppElementsWireSlotId, isAppElementsWireSlotId, parseAppElementsWireElementKey } from "./app-elements-wire-key.js";
5
5
  import { createArtifactCompatibilityEnvelope, parseArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
6
- import { releaseAppElementRenderDependency } from "./app-render-dependency.js";
7
6
  import { isValidElement } from "react";
8
7
  //#region src/server/app-elements-wire.ts
9
8
  const APP_INTERCEPTION_SEPARATOR = "\0";
@@ -14,7 +13,6 @@ const APP_DYNAMIC_STALE_TIME_KEY = "__dynamicStaleTime";
14
13
  const APP_INTERCEPTION_KEY = "__interception";
15
14
  const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
16
15
  const APP_LAYOUT_IDS_KEY = "__layoutIds";
17
- const APP_LAYOUT_FLAGS_KEY = "__layoutFlags";
18
16
  const APP_ROUTE_KEY = "__route";
19
17
  const APP_ROOT_LAYOUT_KEY = "__rootLayout";
20
18
  const APP_SKIPPED_LAYOUT_IDS_KEY = "__skippedLayoutIds";
@@ -33,7 +31,6 @@ const APP_BFCACHE_SEGMENT_IDENTITIES_KEY = "__bfcacheSegmentIdentities";
33
31
  const APP_STATIC_SIBLINGS_KEY = "__staticSiblings";
34
32
  const APP_UNMATCHED_SLOT_WIRE_VALUE = "__VINEXT_UNMATCHED_SLOT__";
35
33
  const UNMATCHED_SLOT = Symbol.for("vinext.unmatchedSlot");
36
- const EMPTY_SKIPPED_LAYOUT_IDS = /* @__PURE__ */ new Set();
37
34
  function createCacheProofRejectionCodeSet(codes) {
38
35
  return new Set(codes);
39
36
  }
@@ -147,15 +144,6 @@ function normalizeAppElements(elements) {
147
144
  for (const [key, value] of Object.entries(elements)) normalized[key] = isAppElementsWireSlotId(key) && value === "__VINEXT_UNMATCHED_SLOT__" ? UNMATCHED_SLOT : value;
148
145
  return normalized;
149
146
  }
150
- function isLayoutFlagsRecord(value) {
151
- if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
152
- for (const v of Object.values(value)) if (v !== "s" && v !== "d") return false;
153
- return true;
154
- }
155
- function parseLayoutFlags(value) {
156
- if (isLayoutFlagsRecord(value)) return value;
157
- return {};
158
- }
159
147
  function parseLayoutIdList(value, fieldName) {
160
148
  if (value === void 0) return [];
161
149
  if (!Array.isArray(value)) throw new Error(`[vinext] Invalid ${fieldName} in App Router payload: expected layout id string[]`);
@@ -242,7 +230,7 @@ function parseInterceptionMetadata(value) {
242
230
  * Used to distinguish the App Router payload object from bare React elements at
243
231
  * the render boundary. Narrows to `Readonly<Record<string, unknown>>` because
244
232
  * the outgoing payload carries heterogeneous values (ReactNodes for the rendered
245
- * tree, plus metadata like `__layoutFlags` which is a plain object). Delegates
233
+ * tree, plus metadata like `__artifactCompatibility`, a plain object). Delegates
246
234
  * to React's canonical `isValidElement` so we don't depend on React's internal
247
235
  * `$$typeof` marker scheme.
248
236
  */
@@ -252,36 +240,15 @@ function isAppElementsRecord(value) {
252
240
  if (isValidElement(value)) return false;
253
241
  return true;
254
242
  }
255
- function withLayoutFlags(elements, layoutFlags) {
256
- return {
257
- ...elements,
258
- [APP_LAYOUT_FLAGS_KEY]: layoutFlags
259
- };
260
- }
261
243
  function buildOutgoingAppPayload(input) {
262
244
  if (!isAppElementsRecord(input.element)) return input.element;
263
- const skippedLayoutIds = createSkippedLayoutIds(input.skipDisposition);
264
245
  const payload = {};
265
- for (const [key, value] of Object.entries(input.element)) {
266
- if (skippedLayoutIds.has(key)) {
267
- releaseAppElementRenderDependency(input.element, key);
268
- continue;
269
- }
270
- payload[key] = value === UNMATCHED_SLOT ? APP_UNMATCHED_SLOT_WIRE_VALUE : value;
271
- }
272
- payload[APP_LAYOUT_FLAGS_KEY] = input.layoutFlags;
273
- if (skippedLayoutIds.size > 0) payload[APP_SKIPPED_LAYOUT_IDS_KEY] = [...skippedLayoutIds];
246
+ for (const [key, value] of Object.entries(input.element)) payload[key] = value === UNMATCHED_SLOT ? APP_UNMATCHED_SLOT_WIRE_VALUE : value;
274
247
  payload[APP_ARTIFACT_COMPATIBILITY_KEY] = input.artifactCompatibility ?? createArtifactCompatibilityEnvelope();
275
248
  if (input.cacheEntryReuseProof) payload[APP_CACHE_ENTRY_REUSE_PROOF_KEY] = input.cacheEntryReuseProof;
276
249
  if (input.dynamicStaleTimeSeconds !== void 0) payload[APP_DYNAMIC_STALE_TIME_KEY] = input.dynamicStaleTimeSeconds;
277
250
  return payload;
278
251
  }
279
- function createSkippedLayoutIds(skipDisposition) {
280
- if (skipDisposition?.enabled !== true) return EMPTY_SKIPPED_LAYOUT_IDS;
281
- const skippedLayoutIds = /* @__PURE__ */ new Set();
282
- for (const id of skipDisposition.skippedEntryIds) if (parseAppElementsWireElementKey(id)?.kind === "layout") skippedLayoutIds.add(id);
283
- return skippedLayoutIds;
284
- }
285
252
  function readArtifactCompatibilityMetadata(value) {
286
253
  if (value === void 0) return createArtifactCompatibilityEnvelope();
287
254
  return parseArtifactCompatibilityEnvelope(value) ?? createArtifactCompatibilityEnvelope();
@@ -351,7 +318,6 @@ function readAppElementsMetadata(elements) {
351
318
  const rootLayoutTreePath = elements[APP_ROOT_LAYOUT_KEY];
352
319
  if (rootLayoutTreePath === void 0) throw new Error("[vinext] Missing __rootLayout key in App Router payload");
353
320
  if (rootLayoutTreePath !== null && typeof rootLayoutTreePath !== "string") throw new Error("[vinext] Invalid __rootLayout in App Router payload: expected string or null");
354
- const layoutFlags = parseLayoutFlags(elements[APP_LAYOUT_FLAGS_KEY]);
355
321
  const layoutIds = parseLayoutIds(elements[APP_LAYOUT_IDS_KEY]);
356
322
  const skippedLayoutIds = parseSkippedLayoutIds(elements[APP_SKIPPED_LAYOUT_IDS_KEY]);
357
323
  const slotBindings = parseSlotBindings(elements[APP_SLOT_BINDINGS_KEY], { layoutIds });
@@ -369,7 +335,6 @@ function readAppElementsMetadata(elements) {
369
335
  interception,
370
336
  interceptionContext: interceptionContext ?? null,
371
337
  layoutIds,
372
- layoutFlags,
373
338
  routeId,
374
339
  rootLayoutTreePath,
375
340
  bfcacheSegmentIdentities,
@@ -386,7 +351,6 @@ const AppElementsWire = {
386
351
  interception: APP_INTERCEPTION_KEY,
387
352
  interceptionContext: APP_INTERCEPTION_CONTEXT_KEY,
388
353
  layoutIds: APP_LAYOUT_IDS_KEY,
389
- layoutFlags: APP_LAYOUT_FLAGS_KEY,
390
354
  rootLayout: APP_ROOT_LAYOUT_KEY,
391
355
  route: APP_ROUTE_KEY,
392
356
  bfcacheSegmentIdentities: APP_BFCACHE_SEGMENT_IDENTITIES_KEY,
@@ -406,8 +370,7 @@ const AppElementsWire = {
406
370
  encodeTemplateId: createAppPayloadTemplateId,
407
371
  isSlotId: isAppElementsWireSlotId,
408
372
  parseElementKey: parseAppElementsWireElementKey,
409
- readMetadata: readAppElementsMetadata,
410
- withLayoutFlags
373
+ readMetadata: readAppElementsMetadata
411
374
  };
412
375
  //#endregion
413
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
376
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata };
@@ -1,4 +1,4 @@
1
- import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsBfcacheSegmentIdentities, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
1
+ import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsBfcacheSegmentIdentities, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata } from "./app-elements-wire.js";
2
2
  //#region src/server/app-elements.d.ts
3
3
  export declare const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
4
4
  /** Prefix of the element that streams a route's generateMetadata() tags in the body. */
@@ -7,4 +7,4 @@ export declare function getMountedSlotIds(elements: AppElements): string[];
7
7
  export declare function getMountedSlotIdsHeader(elements: AppElements): string | null;
8
8
  export declare function resolveVisitedResponseInterceptionContext(requestInterceptionContext: string | null, payloadInterceptionContext: string | null): string | null;
9
9
  //#endregion
10
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsBfcacheSegmentIdentities, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, type LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
10
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsBfcacheSegmentIdentities, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata };
@@ -1,5 +1,5 @@
1
1
  import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
2
- import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
2
+ import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata } from "./app-elements-wire.js";
3
3
  //#region src/server/app-elements.ts
4
4
  const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
5
5
  /** Prefix of the element that streams a route's generateMetadata() tags in the body. */
@@ -18,4 +18,4 @@ function resolveVisitedResponseInterceptionContext(requestInterceptionContext, p
18
18
  return payloadInterceptionContext ?? requestInterceptionContext;
19
19
  }
20
20
  //#endregion
21
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_STREAMING_METADATA_BODY_ID_PREFIX, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
21
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_STREAMING_METADATA_BODY_ID_PREFIX, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext };
@@ -75,11 +75,11 @@ export declare function isExternalHistoryState(state: unknown): boolean;
75
75
  */
76
76
  export declare function isAppOwnedHistoryState(state: unknown): boolean;
77
77
  export declare function createAppOwnedHistoryState(state: unknown): unknown;
78
- export declare function createHistoryStateWithTreeSnapshotId(state: unknown, treeSnapshotId: number | null): unknown;
78
+ export declare function createHistoryStateWithTreeSnapshotId(state: unknown, treeSnapshotId: string | null): unknown;
79
79
  export declare function createHistoryStateWithTreeSnapshotClaim(state: unknown, claimed: boolean): unknown;
80
80
  export declare function isHistoryStateTreeSnapshotClaimed(state: unknown): boolean;
81
81
  export declare function clearHistoryStateTreeSnapshotId(state: unknown): unknown;
82
- export declare function readHistoryStateTreeSnapshotId(state: unknown): number | null;
82
+ export declare function readHistoryStateTreeSnapshotId(state: unknown): string | null;
83
83
  export declare function readHistoryStateActiveRoutePaths(state: unknown): readonly string[] | null;
84
84
  export declare function resolveActiveRoutePaths(slotBindings: readonly {
85
85
  activeRouteId?: string | null;
@@ -210,7 +210,7 @@ function createAppOwnedHistoryState(state) {
210
210
  function createHistoryStateWithTreeSnapshotId(state, treeSnapshotId) {
211
211
  const nextState = cloneHistoryState(state);
212
212
  const previousTreeSnapshotId = readHistoryStateTreeSnapshotId(nextState);
213
- if (isNonNegativeSafeInteger(treeSnapshotId)) {
213
+ if (isTreeSnapshotId(treeSnapshotId)) {
214
214
  nextState[VINEXT_TREE_SNAPSHOT_ID_HISTORY_STATE_KEY] = treeSnapshotId;
215
215
  if (previousTreeSnapshotId !== treeSnapshotId) delete nextState[VINEXT_TREE_SNAPSHOT_CLAIMED_HISTORY_STATE_KEY];
216
216
  } else {
@@ -233,7 +233,10 @@ function clearHistoryStateTreeSnapshotId(state) {
233
233
  }
234
234
  function readHistoryStateTreeSnapshotId(state) {
235
235
  const value = readHistoryStateRecord(state)?.[VINEXT_TREE_SNAPSHOT_ID_HISTORY_STATE_KEY];
236
- return isNonNegativeSafeInteger(value) ? value : null;
236
+ return isTreeSnapshotId(value) ? value : null;
237
+ }
238
+ function isTreeSnapshotId(value) {
239
+ return typeof value === "string" && value.length > 0;
237
240
  }
238
241
  function readHistoryStateActiveRoutePaths(state) {
239
242
  const value = readHistoryStateRecord(state)?.[VINEXT_ACTIVE_ROUTE_PATHS_HISTORY_STATE_KEY];
@@ -0,0 +1,21 @@
1
+ import { AppElements } from "./app-elements-wire.js";
2
+ import "./app-elements.js";
3
+ //#region src/server/app-mounted-layouts.d.ts
4
+ export declare function hashMountedLayoutIdentity(identity: string): string;
5
+ export declare function parseMountedLayoutsHeader(value: string | null): ReadonlySet<string> | null;
6
+ /**
7
+ * The header for the outermost layouts a client state holds. Only that prefix
8
+ * can be left out of a render, as a layout below one that re-renders renders
9
+ * inside it.
10
+ */
11
+ export declare function createMountedLayoutsHeader(elements: AppElements, layoutIds: readonly string[]): string | null;
12
+ /**
13
+ * Whether a client state still holds, unchanged, every layout a payload left
14
+ * out. A navigation that started from another state, or a payload stored for
15
+ * another client, can name layouts this one doesn't hold.
16
+ */
17
+ export declare function holdsSkippedLayouts(current: {
18
+ elements: AppElements;
19
+ layoutIds: readonly string[];
20
+ }, next: AppElements): boolean;
21
+ //#endregion