vinext 0.0.41 → 0.0.43

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 (166) 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 +315 -101
  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 +44 -25
  42. package/dist/routing/app-router.js.map +1 -1
  43. package/dist/server/app-browser-entry.js +307 -100
  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-policy.js +5 -3
  85. package/dist/server/app-route-handler-policy.js.map +1 -1
  86. package/dist/server/app-route-handler-response.js +2 -0
  87. package/dist/server/app-route-handler-response.js.map +1 -1
  88. package/dist/server/app-route-handler-runtime.d.ts +1 -0
  89. package/dist/server/app-route-handler-runtime.js +26 -1
  90. package/dist/server/app-route-handler-runtime.js.map +1 -1
  91. package/dist/server/app-ssr-entry.js +6 -2
  92. package/dist/server/app-ssr-entry.js.map +1 -1
  93. package/dist/server/dev-server.js +2 -4
  94. package/dist/server/dev-server.js.map +1 -1
  95. package/dist/server/middleware.js +1 -5
  96. package/dist/server/middleware.js.map +1 -1
  97. package/dist/server/prod-server.d.ts +3 -3
  98. package/dist/server/prod-server.js +1 -1
  99. package/dist/server/prod-server.js.map +1 -1
  100. package/dist/server/request-pipeline.d.ts +2 -1
  101. package/dist/server/request-pipeline.js +34 -5
  102. package/dist/server/request-pipeline.js.map +1 -1
  103. package/dist/shims/cache-runtime.d.ts +1 -0
  104. package/dist/shims/cache-runtime.js +0 -5
  105. package/dist/shims/cache-runtime.js.map +1 -1
  106. package/dist/shims/cache.d.ts +1 -0
  107. package/dist/shims/cache.js +1 -8
  108. package/dist/shims/cache.js.map +1 -1
  109. package/dist/shims/client-hook-error.d.ts +14 -0
  110. package/dist/shims/client-hook-error.js +19 -0
  111. package/dist/shims/client-hook-error.js.map +1 -0
  112. package/dist/shims/constants.d.ts +3 -3
  113. package/dist/shims/constants.js +3 -3
  114. package/dist/shims/constants.js.map +1 -1
  115. package/dist/shims/document.d.ts +6 -6
  116. package/dist/shims/error-boundary.d.ts +4 -4
  117. package/dist/shims/error-boundary.js +1 -1
  118. package/dist/shims/error-boundary.js.map +1 -1
  119. package/dist/shims/form.d.ts +3 -3
  120. package/dist/shims/head-state.d.ts +1 -0
  121. package/dist/shims/head-state.js +0 -5
  122. package/dist/shims/head-state.js.map +1 -1
  123. package/dist/shims/headers.d.ts +11 -0
  124. package/dist/shims/headers.js +13 -10
  125. package/dist/shims/headers.js.map +1 -1
  126. package/dist/shims/i18n-state.d.ts +1 -0
  127. package/dist/shims/i18n-state.js +0 -4
  128. package/dist/shims/i18n-state.js.map +1 -1
  129. package/dist/shims/internal/app-router-context.d.ts +6 -6
  130. package/dist/shims/internal/router-context.d.ts +2 -2
  131. package/dist/shims/layout-segment-context.d.ts +2 -2
  132. package/dist/shims/link.js +19 -11
  133. package/dist/shims/link.js.map +1 -1
  134. package/dist/shims/metadata.d.ts +3 -3
  135. package/dist/shims/navigation-state.d.ts +2 -0
  136. package/dist/shims/navigation-state.js +0 -13
  137. package/dist/shims/navigation-state.js.map +1 -1
  138. package/dist/shims/navigation.d.ts +56 -9
  139. package/dist/shims/navigation.js +112 -28
  140. package/dist/shims/navigation.js.map +1 -1
  141. package/dist/shims/navigation.react-server.d.ts +14 -0
  142. package/dist/shims/navigation.react-server.js +29 -0
  143. package/dist/shims/navigation.react-server.js.map +1 -0
  144. package/dist/shims/request-context.d.ts +1 -0
  145. package/dist/shims/request-context.js +0 -9
  146. package/dist/shims/request-context.js.map +1 -1
  147. package/dist/shims/request-state-types.d.ts +1 -1
  148. package/dist/shims/router-state.d.ts +1 -0
  149. package/dist/shims/router-state.js +0 -5
  150. package/dist/shims/router-state.js.map +1 -1
  151. package/dist/shims/slot.d.ts +11 -7
  152. package/dist/shims/slot.js +28 -19
  153. package/dist/shims/slot.js.map +1 -1
  154. package/dist/shims/unified-request-context.d.ts +2 -0
  155. package/dist/shims/unified-request-context.js +0 -14
  156. package/dist/shims/unified-request-context.js.map +1 -1
  157. package/dist/utils/mdx-scan.d.ts +10 -0
  158. package/dist/utils/mdx-scan.js +36 -0
  159. package/dist/utils/mdx-scan.js.map +1 -0
  160. package/dist/utils/public-routes.d.ts +5 -0
  161. package/dist/utils/public-routes.js +50 -0
  162. package/dist/utils/public-routes.js.map +1 -0
  163. package/package.json +3 -3
  164. package/dist/plugins/fix-use-server-closure-collision.d.ts +0 -29
  165. package/dist/plugins/fix-use-server-closure-collision.js +0 -204
  166. 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, useRef, useState } 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,55 @@ 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
+ function isRouterStatePromise(value) {
25
+ return value instanceof Promise;
26
+ }
27
+ let setBrowserRouterState = null;
28
+ let browserRouterStateRef = null;
29
+ let activePendingBrowserRouterState = null;
18
30
  let latestClientParams = {};
19
31
  const visitedResponseCache = /* @__PURE__ */ new Map();
20
32
  function isServerActionResult(value) {
21
33
  return !!value && typeof value === "object" && "root" in value;
22
34
  }
23
- function getBrowserTreeStateSetter() {
24
- if (!setBrowserTreeState) throw new Error("[vinext] Browser tree state is not initialized");
25
- return setBrowserTreeState;
35
+ function getBrowserRouterStateSetter() {
36
+ if (!setBrowserRouterState) throw new Error("[vinext] Browser router state setter is not initialized");
37
+ return setBrowserRouterState;
38
+ }
39
+ function getBrowserRouterState() {
40
+ if (!browserRouterStateRef) throw new Error("[vinext] Browser router state is not initialized");
41
+ return browserRouterStateRef.current;
42
+ }
43
+ function beginPendingBrowserRouterState() {
44
+ const setter = getBrowserRouterStateSetter();
45
+ if (activePendingBrowserRouterState && !activePendingBrowserRouterState.settled) {
46
+ activePendingBrowserRouterState.settled = true;
47
+ activePendingBrowserRouterState.resolve(getBrowserRouterState());
48
+ }
49
+ let resolve;
50
+ const promise = new Promise((resolvePromise) => {
51
+ resolve = resolvePromise;
52
+ });
53
+ const pending = {
54
+ promise,
55
+ resolve,
56
+ settled: false
57
+ };
58
+ activePendingBrowserRouterState = pending;
59
+ setter(promise);
60
+ return pending;
61
+ }
62
+ function settlePendingBrowserRouterState(pending) {
63
+ if (!pending || pending.settled) return;
64
+ pending.settled = true;
65
+ pending.resolve(getBrowserRouterState());
66
+ if (activePendingBrowserRouterState === pending) activePendingBrowserRouterState = null;
67
+ }
68
+ function resolvePendingBrowserRouterState(pending, action) {
69
+ if (!pending || pending.settled) return;
70
+ pending.settled = true;
71
+ pending.resolve(routerReducer(getBrowserRouterState(), action));
72
+ if (activePendingBrowserRouterState === pending) activePendingBrowserRouterState = null;
26
73
  }
27
74
  function applyClientParams(params) {
28
75
  latestClientParams = params;
@@ -62,15 +109,21 @@ function drainPrePaintEffects(upToRenderId) {
62
109
  for (const [id, effect] of pendingNavigationPrePaintEffects) if (id <= upToRenderId) {
63
110
  pendingNavigationPrePaintEffects.delete(id);
64
111
  if (id === upToRenderId) effect();
65
- else commitClientNavigationState();
112
+ else commitClientNavigationState(void 0);
66
113
  }
67
114
  }
68
- function createNavigationCommitEffect(href, historyUpdateMode) {
115
+ function createNavigationCommitEffect(href, historyUpdateMode, navId, params, previousNextUrl) {
69
116
  return () => {
117
+ if (navId !== activeNavigationId) {
118
+ commitClientNavigationState(void 0);
119
+ return;
120
+ }
70
121
  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();
122
+ stageClientParams(params);
123
+ const historyState = createHistoryStateWithPreviousNextUrl(historyUpdateMode === "replace" ? window.history.state : null, previousNextUrl);
124
+ if (historyUpdateMode === "replace" && window.location.href !== targetHref) replaceHistoryStateWithoutNotify(historyState, "", href);
125
+ else if (historyUpdateMode === "push" && window.location.href !== targetHref) pushHistoryStateWithoutNotify(historyState, "", href);
126
+ commitClientNavigationState(navId);
74
127
  };
75
128
  }
76
129
  function evictVisitedResponseCacheIfNeeded() {
@@ -80,38 +133,76 @@ function evictVisitedResponseCacheIfNeeded() {
80
133
  visitedResponseCache.delete(oldest);
81
134
  }
82
135
  }
83
- function getVisitedResponse(rscUrl, navigationKind) {
84
- const cached = visitedResponseCache.get(rscUrl);
136
+ function getVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, navigationKind) {
137
+ const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);
138
+ const cached = visitedResponseCache.get(cacheKey);
85
139
  if (!cached) return null;
140
+ if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {
141
+ visitedResponseCache.delete(cacheKey);
142
+ return null;
143
+ }
86
144
  if (navigationKind === "refresh") return null;
87
145
  if (navigationKind === "traverse") {
88
146
  const createdAt = cached.expiresAt - VISITED_RESPONSE_CACHE_TTL;
89
147
  if (Date.now() - createdAt >= MAX_TRAVERSAL_CACHE_TTL) {
90
- visitedResponseCache.delete(rscUrl);
148
+ visitedResponseCache.delete(cacheKey);
91
149
  return null;
92
150
  }
93
- visitedResponseCache.delete(rscUrl);
94
- visitedResponseCache.set(rscUrl, cached);
151
+ visitedResponseCache.delete(cacheKey);
152
+ visitedResponseCache.set(cacheKey, cached);
95
153
  return cached;
96
154
  }
97
155
  if (cached.expiresAt > Date.now()) {
98
- visitedResponseCache.delete(rscUrl);
99
- visitedResponseCache.set(rscUrl, cached);
156
+ visitedResponseCache.delete(cacheKey);
157
+ visitedResponseCache.set(cacheKey, cached);
100
158
  return cached;
101
159
  }
102
- visitedResponseCache.delete(rscUrl);
160
+ visitedResponseCache.delete(cacheKey);
103
161
  return null;
104
162
  }
105
- function storeVisitedResponseSnapshot(rscUrl, snapshot, params) {
106
- visitedResponseCache.delete(rscUrl);
163
+ function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, params) {
164
+ const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);
165
+ visitedResponseCache.delete(cacheKey);
107
166
  evictVisitedResponseCacheIfNeeded();
108
167
  const now = Date.now();
109
- visitedResponseCache.set(rscUrl, {
168
+ visitedResponseCache.set(cacheKey, {
110
169
  params,
111
170
  expiresAt: now + VISITED_RESPONSE_CACHE_TTL,
112
171
  response: snapshot
113
172
  });
114
173
  }
174
+ function getRequestState(navigationKind, previousNextUrlOverride) {
175
+ if (previousNextUrlOverride !== void 0) return {
176
+ interceptionContext: resolveInterceptionContextFromPreviousNextUrl(previousNextUrlOverride, __basePath),
177
+ previousNextUrl: previousNextUrlOverride
178
+ };
179
+ switch (navigationKind) {
180
+ case "navigate": return {
181
+ interceptionContext: getCurrentInterceptionContext(),
182
+ previousNextUrl: getCurrentNextUrl()
183
+ };
184
+ case "traverse": {
185
+ const previousNextUrl = readHistoryStatePreviousNextUrl(window.history.state);
186
+ return {
187
+ interceptionContext: resolveInterceptionContextFromPreviousNextUrl(previousNextUrl, __basePath),
188
+ previousNextUrl
189
+ };
190
+ }
191
+ case "refresh": {
192
+ const currentPreviousNextUrl = getBrowserRouterState().previousNextUrl;
193
+ return {
194
+ interceptionContext: resolveInterceptionContextFromPreviousNextUrl(currentPreviousNextUrl, __basePath),
195
+ previousNextUrl: currentPreviousNextUrl
196
+ };
197
+ }
198
+ default: throw new Error("[vinext] Unknown navigation kind: " + String(navigationKind));
199
+ }
200
+ }
201
+ function createRscRequestHeaders(interceptionContext) {
202
+ const headers = new Headers({ Accept: "text/x-component" });
203
+ if (interceptionContext !== null) headers.set("X-Vinext-Interception-Context", interceptionContext);
204
+ return headers;
205
+ }
115
206
  /**
116
207
  * Resolve all pending navigation commits with renderId <= the committed renderId.
117
208
  * Note: Map iteration handles concurrent deletion safely — entries are visited in
@@ -137,63 +228,137 @@ function NavigationCommitSignal({ renderId, children }) {
137
228
  }, [renderId]);
138
229
  return children;
139
230
  }
140
- function BrowserRoot({ initialNode, initialNavigationSnapshot }) {
141
- const [treeState, setTreeState] = useState({
231
+ function normalizeAppElementsPromise(payload) {
232
+ return Promise.resolve(payload).then((elements) => normalizeAppElements(elements));
233
+ }
234
+ async function commitSameUrlNavigatePayload(nextElements, returnValue) {
235
+ const navigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
236
+ const currentState = getBrowserRouterState();
237
+ const startedNavigationId = activeNavigationId;
238
+ const { disposition, pending } = await resolveAndClassifyNavigationCommit({
239
+ activeNavigationId,
240
+ currentState,
241
+ navigationSnapshot,
242
+ nextElements,
243
+ renderId: ++nextNavigationRenderId,
244
+ startedNavigationId,
245
+ type: "navigate"
246
+ });
247
+ if (disposition === "hard-navigate") {
248
+ window.location.assign(window.location.href);
249
+ return;
250
+ }
251
+ if (disposition === "dispatch") dispatchBrowserTree(pending.action.elements, navigationSnapshot, pending.action.renderId, "navigate", pending.interceptionContext, pending.action.layoutFlags, pending.previousNextUrl, pending.routeId, pending.rootLayoutTreePath, null, false);
252
+ if (returnValue) {
253
+ if (!returnValue.ok) throw returnValue.data;
254
+ return returnValue.data;
255
+ }
256
+ }
257
+ function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
258
+ const resolvedElements = use(initialElements);
259
+ const initialMetadata = readAppElementsMetadata(resolvedElements);
260
+ const [treeStateValue, setTreeStateValue] = useState({
261
+ elements: resolvedElements,
262
+ interceptionContext: initialMetadata.interceptionContext,
263
+ layoutFlags: initialMetadata.layoutFlags,
264
+ navigationSnapshot: initialNavigationSnapshot,
265
+ previousNextUrl: null,
142
266
  renderId: 0,
143
- node: use(initialNode),
144
- navigationSnapshot: initialNavigationSnapshot
267
+ rootLayoutTreePath: initialMetadata.rootLayoutTreePath,
268
+ routeId: initialMetadata.routeId
145
269
  });
270
+ const treeState = isRouterStatePromise(treeStateValue) ? use(treeStateValue) : treeStateValue;
271
+ const stateRef = useRef(treeState);
272
+ stateRef.current = treeState;
146
273
  useLayoutEffect(() => {
147
- setBrowserTreeState = setTreeState;
148
- }, []);
149
- const committedTree = createElement(NavigationCommitSignal, { renderId: treeState.renderId }, treeState.node);
274
+ setBrowserRouterState = setTreeStateValue;
275
+ browserRouterStateRef = stateRef;
276
+ return () => {
277
+ if (setBrowserRouterState === setTreeStateValue) setBrowserRouterState = null;
278
+ if (browserRouterStateRef === stateRef) browserRouterStateRef = null;
279
+ setMountedSlotsHeader(null);
280
+ };
281
+ }, [setTreeStateValue]);
282
+ useLayoutEffect(() => {
283
+ setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));
284
+ }, [treeState.elements]);
285
+ useLayoutEffect(() => {
286
+ if (treeState.renderId !== 0) return;
287
+ replaceHistoryStateWithoutNotify(createHistoryStateWithPreviousNextUrl(window.history.state, treeState.previousNextUrl), "", window.location.href);
288
+ }, [treeState.previousNextUrl, treeState.renderId]);
289
+ const committedTree = createElement(NavigationCommitSignal, { renderId: treeState.renderId }, createElement(ElementsContext.Provider, { value: treeState.elements }, createElement(Slot, { id: treeState.routeId })));
150
290
  const ClientNavigationRenderContext = getClientNavigationRenderContext();
151
291
  if (!ClientNavigationRenderContext) return committedTree;
152
292
  return createElement(ClientNavigationRenderContext.Provider, { value: treeState.navigationSnapshot }, committedTree);
153
293
  }
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
- });
294
+ function dispatchBrowserTree(elements, navigationSnapshot, renderId, actionType, interceptionContext, layoutFlags, previousNextUrl, routeId, rootLayoutTreePath, pendingRouterState, useTransitionMode) {
295
+ const setter = getBrowserRouterStateSetter();
296
+ const action = {
297
+ elements,
298
+ interceptionContext,
299
+ layoutFlags,
300
+ navigationSnapshot,
301
+ previousNextUrl,
302
+ renderId,
303
+ rootLayoutTreePath,
304
+ routeId,
305
+ type: actionType
162
306
  };
163
- const handleAsyncError = () => {
164
- pendingNavigationPrePaintEffects.delete(renderId);
165
- const resolve = pendingNavigationCommits.get(renderId);
166
- pendingNavigationCommits.delete(renderId);
167
- if (snapshotActivated) commitClientNavigationState();
168
- resolve?.();
307
+ const applyAction = () => {
308
+ if (pendingRouterState) {
309
+ resolvePendingBrowserRouterState(pendingRouterState, action);
310
+ return;
311
+ }
312
+ setter(routerReducer(getBrowserRouterState(), action));
169
313
  };
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);
314
+ if (useTransitionMode) startTransition(applyAction);
315
+ else applyAction();
182
316
  }
183
- function renderNavigationPayload(payload, navigationSnapshot, prePaintEffect = null, useTransition = true) {
317
+ async function renderNavigationPayload(payload, navigationSnapshot, targetHref, navId, historyUpdateMode, params, previousNextUrl, pendingRouterState, useTransition = true, actionType = "navigate") {
184
318
  const renderId = ++nextNavigationRenderId;
185
- queuePrePaintNavigationEffect(renderId, prePaintEffect);
186
319
  const committed = new Promise((resolve) => {
187
320
  pendingNavigationCommits.set(renderId, resolve);
188
321
  });
189
- activateNavigationSnapshot();
322
+ let snapshotActivated = false;
190
323
  try {
191
- updateBrowserTree(payload, navigationSnapshot, renderId, useTransition, true);
324
+ const currentState = getBrowserRouterState();
325
+ const pending = await createPendingNavigationCommit({
326
+ currentState,
327
+ nextElements: payload,
328
+ navigationSnapshot,
329
+ previousNextUrl,
330
+ renderId,
331
+ type: actionType
332
+ });
333
+ const disposition = resolvePendingNavigationCommitDisposition({
334
+ activeNavigationId,
335
+ currentRootLayoutTreePath: currentState.rootLayoutTreePath,
336
+ nextRootLayoutTreePath: pending.rootLayoutTreePath,
337
+ startedNavigationId: navId
338
+ });
339
+ if (disposition === "skip") {
340
+ settlePendingBrowserRouterState(pendingRouterState);
341
+ const resolve = pendingNavigationCommits.get(renderId);
342
+ pendingNavigationCommits.delete(renderId);
343
+ resolve?.();
344
+ return;
345
+ }
346
+ if (disposition === "hard-navigate") {
347
+ settlePendingBrowserRouterState(pendingRouterState);
348
+ pendingNavigationCommits.delete(renderId);
349
+ window.location.assign(targetHref);
350
+ return;
351
+ }
352
+ queuePrePaintNavigationEffect(renderId, createNavigationCommitEffect(targetHref, historyUpdateMode, navId, params, pending.previousNextUrl));
353
+ activateNavigationSnapshot();
354
+ snapshotActivated = true;
355
+ dispatchBrowserTree(pending.action.elements, navigationSnapshot, renderId, actionType, pending.interceptionContext, pending.action.layoutFlags, pending.previousNextUrl, pending.routeId, pending.rootLayoutTreePath, pendingRouterState, useTransition);
192
356
  } catch (error) {
193
357
  pendingNavigationPrePaintEffects.delete(renderId);
194
358
  const resolve = pendingNavigationCommits.get(renderId);
195
359
  pendingNavigationCommits.delete(renderId);
196
- commitClientNavigationState();
360
+ if (snapshotActivated) commitClientNavigationState(navId);
361
+ settlePendingBrowserRouterState(pendingRouterState);
197
362
  resolve?.();
198
363
  throw error;
199
364
  }
@@ -245,9 +410,16 @@ function registerServerActionCallback() {
245
410
  setServerCallback(async (id, args) => {
246
411
  const temporaryReferences = createTemporaryReferenceSet();
247
412
  const body = await encodeReply(args, { temporaryReferences });
413
+ const currentState = getBrowserRouterState();
414
+ const { headers } = resolveServerActionRequestState({
415
+ actionId: id,
416
+ basePath: __basePath,
417
+ elements: currentState.elements,
418
+ previousNextUrl: currentState.previousNextUrl
419
+ });
248
420
  const fetchResponse = await fetch(toRscUrl(window.location.pathname + window.location.search), {
249
421
  method: "POST",
250
- headers: { "x-rsc-action": id },
422
+ headers,
251
423
  body
252
424
  });
253
425
  const actionRedirect = fetchResponse.headers.get("x-action-redirect");
@@ -264,51 +436,58 @@ function registerServerActionCallback() {
264
436
  }
265
437
  clearClientNavigationCaches();
266
438
  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;
439
+ if (isServerActionResult(result)) return commitSameUrlNavigatePayload(Promise.resolve(normalizeAppElements(result.root)), result.returnValue);
440
+ return commitSameUrlNavigatePayload(Promise.resolve(normalizeAppElements(result)));
277
441
  });
278
442
  }
279
443
  async function main() {
280
444
  registerServerActionCallback();
281
- const root = createFromReadableStream(await readInitialRscStream());
445
+ const root = normalizeAppElementsPromise(createFromReadableStream(await readInitialRscStream()));
282
446
  const initialNavigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
447
+ replaceHistoryStateWithoutNotify(createHistoryStateWithPreviousNextUrl(window.history.state, null), "", window.location.href);
283
448
  window.__VINEXT_RSC_ROOT__ = hydrateRoot(document, createElement(BrowserRoot, {
284
- initialNode: root,
449
+ initialElements: root,
285
450
  initialNavigationSnapshot
286
- }), import.meta.env.DEV ? { onCaughtError() {} } : void 0);
451
+ }), import.meta.env.DEV ? { onCaughtError: devOnCaughtError } : void 0);
287
452
  window.__VINEXT_HYDRATED_AT = performance.now();
288
- window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(href, redirectDepth = 0, navigationKind = "navigate", historyUpdateMode) {
453
+ window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(href, redirectDepth = 0, navigationKind = "navigate", historyUpdateMode, previousNextUrlOverride, programmaticTransition = false) {
289
454
  if (redirectDepth > 10) {
290
455
  console.error("[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.");
291
456
  window.location.href = href;
292
457
  return;
293
458
  }
294
459
  let _snapshotPending = false;
460
+ let pendingRouterState = null;
295
461
  const navId = ++activeNavigationId;
296
462
  try {
463
+ if (programmaticTransition) pendingRouterState = beginPendingBrowserRouterState();
297
464
  const url = new URL(href, window.location.origin);
298
465
  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);
466
+ const requestState = getRequestState(navigationKind, previousNextUrlOverride);
467
+ const requestInterceptionContext = requestState.interceptionContext;
468
+ const requestPreviousNextUrl = requestState.previousNextUrl;
469
+ const navState = getClientNavigationState();
470
+ const currentPath = navState?.pendingPathname ?? navState?.cachedPathname ?? stripBasePath(window.location.pathname, __basePath);
471
+ const isSameRoute = stripBasePath(url.pathname, __basePath) === currentPath;
472
+ setPendingPathname(url.pathname, navId);
473
+ const elementsAtNavStart = getBrowserRouterState().elements;
474
+ const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);
475
+ const cachedRoute = getVisitedResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader, navigationKind);
302
476
  if (cachedRoute) {
303
- if (navId !== activeNavigationId) return;
477
+ if (navId !== activeNavigationId) {
478
+ settlePendingBrowserRouterState(pendingRouterState);
479
+ return;
480
+ }
304
481
  const cachedParams = cachedRoute.params;
305
482
  const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(href, cachedParams);
306
- const cachedPayload = await createFromFetch(Promise.resolve(restoreRscResponse(cachedRoute.response)));
307
- if (navId !== activeNavigationId) return;
483
+ const cachedPayload = normalizeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(cachedRoute.response))));
484
+ if (navId !== activeNavigationId) {
485
+ settlePendingBrowserRouterState(pendingRouterState);
486
+ return;
487
+ }
308
488
  _snapshotPending = true;
309
- stageClientParams(cachedParams);
310
489
  try {
311
- await renderNavigationPayload(cachedPayload, cachedNavigationSnapshot, navigationCommitEffect, isSameRoute);
490
+ await renderNavigationPayload(cachedPayload, cachedNavigationSnapshot, href, navId, historyUpdateMode, cachedParams, requestPreviousNextUrl, pendingRouterState, isSameRoute, toActionType(navigationKind));
312
491
  } finally {
313
492
  _snapshotPending = false;
314
493
  }
@@ -317,28 +496,37 @@ async function main() {
317
496
  let navResponse;
318
497
  let navResponseUrl = null;
319
498
  if (navigationKind !== "refresh") {
320
- const prefetchedResponse = consumePrefetchResponse(rscUrl);
499
+ const prefetchedResponse = consumePrefetchResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader);
321
500
  if (prefetchedResponse) {
322
501
  navResponse = restoreRscResponse(prefetchedResponse, false);
323
502
  navResponseUrl = prefetchedResponse.url;
324
503
  }
325
504
  }
326
- if (!navResponse) navResponse = await fetch(rscUrl, {
327
- headers: { Accept: "text/x-component" },
328
- credentials: "include"
329
- });
330
- if (navId !== activeNavigationId) return;
505
+ if (!navResponse) {
506
+ const requestHeaders = createRscRequestHeaders(requestInterceptionContext);
507
+ if (mountedSlotsHeader) requestHeaders.set("X-Vinext-Mounted-Slots", mountedSlotsHeader);
508
+ navResponse = await fetch(rscUrl, {
509
+ headers: requestHeaders,
510
+ credentials: "include"
511
+ });
512
+ }
513
+ if (navId !== activeNavigationId) {
514
+ settlePendingBrowserRouterState(pendingRouterState);
515
+ return;
516
+ }
331
517
  const finalUrl = new URL(navResponseUrl ?? navResponse.url, window.location.origin);
332
518
  const requestedUrl = new URL(rscUrl, window.location.origin);
333
519
  if (finalUrl.pathname !== requestedUrl.pathname) {
334
520
  const destinationPath = finalUrl.pathname.replace(/\.rsc$/, "") + finalUrl.search;
335
- replaceHistoryStateWithoutNotify(null, "", destinationPath);
521
+ replaceHistoryStateWithoutNotify(createHistoryStateWithPreviousNextUrl(null, requestPreviousNextUrl), "", destinationPath);
336
522
  const navigate = window.__VINEXT_RSC_NAVIGATE__;
337
523
  if (!navigate) {
524
+ settlePendingBrowserRouterState(pendingRouterState);
338
525
  window.location.href = destinationPath;
339
526
  return;
340
527
  }
341
- return navigate(destinationPath, redirectDepth + 1, navigationKind, void 0);
528
+ settlePendingBrowserRouterState(pendingRouterState);
529
+ return navigate(destinationPath, redirectDepth + 1, navigationKind, void 0, requestPreviousNextUrl, false);
342
530
  }
343
531
  let navParams = {};
344
532
  const paramsHeader = navResponse.headers.get("X-Vinext-Params");
@@ -347,23 +535,34 @@ async function main() {
347
535
  } catch {}
348
536
  const navigationSnapshot = createClientNavigationRenderSnapshot(href, navParams);
349
537
  const responseSnapshot = await snapshotRscResponse(navResponse);
350
- if (navId !== activeNavigationId) return;
351
- const rscPayload = await createFromFetch(Promise.resolve(restoreRscResponse(responseSnapshot)));
352
- if (navId !== activeNavigationId) return;
538
+ if (navId !== activeNavigationId) {
539
+ settlePendingBrowserRouterState(pendingRouterState);
540
+ return;
541
+ }
542
+ const rscPayload = normalizeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(responseSnapshot))));
543
+ if (navId !== activeNavigationId) {
544
+ settlePendingBrowserRouterState(pendingRouterState);
545
+ return;
546
+ }
353
547
  _snapshotPending = true;
354
- stageClientParams(navParams);
355
548
  try {
356
- await renderNavigationPayload(rscPayload, navigationSnapshot, navigationCommitEffect, isSameRoute);
549
+ await renderNavigationPayload(rscPayload, navigationSnapshot, href, navId, historyUpdateMode, navParams, requestPreviousNextUrl, pendingRouterState, isSameRoute, toActionType(navigationKind));
357
550
  } finally {
358
551
  _snapshotPending = false;
359
552
  }
360
- storeVisitedResponseSnapshot(rscUrl, responseSnapshot, navParams);
553
+ if (navId !== activeNavigationId) {
554
+ settlePendingBrowserRouterState(pendingRouterState);
555
+ return;
556
+ }
557
+ storeVisitedResponseSnapshot(rscUrl, resolveVisitedResponseInterceptionContext(requestInterceptionContext, readAppElementsMetadata(await rscPayload).interceptionContext), responseSnapshot, navParams);
361
558
  return;
362
559
  } catch (error) {
363
560
  if (_snapshotPending) {
364
561
  _snapshotPending = false;
365
- commitClientNavigationState();
562
+ commitClientNavigationState(navId);
366
563
  }
564
+ settlePendingBrowserRouterState(pendingRouterState);
565
+ if (navId === activeNavigationId) clearPendingPathname(navId);
367
566
  if (navId !== activeNavigationId) return;
368
567
  console.error("[vinext] RSC navigation error:", error);
369
568
  window.location.href = href;
@@ -382,13 +581,21 @@ async function main() {
382
581
  if (import.meta.hot) import.meta.hot.on("rsc:update", async () => {
383
582
  try {
384
583
  clearClientNavigationCaches();
385
- updateBrowserTree(await createFromFetch(fetch(toRscUrl(window.location.pathname + window.location.search))), createClientNavigationRenderSnapshot(window.location.href, latestClientParams), ++nextNavigationRenderId, false);
584
+ const navigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
585
+ const pending = await createPendingNavigationCommit({
586
+ currentState: getBrowserRouterState(),
587
+ nextElements: normalizeAppElementsPromise(createFromFetch(fetch(toRscUrl(window.location.pathname + window.location.search)))),
588
+ navigationSnapshot,
589
+ renderId: ++nextNavigationRenderId,
590
+ type: "replace"
591
+ });
592
+ dispatchBrowserTree(pending.action.elements, navigationSnapshot, pending.action.renderId, "replace", pending.interceptionContext, pending.action.layoutFlags, pending.previousNextUrl, pending.routeId, pending.rootLayoutTreePath, null, false);
386
593
  } catch (error) {
387
594
  console.error("[vinext] RSC HMR error:", error);
388
595
  }
389
596
  });
390
597
  }
391
- main();
598
+ if (typeof document !== "undefined") main();
392
599
  //#endregion
393
600
  export {};
394
601