vinext 0.0.41 → 0.0.42

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 (162) hide show
  1. package/README.md +0 -1
  2. package/dist/build/client-build-config.d.ts +119 -0
  3. package/dist/build/client-build-config.js +149 -0
  4. package/dist/build/client-build-config.js.map +1 -0
  5. package/dist/build/layout-classification-types.d.ts +62 -0
  6. package/dist/build/layout-classification-types.js +1 -0
  7. package/dist/build/layout-classification.d.ts +60 -0
  8. package/dist/build/layout-classification.js +98 -0
  9. package/dist/build/layout-classification.js.map +1 -0
  10. package/dist/build/report.d.ts +15 -1
  11. package/dist/build/report.js +50 -1
  12. package/dist/build/report.js.map +1 -1
  13. package/dist/build/route-classification-manifest.d.ts +53 -0
  14. package/dist/build/route-classification-manifest.js +145 -0
  15. package/dist/build/route-classification-manifest.js.map +1 -0
  16. package/dist/build/run-prerender.js +1 -1
  17. package/dist/build/ssr-manifest.d.ts +19 -0
  18. package/dist/build/ssr-manifest.js +71 -0
  19. package/dist/build/ssr-manifest.js.map +1 -0
  20. package/dist/check.js +2 -2
  21. package/dist/check.js.map +1 -1
  22. package/dist/cli.js +1 -1
  23. package/dist/client/entry.js +1 -1
  24. package/dist/config/config-matchers.js +1 -0
  25. package/dist/config/config-matchers.js.map +1 -1
  26. package/dist/entries/app-rsc-entry.js +287 -95
  27. package/dist/entries/app-rsc-entry.js.map +1 -1
  28. package/dist/index.d.ts +1 -169
  29. package/dist/index.js +112 -432
  30. package/dist/index.js.map +1 -1
  31. package/dist/plugins/fonts.d.ts +49 -1
  32. package/dist/plugins/fonts.js +96 -3
  33. package/dist/plugins/fonts.js.map +1 -1
  34. package/dist/plugins/postcss.d.ts +27 -0
  35. package/dist/plugins/postcss.js +94 -0
  36. package/dist/plugins/postcss.js.map +1 -0
  37. package/dist/plugins/strip-server-exports.d.ts +14 -0
  38. package/dist/plugins/strip-server-exports.js +73 -0
  39. package/dist/plugins/strip-server-exports.js.map +1 -0
  40. package/dist/routing/app-router.d.ts +6 -4
  41. package/dist/routing/app-router.js +21 -22
  42. package/dist/routing/app-router.js.map +1 -1
  43. package/dist/server/app-browser-entry.js +235 -97
  44. package/dist/server/app-browser-entry.js.map +1 -1
  45. package/dist/server/app-browser-error.d.ts +8 -0
  46. package/dist/server/app-browser-error.js +9 -0
  47. package/dist/server/app-browser-error.js.map +1 -0
  48. package/dist/server/app-browser-state.d.ts +93 -0
  49. package/dist/server/app-browser-state.js +132 -0
  50. package/dist/server/app-browser-state.js.map +1 -0
  51. package/dist/server/app-elements.d.ts +92 -0
  52. package/dist/server/app-elements.js +122 -0
  53. package/dist/server/app-elements.js.map +1 -0
  54. package/dist/server/app-page-boundary-render.d.ts +2 -1
  55. package/dist/server/app-page-boundary-render.js +40 -1
  56. package/dist/server/app-page-boundary-render.js.map +1 -1
  57. package/dist/server/app-page-cache.d.ts +6 -3
  58. package/dist/server/app-page-cache.js +14 -8
  59. package/dist/server/app-page-cache.js.map +1 -1
  60. package/dist/server/app-page-execution.d.ts +36 -3
  61. package/dist/server/app-page-execution.js +50 -10
  62. package/dist/server/app-page-execution.js.map +1 -1
  63. package/dist/server/app-page-probe.d.ts +10 -4
  64. package/dist/server/app-page-probe.js +24 -15
  65. package/dist/server/app-page-probe.js.map +1 -1
  66. package/dist/server/app-page-render.d.ts +7 -4
  67. package/dist/server/app-page-render.js +13 -4
  68. package/dist/server/app-page-render.js.map +1 -1
  69. package/dist/server/app-page-request.d.ts +52 -4
  70. package/dist/server/app-page-request.js +86 -16
  71. package/dist/server/app-page-request.js.map +1 -1
  72. package/dist/server/app-page-response.d.ts +1 -0
  73. package/dist/server/app-page-response.js +1 -0
  74. package/dist/server/app-page-response.js.map +1 -1
  75. package/dist/server/app-page-route-wiring.d.ts +22 -8
  76. package/dist/server/app-page-route-wiring.js +219 -83
  77. package/dist/server/app-page-route-wiring.js.map +1 -1
  78. package/dist/server/app-render-dependency.d.ts +13 -0
  79. package/dist/server/app-render-dependency.js +35 -0
  80. package/dist/server/app-render-dependency.js.map +1 -0
  81. package/dist/server/app-route-handler-execution.d.ts +1 -0
  82. package/dist/server/app-route-handler-execution.js +1 -0
  83. package/dist/server/app-route-handler-execution.js.map +1 -1
  84. package/dist/server/app-route-handler-runtime.d.ts +1 -0
  85. package/dist/server/app-route-handler-runtime.js +26 -1
  86. package/dist/server/app-route-handler-runtime.js.map +1 -1
  87. package/dist/server/app-ssr-entry.js +6 -2
  88. package/dist/server/app-ssr-entry.js.map +1 -1
  89. package/dist/server/dev-server.js +2 -4
  90. package/dist/server/dev-server.js.map +1 -1
  91. package/dist/server/middleware.js +1 -5
  92. package/dist/server/middleware.js.map +1 -1
  93. package/dist/server/prod-server.d.ts +3 -3
  94. package/dist/server/prod-server.js +1 -1
  95. package/dist/server/prod-server.js.map +1 -1
  96. package/dist/server/request-pipeline.d.ts +2 -1
  97. package/dist/server/request-pipeline.js +34 -5
  98. package/dist/server/request-pipeline.js.map +1 -1
  99. package/dist/shims/cache-runtime.d.ts +1 -0
  100. package/dist/shims/cache-runtime.js +0 -5
  101. package/dist/shims/cache-runtime.js.map +1 -1
  102. package/dist/shims/cache.d.ts +1 -0
  103. package/dist/shims/cache.js +1 -8
  104. package/dist/shims/cache.js.map +1 -1
  105. package/dist/shims/client-hook-error.d.ts +14 -0
  106. package/dist/shims/client-hook-error.js +19 -0
  107. package/dist/shims/client-hook-error.js.map +1 -0
  108. package/dist/shims/constants.d.ts +3 -3
  109. package/dist/shims/constants.js +3 -3
  110. package/dist/shims/constants.js.map +1 -1
  111. package/dist/shims/document.d.ts +6 -6
  112. package/dist/shims/error-boundary.d.ts +4 -4
  113. package/dist/shims/error-boundary.js +1 -1
  114. package/dist/shims/error-boundary.js.map +1 -1
  115. package/dist/shims/form.d.ts +3 -3
  116. package/dist/shims/head-state.d.ts +1 -0
  117. package/dist/shims/head-state.js +0 -5
  118. package/dist/shims/head-state.js.map +1 -1
  119. package/dist/shims/headers.d.ts +11 -0
  120. package/dist/shims/headers.js +13 -10
  121. package/dist/shims/headers.js.map +1 -1
  122. package/dist/shims/i18n-state.d.ts +1 -0
  123. package/dist/shims/i18n-state.js +0 -4
  124. package/dist/shims/i18n-state.js.map +1 -1
  125. package/dist/shims/internal/app-router-context.d.ts +6 -6
  126. package/dist/shims/internal/router-context.d.ts +2 -2
  127. package/dist/shims/layout-segment-context.d.ts +2 -2
  128. package/dist/shims/link.js +19 -11
  129. package/dist/shims/link.js.map +1 -1
  130. package/dist/shims/metadata.d.ts +3 -3
  131. package/dist/shims/navigation-state.d.ts +2 -0
  132. package/dist/shims/navigation-state.js +0 -13
  133. package/dist/shims/navigation-state.js.map +1 -1
  134. package/dist/shims/navigation.d.ts +55 -8
  135. package/dist/shims/navigation.js +97 -23
  136. package/dist/shims/navigation.js.map +1 -1
  137. package/dist/shims/navigation.react-server.d.ts +14 -0
  138. package/dist/shims/navigation.react-server.js +29 -0
  139. package/dist/shims/navigation.react-server.js.map +1 -0
  140. package/dist/shims/request-context.d.ts +1 -0
  141. package/dist/shims/request-context.js +0 -9
  142. package/dist/shims/request-context.js.map +1 -1
  143. package/dist/shims/request-state-types.d.ts +1 -1
  144. package/dist/shims/router-state.d.ts +1 -0
  145. package/dist/shims/router-state.js +0 -5
  146. package/dist/shims/router-state.js.map +1 -1
  147. package/dist/shims/slot.d.ts +11 -7
  148. package/dist/shims/slot.js +28 -19
  149. package/dist/shims/slot.js.map +1 -1
  150. package/dist/shims/unified-request-context.d.ts +2 -0
  151. package/dist/shims/unified-request-context.js +0 -14
  152. package/dist/shims/unified-request-context.js.map +1 -1
  153. package/dist/utils/mdx-scan.d.ts +10 -0
  154. package/dist/utils/mdx-scan.js +36 -0
  155. package/dist/utils/mdx-scan.js.map +1 -0
  156. package/dist/utils/public-routes.d.ts +5 -0
  157. package/dist/utils/public-routes.js +50 -0
  158. package/dist/utils/public-routes.js.map +1 -0
  159. package/package.json +3 -3
  160. package/dist/plugins/fix-use-server-closure-collision.d.ts +0 -29
  161. package/dist/plugins/fix-use-server-closure-collision.js +0 -204
  162. package/dist/plugins/fix-use-server-closure-collision.js.map +0 -1
@@ -1,12 +1,19 @@
1
1
  import { stripBasePath } from "../utils/base-path.js";
2
2
  import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
3
- import { __basePath, activateNavigationSnapshot, commitClientNavigationState, consumePrefetchResponse, createClientNavigationRenderSnapshot, getClientNavigationRenderContext, getPrefetchCache, getPrefetchedUrls, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, restoreRscResponse, setClientParams, setNavigationContext, snapshotRscResponse, toRscUrl } from "../shims/navigation.js";
3
+ import { createAppPayloadCacheKey, getMountedSlotIdsHeader, normalizeAppElements, readAppElementsMetadata, resolveVisitedResponseInterceptionContext } from "./app-elements.js";
4
+ import { __basePath, activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, consumePrefetchResponse, createClientNavigationRenderSnapshot, getClientNavigationRenderContext, getClientNavigationState, getCurrentInterceptionContext, getCurrentNextUrl, getPrefetchCache, getPrefetchedUrls, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, restoreRscResponse, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, toRscUrl } from "../shims/navigation.js";
5
+ import { ElementsContext, Slot } from "../shims/slot.js";
4
6
  import "../client/instrumentation-client.js";
5
7
  import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
6
- import { createElement, startTransition, use, useLayoutEffect, useState } from "react";
8
+ import { createHistoryStateWithPreviousNextUrl, createPendingNavigationCommit, readHistoryStatePreviousNextUrl, resolveAndClassifyNavigationCommit, resolveInterceptionContextFromPreviousNextUrl, resolvePendingNavigationCommitDisposition, resolveServerActionRequestState, routerReducer } from "./app-browser-state.js";
9
+ import { devOnCaughtError } from "./app-browser-error.js";
10
+ import { createElement, startTransition, use, useLayoutEffect, useReducer, useRef } from "react";
7
11
  import { hydrateRoot } from "react-dom/client";
8
12
  import { createFromFetch, createFromReadableStream, createTemporaryReferenceSet, encodeReply, setServerCallback } from "@vitejs/plugin-rsc/browser";
9
13
  //#region src/server/app-browser-entry.ts
14
+ function toActionType(kind) {
15
+ return kind === "traverse" ? "traverse" : "navigate";
16
+ }
10
17
  const MAX_VISITED_RESPONSE_CACHE_SIZE = 50;
11
18
  const VISITED_RESPONSE_CACHE_TTL = 5 * 6e4;
12
19
  const MAX_TRAVERSAL_CACHE_TTL = 30 * 6e4;
@@ -14,15 +21,20 @@ let nextNavigationRenderId = 0;
14
21
  let activeNavigationId = 0;
15
22
  const pendingNavigationCommits = /* @__PURE__ */ new Map();
16
23
  const pendingNavigationPrePaintEffects = /* @__PURE__ */ new Map();
17
- let setBrowserTreeState = null;
24
+ let dispatchBrowserRouterAction = null;
25
+ let browserRouterStateRef = null;
18
26
  let latestClientParams = {};
19
27
  const visitedResponseCache = /* @__PURE__ */ new Map();
20
28
  function isServerActionResult(value) {
21
29
  return !!value && typeof value === "object" && "root" in value;
22
30
  }
23
- function getBrowserTreeStateSetter() {
24
- if (!setBrowserTreeState) throw new Error("[vinext] Browser tree state is not initialized");
25
- return setBrowserTreeState;
31
+ function getBrowserRouterDispatch() {
32
+ if (!dispatchBrowserRouterAction) throw new Error("[vinext] Browser router dispatch is not initialized");
33
+ return dispatchBrowserRouterAction;
34
+ }
35
+ function getBrowserRouterState() {
36
+ if (!browserRouterStateRef) throw new Error("[vinext] Browser router state is not initialized");
37
+ return browserRouterStateRef.current;
26
38
  }
27
39
  function applyClientParams(params) {
28
40
  latestClientParams = params;
@@ -62,15 +74,21 @@ function drainPrePaintEffects(upToRenderId) {
62
74
  for (const [id, effect] of pendingNavigationPrePaintEffects) if (id <= upToRenderId) {
63
75
  pendingNavigationPrePaintEffects.delete(id);
64
76
  if (id === upToRenderId) effect();
65
- else commitClientNavigationState();
77
+ else commitClientNavigationState(void 0);
66
78
  }
67
79
  }
68
- function createNavigationCommitEffect(href, historyUpdateMode) {
80
+ function createNavigationCommitEffect(href, historyUpdateMode, navId, params, previousNextUrl) {
69
81
  return () => {
82
+ if (navId !== activeNavigationId) {
83
+ commitClientNavigationState(void 0);
84
+ return;
85
+ }
70
86
  const targetHref = new URL(href, window.location.origin).href;
71
- if (historyUpdateMode === "replace" && window.location.href !== targetHref) replaceHistoryStateWithoutNotify(null, "", href);
72
- else if (historyUpdateMode === "push" && window.location.href !== targetHref) pushHistoryStateWithoutNotify(null, "", href);
73
- commitClientNavigationState();
87
+ stageClientParams(params);
88
+ const historyState = createHistoryStateWithPreviousNextUrl(historyUpdateMode === "replace" ? window.history.state : null, previousNextUrl);
89
+ if (historyUpdateMode === "replace" && window.location.href !== targetHref) replaceHistoryStateWithoutNotify(historyState, "", href);
90
+ else if (historyUpdateMode === "push" && window.location.href !== targetHref) pushHistoryStateWithoutNotify(historyState, "", href);
91
+ commitClientNavigationState(navId);
74
92
  };
75
93
  }
76
94
  function evictVisitedResponseCacheIfNeeded() {
@@ -80,38 +98,76 @@ function evictVisitedResponseCacheIfNeeded() {
80
98
  visitedResponseCache.delete(oldest);
81
99
  }
82
100
  }
83
- function getVisitedResponse(rscUrl, navigationKind) {
84
- const cached = visitedResponseCache.get(rscUrl);
101
+ function getVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, navigationKind) {
102
+ const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);
103
+ const cached = visitedResponseCache.get(cacheKey);
85
104
  if (!cached) return null;
105
+ if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {
106
+ visitedResponseCache.delete(cacheKey);
107
+ return null;
108
+ }
86
109
  if (navigationKind === "refresh") return null;
87
110
  if (navigationKind === "traverse") {
88
111
  const createdAt = cached.expiresAt - VISITED_RESPONSE_CACHE_TTL;
89
112
  if (Date.now() - createdAt >= MAX_TRAVERSAL_CACHE_TTL) {
90
- visitedResponseCache.delete(rscUrl);
113
+ visitedResponseCache.delete(cacheKey);
91
114
  return null;
92
115
  }
93
- visitedResponseCache.delete(rscUrl);
94
- visitedResponseCache.set(rscUrl, cached);
116
+ visitedResponseCache.delete(cacheKey);
117
+ visitedResponseCache.set(cacheKey, cached);
95
118
  return cached;
96
119
  }
97
120
  if (cached.expiresAt > Date.now()) {
98
- visitedResponseCache.delete(rscUrl);
99
- visitedResponseCache.set(rscUrl, cached);
121
+ visitedResponseCache.delete(cacheKey);
122
+ visitedResponseCache.set(cacheKey, cached);
100
123
  return cached;
101
124
  }
102
- visitedResponseCache.delete(rscUrl);
125
+ visitedResponseCache.delete(cacheKey);
103
126
  return null;
104
127
  }
105
- function storeVisitedResponseSnapshot(rscUrl, snapshot, params) {
106
- visitedResponseCache.delete(rscUrl);
128
+ function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, params) {
129
+ const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);
130
+ visitedResponseCache.delete(cacheKey);
107
131
  evictVisitedResponseCacheIfNeeded();
108
132
  const now = Date.now();
109
- visitedResponseCache.set(rscUrl, {
133
+ visitedResponseCache.set(cacheKey, {
110
134
  params,
111
135
  expiresAt: now + VISITED_RESPONSE_CACHE_TTL,
112
136
  response: snapshot
113
137
  });
114
138
  }
139
+ function getRequestState(navigationKind, previousNextUrlOverride) {
140
+ if (previousNextUrlOverride !== void 0) return {
141
+ interceptionContext: resolveInterceptionContextFromPreviousNextUrl(previousNextUrlOverride, __basePath),
142
+ previousNextUrl: previousNextUrlOverride
143
+ };
144
+ switch (navigationKind) {
145
+ case "navigate": return {
146
+ interceptionContext: getCurrentInterceptionContext(),
147
+ previousNextUrl: getCurrentNextUrl()
148
+ };
149
+ case "traverse": {
150
+ const previousNextUrl = readHistoryStatePreviousNextUrl(window.history.state);
151
+ return {
152
+ interceptionContext: resolveInterceptionContextFromPreviousNextUrl(previousNextUrl, __basePath),
153
+ previousNextUrl
154
+ };
155
+ }
156
+ case "refresh": {
157
+ const currentPreviousNextUrl = getBrowserRouterState().previousNextUrl;
158
+ return {
159
+ interceptionContext: resolveInterceptionContextFromPreviousNextUrl(currentPreviousNextUrl, __basePath),
160
+ previousNextUrl: currentPreviousNextUrl
161
+ };
162
+ }
163
+ default: throw new Error("[vinext] Unknown navigation kind: " + String(navigationKind));
164
+ }
165
+ }
166
+ function createRscRequestHeaders(interceptionContext) {
167
+ const headers = new Headers({ Accept: "text/x-component" });
168
+ if (interceptionContext !== null) headers.set("X-Vinext-Interception-Context", interceptionContext);
169
+ return headers;
170
+ }
115
171
  /**
116
172
  * Resolve all pending navigation commits with renderId <= the committed renderId.
117
173
  * Note: Map iteration handles concurrent deletion safely — entries are visited in
@@ -137,63 +193,126 @@ function NavigationCommitSignal({ renderId, children }) {
137
193
  }, [renderId]);
138
194
  return children;
139
195
  }
140
- function BrowserRoot({ initialNode, initialNavigationSnapshot }) {
141
- const [treeState, setTreeState] = useState({
196
+ function normalizeAppElementsPromise(payload) {
197
+ return Promise.resolve(payload).then((elements) => normalizeAppElements(elements));
198
+ }
199
+ async function commitSameUrlNavigatePayload(nextElements, returnValue) {
200
+ const navigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
201
+ const currentState = getBrowserRouterState();
202
+ const startedNavigationId = activeNavigationId;
203
+ const { disposition, pending } = await resolveAndClassifyNavigationCommit({
204
+ activeNavigationId,
205
+ currentState,
206
+ navigationSnapshot,
207
+ nextElements,
208
+ renderId: ++nextNavigationRenderId,
209
+ startedNavigationId,
210
+ type: "navigate"
211
+ });
212
+ if (disposition === "hard-navigate") {
213
+ window.location.assign(window.location.href);
214
+ return;
215
+ }
216
+ if (disposition === "dispatch") dispatchBrowserTree(pending.action.elements, navigationSnapshot, pending.action.renderId, "navigate", pending.interceptionContext, pending.action.layoutFlags, pending.previousNextUrl, pending.routeId, pending.rootLayoutTreePath, false);
217
+ if (returnValue) {
218
+ if (!returnValue.ok) throw returnValue.data;
219
+ return returnValue.data;
220
+ }
221
+ }
222
+ function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
223
+ const resolvedElements = use(initialElements);
224
+ const initialMetadata = readAppElementsMetadata(resolvedElements);
225
+ const [treeState, dispatchTreeState] = useReducer(routerReducer, {
226
+ elements: resolvedElements,
227
+ interceptionContext: initialMetadata.interceptionContext,
228
+ layoutFlags: initialMetadata.layoutFlags,
229
+ navigationSnapshot: initialNavigationSnapshot,
230
+ previousNextUrl: null,
142
231
  renderId: 0,
143
- node: use(initialNode),
144
- navigationSnapshot: initialNavigationSnapshot
232
+ rootLayoutTreePath: initialMetadata.rootLayoutTreePath,
233
+ routeId: initialMetadata.routeId
145
234
  });
235
+ const stateRef = useRef(treeState);
236
+ stateRef.current = treeState;
237
+ useLayoutEffect(() => {
238
+ dispatchBrowserRouterAction = dispatchTreeState;
239
+ browserRouterStateRef = stateRef;
240
+ return () => {
241
+ if (dispatchBrowserRouterAction === dispatchTreeState) dispatchBrowserRouterAction = null;
242
+ if (browserRouterStateRef === stateRef) browserRouterStateRef = null;
243
+ setMountedSlotsHeader(null);
244
+ };
245
+ }, [dispatchTreeState]);
246
+ useLayoutEffect(() => {
247
+ setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));
248
+ }, [treeState.elements]);
146
249
  useLayoutEffect(() => {
147
- setBrowserTreeState = setTreeState;
148
- }, []);
149
- const committedTree = createElement(NavigationCommitSignal, { renderId: treeState.renderId }, treeState.node);
250
+ if (treeState.renderId !== 0) return;
251
+ replaceHistoryStateWithoutNotify(createHistoryStateWithPreviousNextUrl(window.history.state, treeState.previousNextUrl), "", window.location.href);
252
+ }, [treeState.previousNextUrl, treeState.renderId]);
253
+ const committedTree = createElement(NavigationCommitSignal, { renderId: treeState.renderId }, createElement(ElementsContext.Provider, { value: treeState.elements }, createElement(Slot, { id: treeState.routeId })));
150
254
  const ClientNavigationRenderContext = getClientNavigationRenderContext();
151
255
  if (!ClientNavigationRenderContext) return committedTree;
152
256
  return createElement(ClientNavigationRenderContext.Provider, { value: treeState.navigationSnapshot }, committedTree);
153
257
  }
154
- function updateBrowserTree(node, navigationSnapshot, renderId, useTransitionMode, snapshotActivated = false) {
155
- const setter = getBrowserTreeStateSetter();
156
- const resolvedThenSet = (resolvedNode) => {
157
- setter({
158
- renderId,
159
- node: resolvedNode,
160
- navigationSnapshot
161
- });
162
- };
163
- const handleAsyncError = () => {
164
- pendingNavigationPrePaintEffects.delete(renderId);
165
- const resolve = pendingNavigationCommits.get(renderId);
166
- pendingNavigationCommits.delete(renderId);
167
- if (snapshotActivated) commitClientNavigationState();
168
- resolve?.();
169
- };
170
- if (node != null && typeof node.then === "function") {
171
- const thenable = node;
172
- if (useTransitionMode) thenable.then((resolved) => startTransition(() => resolvedThenSet(resolved)), handleAsyncError);
173
- else thenable.then(resolvedThenSet, handleAsyncError);
174
- return;
175
- }
176
- const syncNode = node;
177
- if (useTransitionMode) {
178
- startTransition(() => resolvedThenSet(syncNode));
179
- return;
180
- }
181
- resolvedThenSet(syncNode);
258
+ function dispatchBrowserTree(elements, navigationSnapshot, renderId, actionType, interceptionContext, layoutFlags, previousNextUrl, routeId, rootLayoutTreePath, useTransitionMode) {
259
+ const dispatch = getBrowserRouterDispatch();
260
+ const applyAction = () => dispatch({
261
+ elements,
262
+ interceptionContext,
263
+ layoutFlags,
264
+ navigationSnapshot,
265
+ previousNextUrl,
266
+ renderId,
267
+ rootLayoutTreePath,
268
+ routeId,
269
+ type: actionType
270
+ });
271
+ if (useTransitionMode) startTransition(applyAction);
272
+ else applyAction();
182
273
  }
183
- function renderNavigationPayload(payload, navigationSnapshot, prePaintEffect = null, useTransition = true) {
274
+ async function renderNavigationPayload(payload, navigationSnapshot, targetHref, navId, historyUpdateMode, params, previousNextUrl, useTransition = true, actionType = "navigate") {
184
275
  const renderId = ++nextNavigationRenderId;
185
- queuePrePaintNavigationEffect(renderId, prePaintEffect);
186
276
  const committed = new Promise((resolve) => {
187
277
  pendingNavigationCommits.set(renderId, resolve);
188
278
  });
189
- activateNavigationSnapshot();
279
+ let snapshotActivated = false;
190
280
  try {
191
- updateBrowserTree(payload, navigationSnapshot, renderId, useTransition, true);
281
+ const currentState = getBrowserRouterState();
282
+ const pending = await createPendingNavigationCommit({
283
+ currentState,
284
+ nextElements: payload,
285
+ navigationSnapshot,
286
+ previousNextUrl,
287
+ renderId,
288
+ type: actionType
289
+ });
290
+ const disposition = resolvePendingNavigationCommitDisposition({
291
+ activeNavigationId,
292
+ currentRootLayoutTreePath: currentState.rootLayoutTreePath,
293
+ nextRootLayoutTreePath: pending.rootLayoutTreePath,
294
+ startedNavigationId: navId
295
+ });
296
+ if (disposition === "skip") {
297
+ const resolve = pendingNavigationCommits.get(renderId);
298
+ pendingNavigationCommits.delete(renderId);
299
+ resolve?.();
300
+ return;
301
+ }
302
+ if (disposition === "hard-navigate") {
303
+ pendingNavigationCommits.delete(renderId);
304
+ window.location.assign(targetHref);
305
+ return;
306
+ }
307
+ queuePrePaintNavigationEffect(renderId, createNavigationCommitEffect(targetHref, historyUpdateMode, navId, params, pending.previousNextUrl));
308
+ activateNavigationSnapshot();
309
+ snapshotActivated = true;
310
+ dispatchBrowserTree(pending.action.elements, navigationSnapshot, renderId, actionType, pending.interceptionContext, pending.action.layoutFlags, pending.previousNextUrl, pending.routeId, pending.rootLayoutTreePath, useTransition);
192
311
  } catch (error) {
193
312
  pendingNavigationPrePaintEffects.delete(renderId);
194
313
  const resolve = pendingNavigationCommits.get(renderId);
195
314
  pendingNavigationCommits.delete(renderId);
196
- commitClientNavigationState();
315
+ if (snapshotActivated) commitClientNavigationState(navId);
197
316
  resolve?.();
198
317
  throw error;
199
318
  }
@@ -245,9 +364,16 @@ function registerServerActionCallback() {
245
364
  setServerCallback(async (id, args) => {
246
365
  const temporaryReferences = createTemporaryReferenceSet();
247
366
  const body = await encodeReply(args, { temporaryReferences });
367
+ const currentState = getBrowserRouterState();
368
+ const { headers } = resolveServerActionRequestState({
369
+ actionId: id,
370
+ basePath: __basePath,
371
+ elements: currentState.elements,
372
+ previousNextUrl: currentState.previousNextUrl
373
+ });
248
374
  const fetchResponse = await fetch(toRscUrl(window.location.pathname + window.location.search), {
249
375
  method: "POST",
250
- headers: { "x-rsc-action": id },
376
+ headers,
251
377
  body
252
378
  });
253
379
  const actionRedirect = fetchResponse.headers.get("x-action-redirect");
@@ -264,28 +390,21 @@ function registerServerActionCallback() {
264
390
  }
265
391
  clearClientNavigationCaches();
266
392
  const result = await createFromFetch(Promise.resolve(fetchResponse), { temporaryReferences });
267
- if (isServerActionResult(result)) {
268
- updateBrowserTree(result.root, createClientNavigationRenderSnapshot(window.location.href, latestClientParams), ++nextNavigationRenderId, false);
269
- if (result.returnValue) {
270
- if (!result.returnValue.ok) throw result.returnValue.data;
271
- return result.returnValue.data;
272
- }
273
- return;
274
- }
275
- updateBrowserTree(result, createClientNavigationRenderSnapshot(window.location.href, latestClientParams), ++nextNavigationRenderId, false);
276
- return result;
393
+ if (isServerActionResult(result)) return commitSameUrlNavigatePayload(Promise.resolve(normalizeAppElements(result.root)), result.returnValue);
394
+ return commitSameUrlNavigatePayload(Promise.resolve(normalizeAppElements(result)));
277
395
  });
278
396
  }
279
397
  async function main() {
280
398
  registerServerActionCallback();
281
- const root = createFromReadableStream(await readInitialRscStream());
399
+ const root = normalizeAppElementsPromise(createFromReadableStream(await readInitialRscStream()));
282
400
  const initialNavigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
401
+ replaceHistoryStateWithoutNotify(createHistoryStateWithPreviousNextUrl(window.history.state, null), "", window.location.href);
283
402
  window.__VINEXT_RSC_ROOT__ = hydrateRoot(document, createElement(BrowserRoot, {
284
- initialNode: root,
403
+ initialElements: root,
285
404
  initialNavigationSnapshot
286
- }), import.meta.env.DEV ? { onCaughtError() {} } : void 0);
405
+ }), import.meta.env.DEV ? { onCaughtError: devOnCaughtError } : void 0);
287
406
  window.__VINEXT_HYDRATED_AT = performance.now();
288
- window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(href, redirectDepth = 0, navigationKind = "navigate", historyUpdateMode) {
407
+ window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(href, redirectDepth = 0, navigationKind = "navigate", historyUpdateMode, previousNextUrlOverride) {
289
408
  if (redirectDepth > 10) {
290
409
  console.error("[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.");
291
410
  window.location.href = href;
@@ -296,19 +415,25 @@ async function main() {
296
415
  try {
297
416
  const url = new URL(href, window.location.origin);
298
417
  const rscUrl = toRscUrl(url.pathname + url.search);
299
- const isSameRoute = stripBasePath(url.pathname, __basePath) === stripBasePath(window.location.pathname, __basePath);
300
- const cachedRoute = getVisitedResponse(rscUrl, navigationKind);
301
- const navigationCommitEffect = createNavigationCommitEffect(href, historyUpdateMode);
418
+ const requestState = getRequestState(navigationKind, previousNextUrlOverride);
419
+ const requestInterceptionContext = requestState.interceptionContext;
420
+ const requestPreviousNextUrl = requestState.previousNextUrl;
421
+ const navState = getClientNavigationState();
422
+ const currentPath = navState?.pendingPathname ?? navState?.cachedPathname ?? stripBasePath(window.location.pathname, __basePath);
423
+ const isSameRoute = stripBasePath(url.pathname, __basePath) === currentPath;
424
+ setPendingPathname(url.pathname, navId);
425
+ const elementsAtNavStart = getBrowserRouterState().elements;
426
+ const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);
427
+ const cachedRoute = getVisitedResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader, navigationKind);
302
428
  if (cachedRoute) {
303
429
  if (navId !== activeNavigationId) return;
304
430
  const cachedParams = cachedRoute.params;
305
431
  const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(href, cachedParams);
306
- const cachedPayload = await createFromFetch(Promise.resolve(restoreRscResponse(cachedRoute.response)));
432
+ const cachedPayload = normalizeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(cachedRoute.response))));
307
433
  if (navId !== activeNavigationId) return;
308
434
  _snapshotPending = true;
309
- stageClientParams(cachedParams);
310
435
  try {
311
- await renderNavigationPayload(cachedPayload, cachedNavigationSnapshot, navigationCommitEffect, isSameRoute);
436
+ await renderNavigationPayload(cachedPayload, cachedNavigationSnapshot, href, navId, historyUpdateMode, cachedParams, requestPreviousNextUrl, isSameRoute, toActionType(navigationKind));
312
437
  } finally {
313
438
  _snapshotPending = false;
314
439
  }
@@ -317,28 +442,32 @@ async function main() {
317
442
  let navResponse;
318
443
  let navResponseUrl = null;
319
444
  if (navigationKind !== "refresh") {
320
- const prefetchedResponse = consumePrefetchResponse(rscUrl);
445
+ const prefetchedResponse = consumePrefetchResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader);
321
446
  if (prefetchedResponse) {
322
447
  navResponse = restoreRscResponse(prefetchedResponse, false);
323
448
  navResponseUrl = prefetchedResponse.url;
324
449
  }
325
450
  }
326
- if (!navResponse) navResponse = await fetch(rscUrl, {
327
- headers: { Accept: "text/x-component" },
328
- credentials: "include"
329
- });
451
+ if (!navResponse) {
452
+ const requestHeaders = createRscRequestHeaders(requestInterceptionContext);
453
+ if (mountedSlotsHeader) requestHeaders.set("X-Vinext-Mounted-Slots", mountedSlotsHeader);
454
+ navResponse = await fetch(rscUrl, {
455
+ headers: requestHeaders,
456
+ credentials: "include"
457
+ });
458
+ }
330
459
  if (navId !== activeNavigationId) return;
331
460
  const finalUrl = new URL(navResponseUrl ?? navResponse.url, window.location.origin);
332
461
  const requestedUrl = new URL(rscUrl, window.location.origin);
333
462
  if (finalUrl.pathname !== requestedUrl.pathname) {
334
463
  const destinationPath = finalUrl.pathname.replace(/\.rsc$/, "") + finalUrl.search;
335
- replaceHistoryStateWithoutNotify(null, "", destinationPath);
464
+ replaceHistoryStateWithoutNotify(createHistoryStateWithPreviousNextUrl(null, requestPreviousNextUrl), "", destinationPath);
336
465
  const navigate = window.__VINEXT_RSC_NAVIGATE__;
337
466
  if (!navigate) {
338
467
  window.location.href = destinationPath;
339
468
  return;
340
469
  }
341
- return navigate(destinationPath, redirectDepth + 1, navigationKind, void 0);
470
+ return navigate(destinationPath, redirectDepth + 1, navigationKind, void 0, requestPreviousNextUrl);
342
471
  }
343
472
  let navParams = {};
344
473
  const paramsHeader = navResponse.headers.get("X-Vinext-Params");
@@ -348,22 +477,23 @@ async function main() {
348
477
  const navigationSnapshot = createClientNavigationRenderSnapshot(href, navParams);
349
478
  const responseSnapshot = await snapshotRscResponse(navResponse);
350
479
  if (navId !== activeNavigationId) return;
351
- const rscPayload = await createFromFetch(Promise.resolve(restoreRscResponse(responseSnapshot)));
480
+ const rscPayload = normalizeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(responseSnapshot))));
352
481
  if (navId !== activeNavigationId) return;
353
482
  _snapshotPending = true;
354
- stageClientParams(navParams);
355
483
  try {
356
- await renderNavigationPayload(rscPayload, navigationSnapshot, navigationCommitEffect, isSameRoute);
484
+ await renderNavigationPayload(rscPayload, navigationSnapshot, href, navId, historyUpdateMode, navParams, requestPreviousNextUrl, isSameRoute, toActionType(navigationKind));
357
485
  } finally {
358
486
  _snapshotPending = false;
359
487
  }
360
- storeVisitedResponseSnapshot(rscUrl, responseSnapshot, navParams);
488
+ if (navId !== activeNavigationId) return;
489
+ storeVisitedResponseSnapshot(rscUrl, resolveVisitedResponseInterceptionContext(requestInterceptionContext, readAppElementsMetadata(await rscPayload).interceptionContext), responseSnapshot, navParams);
361
490
  return;
362
491
  } catch (error) {
363
492
  if (_snapshotPending) {
364
493
  _snapshotPending = false;
365
- commitClientNavigationState();
494
+ commitClientNavigationState(navId);
366
495
  }
496
+ if (navId === activeNavigationId) clearPendingPathname(navId);
367
497
  if (navId !== activeNavigationId) return;
368
498
  console.error("[vinext] RSC navigation error:", error);
369
499
  window.location.href = href;
@@ -382,13 +512,21 @@ async function main() {
382
512
  if (import.meta.hot) import.meta.hot.on("rsc:update", async () => {
383
513
  try {
384
514
  clearClientNavigationCaches();
385
- updateBrowserTree(await createFromFetch(fetch(toRscUrl(window.location.pathname + window.location.search))), createClientNavigationRenderSnapshot(window.location.href, latestClientParams), ++nextNavigationRenderId, false);
515
+ const navigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
516
+ const pending = await createPendingNavigationCommit({
517
+ currentState: getBrowserRouterState(),
518
+ nextElements: normalizeAppElementsPromise(createFromFetch(fetch(toRscUrl(window.location.pathname + window.location.search)))),
519
+ navigationSnapshot,
520
+ renderId: ++nextNavigationRenderId,
521
+ type: "replace"
522
+ });
523
+ dispatchBrowserTree(pending.action.elements, navigationSnapshot, pending.action.renderId, "replace", pending.interceptionContext, pending.action.layoutFlags, pending.previousNextUrl, pending.routeId, pending.rootLayoutTreePath, false);
386
524
  } catch (error) {
387
525
  console.error("[vinext] RSC HMR error:", error);
388
526
  }
389
527
  });
390
528
  }
391
- main();
529
+ if (typeof document !== "undefined") main();
392
530
  //#endregion
393
531
  export {};
394
532