vinext 0.0.47 → 0.0.49
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.
- package/README.md +1 -1
- package/dist/build/layout-classification.js +3 -1
- package/dist/build/layout-classification.js.map +1 -1
- package/dist/build/prerender.js +10 -10
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/report.d.ts +8 -4
- package/dist/build/report.js +17 -7
- package/dist/build/report.js.map +1 -1
- package/dist/build/run-prerender.d.ts +5 -0
- package/dist/build/run-prerender.js +4 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/server-manifest.js +2 -7
- package/dist/build/server-manifest.js.map +1 -1
- package/dist/build/standalone.js +3 -5
- package/dist/build/standalone.js.map +1 -1
- package/dist/check.js +45 -29
- package/dist/check.js.map +1 -1
- package/dist/cli-args.d.ts +3 -1
- package/dist/cli-args.js +18 -1
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.js +9 -1
- package/dist/cli.js.map +1 -1
- package/dist/config/config-matchers.js +46 -37
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/deploy.d.ts +18 -2
- package/dist/deploy.js +47 -4
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-rsc-entry.js +11 -9
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.js +4 -1
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/pages-client-entry.js +3 -2
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +21 -62
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.d.ts +12 -3
- package/dist/entries/runtime-entry-module.js +15 -4
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +1 -1
- package/dist/init.js +2 -2
- package/dist/init.js.map +1 -1
- package/dist/plugins/og-assets.js +15 -16
- package/dist/plugins/og-assets.js.map +1 -1
- package/dist/plugins/rsc-client-shim-excludes.d.ts +2 -1
- package/dist/plugins/rsc-client-shim-excludes.js +10 -1
- package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
- package/dist/routing/app-route-graph.d.ts +90 -4
- package/dist/routing/app-route-graph.js +210 -7
- package/dist/routing/app-route-graph.js.map +1 -1
- package/dist/routing/app-router.d.ts +15 -3
- package/dist/routing/app-router.js +20 -23
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.d.ts +3 -1
- package/dist/routing/file-matcher.js +6 -1
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.js +10 -19
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/route-matching.d.ts +28 -0
- package/dist/routing/route-matching.js +44 -0
- package/dist/routing/route-matching.js.map +1 -0
- package/dist/routing/route-pattern.js +4 -1
- package/dist/routing/route-pattern.js.map +1 -1
- package/dist/routing/route-trie.d.ts +8 -0
- package/dist/routing/route-trie.js +12 -1
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/route-validation.js +3 -4
- package/dist/routing/route-validation.js.map +1 -1
- package/dist/routing/utils.d.ts +8 -1
- package/dist/routing/utils.js +25 -2
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.js +2 -8
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-browser-entry.js +66 -49
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-navigation-controller.d.ts +7 -5
- package/dist/server/app-browser-navigation-controller.js +43 -35
- package/dist/server/app-browser-navigation-controller.js.map +1 -1
- package/dist/server/app-browser-state.d.ts +33 -15
- package/dist/server/app-browser-state.js +52 -59
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +68 -0
- package/dist/server/app-browser-visible-commit.js +182 -0
- package/dist/server/app-browser-visible-commit.js.map +1 -0
- package/dist/server/app-client-reference-preloader.d.ts +15 -0
- package/dist/server/app-client-reference-preloader.js +46 -0
- package/dist/server/app-client-reference-preloader.js.map +1 -0
- package/dist/server/app-elements-wire.d.ts +130 -0
- package/dist/server/app-elements-wire.js +205 -0
- package/dist/server/app-elements-wire.js.map +1 -0
- package/dist/server/app-elements.d.ts +2 -84
- package/dist/server/app-elements.js +3 -102
- package/dist/server/app-elements.js.map +1 -1
- package/dist/server/app-fallback-renderer.d.ts +1 -1
- package/dist/server/app-middleware.d.ts +2 -1
- package/dist/server/app-middleware.js +34 -11
- package/dist/server/app-middleware.js.map +1 -1
- package/dist/server/app-page-boundary-render.d.ts +1 -1
- package/dist/server/app-page-boundary-render.js +8 -5
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.js +2 -1
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +1 -0
- package/dist/server/app-page-cache.js +8 -13
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +2 -1
- package/dist/server/app-page-dispatch.js +18 -10
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +1 -1
- package/dist/server/app-page-element-builder.js +8 -5
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.d.ts +23 -5
- package/dist/server/app-page-execution.js +39 -24
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.js +2 -1
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-method.js +2 -5
- package/dist/server/app-page-method.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +1 -1
- package/dist/server/app-page-probe.js +5 -1
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-page-render.d.ts +1 -1
- package/dist/server/app-page-render.js +38 -3
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +7 -10
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.js +3 -2
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +5 -2
- package/dist/server/app-page-route-wiring.js +15 -12
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-stream.d.ts +7 -0
- package/dist/server/app-page-stream.js +9 -2
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-prerender-endpoints.js +3 -2
- package/dist/server/app-prerender-endpoints.js.map +1 -1
- package/dist/server/app-route-handler-cache.js +2 -1
- package/dist/server/app-route-handler-cache.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.js +6 -5
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-policy.js +13 -13
- package/dist/server/app-route-handler-policy.js.map +1 -1
- package/dist/server/app-route-handler-response.js +2 -1
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +9 -1
- package/dist/server/app-route-handler-runtime.js +11 -1
- package/dist/server/app-route-handler-runtime.js.map +1 -1
- package/dist/server/app-router-entry.js +9 -4
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +34 -0
- package/dist/server/app-rsc-cache-busting.js +137 -0
- package/dist/server/app-rsc-cache-busting.js.map +1 -0
- package/dist/server/app-rsc-handler.js +22 -11
- package/dist/server/app-rsc-handler.js.map +1 -1
- package/dist/server/app-rsc-request-normalization.d.ts +4 -2
- package/dist/server/app-rsc-request-normalization.js +10 -6
- package/dist/server/app-rsc-request-normalization.js.map +1 -1
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-rsc-route-matching.js +8 -4
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-segment-config.js +4 -0
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.js +43 -51
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.js +21 -20
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +44 -0
- package/dist/server/artifact-compatibility.js +82 -0
- package/dist/server/artifact-compatibility.js.map +1 -0
- package/dist/server/cache-proof.d.ts +200 -0
- package/dist/server/cache-proof.js +342 -0
- package/dist/server/cache-proof.js.map +1 -0
- package/dist/server/dev-origin-check.js +8 -4
- package/dist/server/dev-origin-check.js.map +1 -1
- package/dist/server/dev-server.js +6 -16
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +67 -0
- package/dist/server/http-error-responses.js +77 -0
- package/dist/server/http-error-responses.js.map +1 -0
- package/dist/server/image-optimization.js +2 -1
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/metadata-route-response.js +6 -5
- package/dist/server/metadata-route-response.js.map +1 -1
- package/dist/server/metadata-routes.d.ts +1 -0
- package/dist/server/metadata-routes.js +6 -0
- package/dist/server/metadata-routes.js.map +1 -1
- package/dist/server/middleware-matcher.js +2 -2
- package/dist/server/middleware-matcher.js.map +1 -1
- package/dist/server/middleware-response-headers.js +21 -0
- package/dist/server/middleware-response-headers.js.map +1 -1
- package/dist/server/middleware-runtime.js +3 -3
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/navigation-trace.d.ts +33 -0
- package/dist/server/navigation-trace.js +35 -0
- package/dist/server/navigation-trace.js.map +1 -0
- package/dist/server/next-error-digest.d.ts +44 -0
- package/dist/server/next-error-digest.js +40 -0
- package/dist/server/next-error-digest.js.map +1 -0
- package/dist/server/pages-api-route.js +4 -7
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-node-compat.js +4 -16
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-response.d.ts +2 -8
- package/dist/server/pages-page-response.js +44 -14
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prod-server.d.ts +6 -0
- package/dist/server/prod-server.js +28 -21
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +42 -1
- package/dist/server/request-pipeline.js +97 -17
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +2 -2
- package/dist/shims/cache-runtime.js +3 -6
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.js +3 -5
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/fetch-cache.js +2 -3
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/head-state.js +2 -3
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/headers.js +4 -44
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-state.js +2 -3
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/internal/als-registry.d.ts +15 -0
- package/dist/shims/internal/als-registry.js +55 -0
- package/dist/shims/internal/als-registry.js.map +1 -0
- package/dist/shims/internal/cookie-serialize.d.ts +46 -0
- package/dist/shims/internal/cookie-serialize.js +51 -0
- package/dist/shims/internal/cookie-serialize.js.map +1 -0
- package/dist/shims/link.js +31 -26
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +26 -1
- package/dist/shims/metadata.js +94 -4
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.js +2 -3
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +2 -7
- package/dist/shims/navigation.js +44 -36
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/request-context.js +2 -4
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/router-state.js +2 -3
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.js +2 -2
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/server.js +5 -30
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +1 -1
- package/dist/shims/slot.js +5 -4
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/thenable-params.d.ts +5 -2
- package/dist/shims/thenable-params.js +26 -6
- package/dist/shims/thenable-params.js.map +1 -1
- package/dist/shims/unified-request-context.js +2 -14
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/utils/base-path.d.ts +7 -1
- package/dist/utils/base-path.js +12 -1
- package/dist/utils/base-path.js.map +1 -1
- package/dist/utils/query.d.ts +8 -1
- package/dist/utils/query.js +12 -1
- package/dist/utils/query.js.map +1 -1
- package/dist/utils/safe-json-file.d.ts +18 -0
- package/dist/utils/safe-json-file.js +25 -0
- package/dist/utils/safe-json-file.js.map +1 -0
- package/dist/utils/text-stream.d.ts +29 -0
- package/dist/utils/text-stream.js +66 -0
- package/dist/utils/text-stream.js.map +1 -0
- package/package.json +5 -5
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
|
|
2
1
|
import { stripBasePath } from "../utils/base-path.js";
|
|
2
|
+
import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
|
|
3
3
|
import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { AppElementsWire } from "./app-elements-wire.js";
|
|
5
|
+
import { getMountedSlotIdsHeader, resolveVisitedResponseInterceptionContext } from "./app-elements.js";
|
|
6
|
+
import { VINEXT_RSC_MOUNTED_SLOTS_HEADER, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
|
|
7
|
+
import { __basePath, commitClientNavigationState, consumePrefetchResponse, createClientNavigationRenderSnapshot, getClientNavigationRenderContext, getClientNavigationState, getCurrentInterceptionContext, getCurrentNextUrl, getPrefetchCache, getPrefetchedUrls, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, restoreRscResponse, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse } from "../shims/navigation.js";
|
|
6
8
|
import { DevRecoveryBoundary } from "../shims/error-boundary.js";
|
|
7
9
|
import { ElementsContext, Slot } from "../shims/slot.js";
|
|
8
10
|
import "../client/instrumentation-client.js";
|
|
@@ -20,11 +22,27 @@ import { hydrateRoot } from "react-dom/client";
|
|
|
20
22
|
function toActionType(kind) {
|
|
21
23
|
return kind === "traverse" ? "traverse" : "navigate";
|
|
22
24
|
}
|
|
25
|
+
function toOperationLane(kind) {
|
|
26
|
+
switch (kind) {
|
|
27
|
+
case "navigate": return "navigation";
|
|
28
|
+
case "refresh": return "refresh";
|
|
29
|
+
case "traverse": return "traverse";
|
|
30
|
+
default: throw new Error("[vinext] Unknown navigation kind: " + String(kind));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
23
33
|
const MAX_VISITED_RESPONSE_CACHE_SIZE = 50;
|
|
24
34
|
const VISITED_RESPONSE_CACHE_TTL = 5 * 6e4;
|
|
25
35
|
const MAX_TRAVERSAL_CACHE_TTL = 30 * 6e4;
|
|
26
36
|
const browserNavigationController = createAppBrowserNavigationController();
|
|
27
37
|
const NavigationCommitSignal = browserNavigationController.NavigationCommitSignal;
|
|
38
|
+
function parseEncodedJsonHeader(value) {
|
|
39
|
+
if (!value) return null;
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(decodeURIComponent(value));
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
28
46
|
function isRouterStatePromise(value) {
|
|
29
47
|
return value instanceof Promise;
|
|
30
48
|
}
|
|
@@ -82,7 +100,7 @@ function createNavigationCommitEffect(options) {
|
|
|
82
100
|
commitClientNavigationState(navId);
|
|
83
101
|
};
|
|
84
102
|
}
|
|
85
|
-
async function renderNavigationPayload(payload, navigationSnapshot, targetHref, navId, historyUpdateMode, params, previousNextUrl, pendingRouterState, useTransition = true, actionType = "navigate") {
|
|
103
|
+
async function renderNavigationPayload(payload, navigationSnapshot, targetHref, navId, historyUpdateMode, params, previousNextUrl, pendingRouterState, useTransition = true, actionType = "navigate", operationLane = "navigation") {
|
|
86
104
|
try {
|
|
87
105
|
return await browserNavigationController.renderNavigationPayload({
|
|
88
106
|
actionType,
|
|
@@ -93,6 +111,7 @@ async function renderNavigationPayload(payload, navigationSnapshot, targetHref,
|
|
|
93
111
|
historyUpdateMode,
|
|
94
112
|
navigationSnapshot,
|
|
95
113
|
nextElements: payload,
|
|
114
|
+
operationLane,
|
|
96
115
|
params,
|
|
97
116
|
pendingRouterState,
|
|
98
117
|
previousNextUrl,
|
|
@@ -105,9 +124,9 @@ async function renderNavigationPayload(payload, navigationSnapshot, targetHref,
|
|
|
105
124
|
throw error;
|
|
106
125
|
}
|
|
107
126
|
}
|
|
108
|
-
async function commitSameUrlNavigatePayload(nextElements, returnValue) {
|
|
127
|
+
async function commitSameUrlNavigatePayload(nextElements, returnValue, actionInitiationState) {
|
|
109
128
|
const navigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
|
|
110
|
-
return browserNavigationController.commitSameUrlNavigatePayload(nextElements, navigationSnapshot, returnValue);
|
|
129
|
+
return browserNavigationController.commitSameUrlNavigatePayload(nextElements, navigationSnapshot, returnValue, actionInitiationState);
|
|
111
130
|
}
|
|
112
131
|
function evictVisitedResponseCacheIfNeeded() {
|
|
113
132
|
while (visitedResponseCache.size >= MAX_VISITED_RESPONSE_CACHE_SIZE) {
|
|
@@ -117,7 +136,7 @@ function evictVisitedResponseCacheIfNeeded() {
|
|
|
117
136
|
}
|
|
118
137
|
}
|
|
119
138
|
function getVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, navigationKind) {
|
|
120
|
-
const cacheKey =
|
|
139
|
+
const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
|
|
121
140
|
const cached = visitedResponseCache.get(cacheKey);
|
|
122
141
|
if (!cached) return null;
|
|
123
142
|
if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {
|
|
@@ -144,7 +163,7 @@ function getVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, nav
|
|
|
144
163
|
return null;
|
|
145
164
|
}
|
|
146
165
|
function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, params) {
|
|
147
|
-
const cacheKey =
|
|
166
|
+
const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
|
|
148
167
|
visitedResponseCache.delete(cacheKey);
|
|
149
168
|
evictVisitedResponseCacheIfNeeded();
|
|
150
169
|
const now = Date.now();
|
|
@@ -181,21 +200,17 @@ function getRequestState(navigationKind, previousNextUrlOverride) {
|
|
|
181
200
|
default: throw new Error("[vinext] Unknown navigation kind: " + String(navigationKind));
|
|
182
201
|
}
|
|
183
202
|
}
|
|
184
|
-
function createRscRequestHeaders(interceptionContext) {
|
|
185
|
-
const headers = new Headers({ Accept: "text/x-component" });
|
|
186
|
-
if (interceptionContext !== null) headers.set("X-Vinext-Interception-Context", interceptionContext);
|
|
187
|
-
return headers;
|
|
188
|
-
}
|
|
189
203
|
function handleDevRecoveryBoundaryCatch(resetKey) {
|
|
190
204
|
browserNavigationController.drainPrePaintEffects(resetKey);
|
|
191
205
|
}
|
|
192
|
-
function
|
|
193
|
-
return Promise.resolve(payload).then((elements) =>
|
|
206
|
+
function decodeAppElementsPromise(payload) {
|
|
207
|
+
return Promise.resolve(payload).then((elements) => AppElementsWire.decode(elements));
|
|
194
208
|
}
|
|
195
209
|
function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
|
|
196
210
|
const resolvedElements = use(initialElements);
|
|
197
|
-
const initialMetadata =
|
|
211
|
+
const initialMetadata = AppElementsWire.readMetadata(resolvedElements);
|
|
198
212
|
const [treeStateValue, setTreeStateValue] = useState({
|
|
213
|
+
activeOperation: null,
|
|
199
214
|
elements: resolvedElements,
|
|
200
215
|
interceptionContext: initialMetadata.interceptionContext,
|
|
201
216
|
layoutFlags: initialMetadata.layoutFlags,
|
|
@@ -203,7 +218,8 @@ function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
|
|
|
203
218
|
previousNextUrl: null,
|
|
204
219
|
renderId: 0,
|
|
205
220
|
rootLayoutTreePath: initialMetadata.rootLayoutTreePath,
|
|
206
|
-
routeId: initialMetadata.routeId
|
|
221
|
+
routeId: initialMetadata.routeId,
|
|
222
|
+
visibleCommitVersion: 0
|
|
207
223
|
});
|
|
208
224
|
const treeState = isRouterStatePromise(treeStateValue) ? use(treeStateValue) : treeStateValue;
|
|
209
225
|
const stateRef = useRef(treeState);
|
|
@@ -324,17 +340,20 @@ async function readInitialRscStream() {
|
|
|
324
340
|
if (vinext.__VINEXT_RSC_NAV__) restoreHydrationNavigationContext(vinext.__VINEXT_RSC_NAV__.pathname, vinext.__VINEXT_RSC_NAV__.searchParams, params);
|
|
325
341
|
return createProgressiveRscStream();
|
|
326
342
|
}
|
|
327
|
-
const
|
|
343
|
+
const rscHeaders = createRscRequestHeaders();
|
|
344
|
+
const rscResponse = await fetch(await createRscRequestUrl(window.location.pathname + window.location.search, rscHeaders), {
|
|
345
|
+
credentials: "include",
|
|
346
|
+
headers: rscHeaders
|
|
347
|
+
});
|
|
328
348
|
if (!rscResponse.ok) return recoverFromBadInitialRscResponse(`returned ${rscResponse.status}`);
|
|
329
349
|
const contentType = rscResponse.headers.get("content-type") ?? "";
|
|
330
350
|
if (!contentType.startsWith("text/x-component")) return recoverFromBadInitialRscResponse(`returned non-RSC content-type "${contentType || "(missing)"}"`);
|
|
331
351
|
if (!rscResponse.body) return recoverFromBadInitialRscResponse("returned empty body");
|
|
332
352
|
clearReloadFlag();
|
|
333
|
-
|
|
334
|
-
const
|
|
335
|
-
if (
|
|
336
|
-
|
|
337
|
-
applyClientParams(params);
|
|
353
|
+
const parsedParams = parseEncodedJsonHeader(rscResponse.headers.get("X-Vinext-Params"));
|
|
354
|
+
const params = parsedParams ?? {};
|
|
355
|
+
if (parsedParams) try {
|
|
356
|
+
applyClientParams(parsedParams);
|
|
338
357
|
} catch {}
|
|
339
358
|
restoreHydrationNavigationContext(window.location.pathname, window.location.search, params);
|
|
340
359
|
return rscResponse.body;
|
|
@@ -350,7 +369,7 @@ function registerServerActionCallback() {
|
|
|
350
369
|
elements: currentState.elements,
|
|
351
370
|
previousNextUrl: currentState.previousNextUrl
|
|
352
371
|
});
|
|
353
|
-
const fetchResponse = await fetch(
|
|
372
|
+
const fetchResponse = await fetch(await createRscRequestUrl(window.location.pathname + window.location.search, headers), {
|
|
354
373
|
method: "POST",
|
|
355
374
|
headers,
|
|
356
375
|
body
|
|
@@ -374,8 +393,8 @@ function registerServerActionCallback() {
|
|
|
374
393
|
}
|
|
375
394
|
clearClientNavigationCaches();
|
|
376
395
|
const result = await createFromFetch(Promise.resolve(fetchResponse), { temporaryReferences });
|
|
377
|
-
if (isServerActionResult(result)) return commitSameUrlNavigatePayload(Promise.resolve(
|
|
378
|
-
return commitSameUrlNavigatePayload(Promise.resolve(
|
|
396
|
+
if (isServerActionResult(result)) return commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result.root)), result.returnValue, currentState);
|
|
397
|
+
return commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result)), void 0, currentState);
|
|
379
398
|
});
|
|
380
399
|
}
|
|
381
400
|
async function main() {
|
|
@@ -386,7 +405,7 @@ async function main() {
|
|
|
386
405
|
}
|
|
387
406
|
function bootstrapHydration(rscStream) {
|
|
388
407
|
if (import.meta.env.DEV) installDevErrorOverlay();
|
|
389
|
-
const root =
|
|
408
|
+
const root = decodeAppElementsPromise(createFromReadableStream(rscStream));
|
|
390
409
|
const initialNavigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
|
|
391
410
|
replaceHistoryStateWithoutNotify(createHistoryStateWithPreviousNextUrl(window.history.state, null), "", window.location.href);
|
|
392
411
|
const onUncaughtError = import.meta.env.DEV ? devOnUncaughtError : createOnUncaughtError(() => pendingNavigationRecoveryHref);
|
|
@@ -419,7 +438,6 @@ function bootstrapHydration(rscStream) {
|
|
|
419
438
|
return;
|
|
420
439
|
}
|
|
421
440
|
const url = new URL(currentHref, window.location.origin);
|
|
422
|
-
const rscUrl = toRscUrl(url.pathname + url.search);
|
|
423
441
|
const requestState = getRequestState(navigationKind, currentPrevNextUrl);
|
|
424
442
|
const requestInterceptionContext = requestState.interceptionContext;
|
|
425
443
|
const requestPreviousNextUrl = requestState.previousNextUrl;
|
|
@@ -429,14 +447,17 @@ function bootstrapHydration(rscStream) {
|
|
|
429
447
|
setPendingPathname(url.pathname, navId);
|
|
430
448
|
const elementsAtNavStart = getBrowserRouterState().elements;
|
|
431
449
|
const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);
|
|
450
|
+
const requestHeaders = createRscRequestHeaders({ interceptionContext: requestInterceptionContext });
|
|
451
|
+
if (mountedSlotsHeader) requestHeaders.set(VINEXT_RSC_MOUNTED_SLOTS_HEADER, mountedSlotsHeader);
|
|
452
|
+
const rscUrl = await createRscRequestUrl(url.pathname + url.search, requestHeaders);
|
|
432
453
|
const cachedRoute = getVisitedResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader, navigationKind);
|
|
433
454
|
if (cachedRoute) {
|
|
434
455
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
435
456
|
const cachedParams = cachedRoute.params;
|
|
436
457
|
const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(currentHref, cachedParams);
|
|
437
|
-
const cachedPayload =
|
|
458
|
+
const cachedPayload = decodeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(cachedRoute.response))));
|
|
438
459
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
439
|
-
await renderNavigationPayload(cachedPayload, cachedNavigationSnapshot, currentHref, navId, currentHistoryMode, cachedParams, requestPreviousNextUrl, pendingRouterState, isSameRoute, toActionType(navigationKind));
|
|
460
|
+
await renderNavigationPayload(cachedPayload, cachedNavigationSnapshot, currentHref, navId, currentHistoryMode, cachedParams, requestPreviousNextUrl, pendingRouterState, isSameRoute, toActionType(navigationKind), toOperationLane(navigationKind));
|
|
440
461
|
return;
|
|
441
462
|
}
|
|
442
463
|
let navResponse;
|
|
@@ -448,14 +469,10 @@ function bootstrapHydration(rscStream) {
|
|
|
448
469
|
navResponseUrl = prefetchedResponse.url;
|
|
449
470
|
}
|
|
450
471
|
}
|
|
451
|
-
if (!navResponse) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
headers: requestHeaders,
|
|
456
|
-
credentials: "include"
|
|
457
|
-
});
|
|
458
|
-
}
|
|
472
|
+
if (!navResponse) navResponse = await fetch(rscUrl, {
|
|
473
|
+
headers: requestHeaders,
|
|
474
|
+
credentials: "include"
|
|
475
|
+
});
|
|
459
476
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
460
477
|
const isRscResponse = (navResponse.headers.get("content-type") ?? "").startsWith("text/x-component");
|
|
461
478
|
if (!navResponse.ok || !isRscResponse || !navResponse.body) {
|
|
@@ -463,8 +480,9 @@ function bootstrapHydration(rscStream) {
|
|
|
463
480
|
let hardNavTarget = currentHref;
|
|
464
481
|
if (responseUrl) {
|
|
465
482
|
const parsed = new URL(responseUrl, window.location.origin);
|
|
483
|
+
stripRscCacheBustingSearchParam(parsed);
|
|
466
484
|
const origUrl = new URL(currentHref, window.location.origin);
|
|
467
|
-
let pathname = parsed.pathname
|
|
485
|
+
let pathname = stripRscSuffix(parsed.pathname);
|
|
468
486
|
if (origUrl.pathname.length > 1 && origUrl.pathname.endsWith("/") && !pathname.endsWith("/")) pathname += "/";
|
|
469
487
|
hardNavTarget = pathname + parsed.search;
|
|
470
488
|
if (origUrl.hash) hardNavTarget += origUrl.hash;
|
|
@@ -473,9 +491,10 @@ function bootstrapHydration(rscStream) {
|
|
|
473
491
|
return;
|
|
474
492
|
}
|
|
475
493
|
const finalUrl = new URL(navResponseUrl ?? navResponse.url, window.location.origin);
|
|
494
|
+
stripRscCacheBustingSearchParam(finalUrl);
|
|
476
495
|
const requestedUrl = new URL(rscUrl, window.location.origin);
|
|
477
496
|
if (finalUrl.pathname !== requestedUrl.pathname) {
|
|
478
|
-
const destinationPath = finalUrl.pathname
|
|
497
|
+
const destinationPath = stripRscSuffix(finalUrl.pathname) + finalUrl.search;
|
|
479
498
|
replaceHistoryStateWithoutNotify(createHistoryStateWithPreviousNextUrl(null, requestPreviousNextUrl), "", destinationPath);
|
|
480
499
|
currentHref = destinationPath;
|
|
481
500
|
currentHistoryMode = void 0;
|
|
@@ -483,19 +502,16 @@ function bootstrapHydration(rscStream) {
|
|
|
483
502
|
redirectCount += 1;
|
|
484
503
|
continue;
|
|
485
504
|
}
|
|
486
|
-
|
|
487
|
-
const paramsHeader = navResponse.headers.get("X-Vinext-Params");
|
|
488
|
-
if (paramsHeader) try {
|
|
489
|
-
navParams = JSON.parse(decodeURIComponent(paramsHeader));
|
|
490
|
-
} catch {}
|
|
505
|
+
const navParams = parseEncodedJsonHeader(navResponse.headers.get("X-Vinext-Params")) ?? {};
|
|
491
506
|
const navigationSnapshot = createClientNavigationRenderSnapshot(currentHref, navParams);
|
|
492
507
|
const responseSnapshot = await snapshotRscResponse(navResponse);
|
|
493
508
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
494
|
-
const rscPayload =
|
|
509
|
+
const rscPayload = decodeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(responseSnapshot))));
|
|
495
510
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
496
|
-
await renderNavigationPayload(rscPayload, navigationSnapshot, currentHref, navId, currentHistoryMode, navParams, requestPreviousNextUrl, pendingRouterState, isSameRoute, toActionType(navigationKind));
|
|
511
|
+
if (await renderNavigationPayload(rscPayload, navigationSnapshot, currentHref, navId, currentHistoryMode, navParams, requestPreviousNextUrl, pendingRouterState, isSameRoute, toActionType(navigationKind), toOperationLane(navigationKind)) !== "committed") return;
|
|
497
512
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
498
|
-
|
|
513
|
+
const resolvedElements = await rscPayload;
|
|
514
|
+
storeVisitedResponseSnapshot(rscUrl, resolveVisitedResponseInterceptionContext(requestInterceptionContext, AppElementsWire.readMetadata(resolvedElements).interceptionContext), responseSnapshot, navParams);
|
|
499
515
|
return;
|
|
500
516
|
}
|
|
501
517
|
} catch (error) {
|
|
@@ -527,7 +543,8 @@ function bootstrapHydration(rscStream) {
|
|
|
527
543
|
clearClientNavigationCaches();
|
|
528
544
|
const navigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
|
|
529
545
|
dismissOverlay();
|
|
530
|
-
|
|
546
|
+
const hmrHeaders = createRscRequestHeaders();
|
|
547
|
+
await browserNavigationController.hmrReplaceTree(decodeAppElementsPromise(createFromFetch(fetch(await createRscRequestUrl(window.location.pathname + window.location.search, hmrHeaders), { headers: hmrHeaders }))), navigationSnapshot);
|
|
531
548
|
} catch (error) {
|
|
532
549
|
console.error("[vinext] RSC HMR error:", error);
|
|
533
550
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-browser-entry.js","names":[],"sources":["../../src/server/app-browser-entry.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\n\nimport { createElement, use, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n createFromFetch,\n createFromReadableStream,\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport \"../client/instrumentation-client.js\";\nimport { notifyAppRouterTransitionStart } from \"../client/instrumentation-client-state.js\";\nimport {\n __basePath,\n commitClientNavigationState,\n consumePrefetchResponse,\n createClientNavigationRenderSnapshot,\n getCurrentNextUrl,\n getCurrentInterceptionContext,\n getClientNavigationRenderContext,\n getClientNavigationState,\n getPrefetchCache,\n getPrefetchedUrls,\n pushHistoryStateWithoutNotify,\n replaceClientParamsWithoutNotify,\n replaceHistoryStateWithoutNotify,\n restoreRscResponse,\n setClientParams,\n setPendingPathname,\n snapshotRscResponse,\n setMountedSlotsHeader,\n setNavigationContext,\n toRscUrl,\n type CachedRscResponse,\n type ClientNavigationRenderSnapshot,\n} from \"vinext/shims/navigation\";\nimport { stripBasePath } from \"../utils/base-path.js\";\nimport {\n chunksToReadableStream,\n createProgressiveRscStream,\n getVinextBrowserGlobal,\n} from \"./app-browser-stream.js\";\nimport {\n createAppBrowserNavigationController,\n type HistoryUpdateMode,\n type PendingBrowserRouterState,\n} from \"./app-browser-navigation-controller.js\";\nimport {\n createAppPayloadCacheKey,\n getMountedSlotIdsHeader,\n normalizeAppElements,\n readAppElementsMetadata,\n resolveVisitedResponseInterceptionContext,\n type AppElements,\n type AppWireElements,\n} from \"./app-elements.js\";\nimport {\n createHistoryStateWithPreviousNextUrl,\n readHistoryStatePreviousNextUrl,\n resolveInterceptionContextFromPreviousNextUrl,\n resolveServerActionRequestState,\n type AppRouterState,\n} from \"./app-browser-state.js\";\nimport { DevRecoveryBoundary } from \"vinext/shims/error-boundary\";\nimport { ElementsContext, Slot } from \"vinext/shims/slot\";\nimport { createOnUncaughtError } from \"./app-browser-error.js\";\nimport {\n devOnCaughtError,\n devOnUncaughtError,\n dismissOverlay,\n installDevErrorOverlay,\n} from \"./dev-error-overlay.js\";\nimport { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from \"vinext/shims/url-safety\";\nimport {\n getServerActionNotFoundClientMessage,\n isServerActionNotFoundResponse,\n} from \"./server-action-not-found.js\";\n\ntype SearchParamInput = ConstructorParameters<typeof URLSearchParams>[0];\n\ntype ServerActionResult = {\n root: AppWireElements;\n returnValue?: {\n ok: boolean;\n data: unknown;\n };\n};\n\ntype NavigationKind = \"navigate\" | \"traverse\" | \"refresh\";\n\n// Maps NavigationKind to the AppRouterAction type used by the reducer.\n// \"refresh\" is intentionally treated as \"navigate\" (merge, preserve absent slots).\n// Both call sites must stay in sync — update here if NavigationKind gains new values.\nfunction toActionType(kind: NavigationKind): \"navigate\" | \"traverse\" {\n return kind === \"traverse\" ? \"traverse\" : \"navigate\";\n}\n\ntype VisitedResponseCacheEntry = {\n params: Record<string, string | string[]>;\n expiresAt: number;\n response: CachedRscResponse;\n};\n\nconst MAX_VISITED_RESPONSE_CACHE_SIZE = 50;\nconst VISITED_RESPONSE_CACHE_TTL = 5 * 60_000;\nconst MAX_TRAVERSAL_CACHE_TTL = 30 * 60_000;\nconst browserNavigationController = createAppBrowserNavigationController();\nconst NavigationCommitSignal = browserNavigationController.NavigationCommitSignal;\n\nfunction isRouterStatePromise(\n value: AppRouterState | Promise<AppRouterState>,\n): value is Promise<AppRouterState> {\n return value instanceof Promise;\n}\n\nlet latestClientParams: Record<string, string | string[]> = {};\nconst visitedResponseCache = new Map<string, VisitedResponseCacheEntry>();\n// Sticky bit: stays true once BrowserRoot has committed at least once. Used by\n// the HMR handler to distinguish \"still hydrating\" (wait) from \"was up, then\n// torn down by a render error\" (full reload to recover).\nlet browserRouterStateHasEverCommitted = false;\n// Most recent navigation target that has been dispatched but not yet committed.\n// Read by the onUncaughtError handler so a render error tearing down the tree\n// can land the browser on the URL the user was actually navigating to, instead\n// of stranding them on the previous URL with a blank page. Cleared once the\n// commit effect runs (URL update succeeded) or the navigation is superseded.\nlet pendingNavigationRecoveryHref: string | null = null;\n\nfunction isServerActionResult(value: unknown): value is ServerActionResult {\n return !!value && typeof value === \"object\" && \"root\" in value;\n}\n\nfunction getBrowserRouterState(): AppRouterState {\n return browserNavigationController.getBrowserRouterState();\n}\n\nfunction hasBrowserRouterState(): boolean {\n return browserNavigationController.hasBrowserRouterState();\n}\n\nfunction waitForBrowserRouterStateReady(): Promise<void> {\n return browserNavigationController.waitForBrowserRouterStateReady();\n}\n\nfunction beginPendingBrowserRouterState(): PendingBrowserRouterState {\n return browserNavigationController.beginPendingBrowserRouterState();\n}\n\nfunction applyClientParams(params: Record<string, string | string[]>): void {\n latestClientParams = params;\n setClientParams(params);\n}\n\nfunction stageClientParams(params: Record<string, string | string[]>): void {\n // NB: latestClientParams diverges from ClientNavigationState.clientParams\n // between staging and commit. Server action snapshots (same-URL\n // commitSameUrlNavigatePayload() calls inside registerServerActionCallback)\n // read latestClientParams, so a\n // server action fired during this window would get the pending (not yet\n // committed) params. This is acceptable because the commit effect fires\n // before hooks observe the new URL state, keeping the window vanishingly small.\n latestClientParams = params;\n replaceClientParamsWithoutNotify(params);\n}\n\nfunction clearVisitedResponseCache(): void {\n visitedResponseCache.clear();\n}\n\nfunction clearPrefetchState(): void {\n getPrefetchCache().clear();\n getPrefetchedUrls().clear();\n}\n\nfunction clearClientNavigationCaches(): void {\n clearVisitedResponseCache();\n clearPrefetchState();\n}\n\nfunction createNavigationCommitEffect(options: {\n href: string;\n historyUpdateMode: HistoryUpdateMode | undefined;\n navId: number;\n params: Record<string, string | string[]>;\n previousNextUrl: string | null;\n}): () => void {\n const { href, historyUpdateMode, navId, params, previousNextUrl } = options;\n\n return () => {\n // Only update URL if this is still the active navigation.\n // A newer navigation would have superseded this navigation id.\n if (!browserNavigationController.isCurrentNavigation(navId)) {\n // This transition was superseded before commit; balance the active\n // snapshot counter without clearing pendingPathname ownership.\n commitClientNavigationState(undefined, { releaseSnapshot: true });\n return;\n }\n\n const targetHref = new URL(href, window.location.origin).href;\n stageClientParams(params);\n const preserveExistingState = historyUpdateMode === \"replace\";\n const historyState = createHistoryStateWithPreviousNextUrl(\n preserveExistingState ? window.history.state : null,\n previousNextUrl,\n );\n\n if (historyUpdateMode === \"replace\" && window.location.href !== targetHref) {\n replaceHistoryStateWithoutNotify(historyState, \"\", href);\n } else if (historyUpdateMode === \"push\" && window.location.href !== targetHref) {\n pushHistoryStateWithoutNotify(historyState, \"\", href);\n }\n\n // URL has been updated; the recovery hard-nav target is no longer needed.\n pendingNavigationRecoveryHref = null;\n commitClientNavigationState(navId);\n };\n}\n\nasync function renderNavigationPayload(\n payload: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n targetHref: string,\n navId: number,\n historyUpdateMode: HistoryUpdateMode | undefined,\n params: Record<string, string | string[]>,\n previousNextUrl: string | null,\n pendingRouterState: PendingBrowserRouterState | null,\n useTransition = true,\n actionType: \"navigate\" | \"replace\" | \"traverse\" = \"navigate\",\n): Promise<void> {\n try {\n return await browserNavigationController.renderNavigationPayload({\n actionType,\n createNavigationCommitEffect: (options) => {\n pendingNavigationRecoveryHref = options.href;\n return createNavigationCommitEffect(options);\n },\n historyUpdateMode,\n navigationSnapshot,\n nextElements: payload,\n params,\n pendingRouterState,\n previousNextUrl,\n targetHref,\n navId,\n useTransition,\n });\n } catch (error) {\n pendingNavigationRecoveryHref = null;\n throw error;\n }\n}\n\nasync function commitSameUrlNavigatePayload(\n nextElements: Promise<AppElements>,\n returnValue?: ServerActionResult[\"returnValue\"],\n): Promise<unknown> {\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n return browserNavigationController.commitSameUrlNavigatePayload(\n nextElements,\n navigationSnapshot,\n returnValue,\n );\n}\n\nfunction evictVisitedResponseCacheIfNeeded(): void {\n while (visitedResponseCache.size >= MAX_VISITED_RESPONSE_CACHE_SIZE) {\n const oldest = visitedResponseCache.keys().next().value;\n if (oldest === undefined) {\n return;\n }\n visitedResponseCache.delete(oldest);\n }\n}\n\nfunction getVisitedResponse(\n rscUrl: string,\n interceptionContext: string | null,\n mountedSlotsHeader: string | null,\n navigationKind: NavigationKind,\n): VisitedResponseCacheEntry | null {\n const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);\n const cached = visitedResponseCache.get(cacheKey);\n if (!cached) {\n return null;\n }\n\n if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n\n if (navigationKind === \"refresh\") {\n return null;\n }\n\n if (navigationKind === \"traverse\") {\n const createdAt = cached.expiresAt - VISITED_RESPONSE_CACHE_TTL;\n if (Date.now() - createdAt >= MAX_TRAVERSAL_CACHE_TTL) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n // LRU: promote to most-recently-used (delete + re-insert moves to end of Map)\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n if (cached.expiresAt > Date.now()) {\n // LRU: promote to most-recently-used\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n visitedResponseCache.delete(cacheKey);\n return null;\n}\n\nfunction storeVisitedResponseSnapshot(\n rscUrl: string,\n interceptionContext: string | null,\n snapshot: CachedRscResponse,\n params: Record<string, string | string[]>,\n): void {\n const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);\n visitedResponseCache.delete(cacheKey);\n evictVisitedResponseCacheIfNeeded();\n const now = Date.now();\n visitedResponseCache.set(cacheKey, {\n params,\n expiresAt: now + VISITED_RESPONSE_CACHE_TTL,\n response: snapshot,\n });\n}\n\ntype NavigationRequestState = {\n interceptionContext: string | null;\n previousNextUrl: string | null;\n};\n\nfunction getRequestState(\n navigationKind: NavigationKind,\n previousNextUrlOverride?: string | null,\n): NavigationRequestState {\n if (previousNextUrlOverride !== undefined) {\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrlOverride,\n __basePath,\n ),\n previousNextUrl: previousNextUrlOverride,\n };\n }\n\n switch (navigationKind) {\n case \"navigate\":\n return {\n interceptionContext: getCurrentInterceptionContext(),\n previousNextUrl: getCurrentNextUrl(),\n };\n case \"traverse\": {\n const previousNextUrl = readHistoryStatePreviousNextUrl(window.history.state);\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrl,\n __basePath,\n ),\n previousNextUrl,\n };\n }\n case \"refresh\": {\n const currentPreviousNextUrl = getBrowserRouterState().previousNextUrl;\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n currentPreviousNextUrl,\n __basePath,\n ),\n previousNextUrl: currentPreviousNextUrl,\n };\n }\n default: {\n const _exhaustive: never = navigationKind;\n throw new Error(\"[vinext] Unknown navigation kind: \" + String(_exhaustive));\n }\n }\n}\n\nfunction createRscRequestHeaders(interceptionContext: string | null): Headers {\n const headers = new Headers({ Accept: \"text/x-component\" });\n if (interceptionContext !== null) {\n headers.set(\"X-Vinext-Interception-Context\", interceptionContext);\n }\n return headers;\n}\n\n// Dev-only callback invoked when DevRecoveryBoundary catches. The replaced\n// subtree means NavigationCommitSignal's useLayoutEffect never fires, so the\n// URL update for the in-flight navigation would otherwise be lost. Force-drain\n// the queued pre-paint effect for this renderId so the URL still moves to the\n// navigation target, the dev overlay shows which URL is broken, and HMR's\n// rsc:update fetches the right payload after the bug is fixed.\nfunction handleDevRecoveryBoundaryCatch(resetKey: number): void {\n // React's onCaughtError option already routes the error to the dev overlay.\n // Our job here is purely to drive the URL update for the in-flight\n // navigation that this failed render belonged to.\n browserNavigationController.drainPrePaintEffects(resetKey);\n}\n\nfunction normalizeAppElementsPromise(payload: Promise<AppWireElements>): Promise<AppElements> {\n // Wrap in Promise.resolve() because createFromReadableStream() returns a\n // React Flight thenable whose .then() returns undefined (not a new Promise).\n // Without the wrap, chaining .then() produces undefined → use() crashes.\n return Promise.resolve(payload).then((elements) => normalizeAppElements(elements));\n}\n\nfunction BrowserRoot({\n initialElements,\n initialNavigationSnapshot,\n}: {\n initialElements: Promise<AppElements>;\n initialNavigationSnapshot: ClientNavigationRenderSnapshot;\n}) {\n const resolvedElements = use(initialElements);\n const initialMetadata = readAppElementsMetadata(resolvedElements);\n const [treeStateValue, setTreeStateValue] = useState<AppRouterState | Promise<AppRouterState>>({\n elements: resolvedElements,\n interceptionContext: initialMetadata.interceptionContext,\n layoutFlags: initialMetadata.layoutFlags,\n navigationSnapshot: initialNavigationSnapshot,\n previousNextUrl: null,\n renderId: 0,\n rootLayoutTreePath: initialMetadata.rootLayoutTreePath,\n routeId: initialMetadata.routeId,\n });\n const treeState = isRouterStatePromise(treeStateValue) ? use(treeStateValue) : treeStateValue;\n\n // Keep the latest router state in a ref so external callers (navigate(),\n // server actions, HMR) always read the current state. Safe: those readers\n // run from events/effects, never from React render itself.\n // Note: stateRef.current is written during render, not in an effect, to\n // avoid a stale-read window between commit and layout effects. This mirrors\n // the same render-phase ref update pattern used by Next.js's own router.\n const stateRef = useRef(treeState);\n stateRef.current = treeState;\n\n // Publish the stable ref object and dispatch during layout commit. This keeps\n // the module-level escape hatches aligned with React's committed tree without\n // performing module writes during render. __VINEXT_RSC_NAVIGATE__ is assigned\n // after hydrateRoot() returns; by then this layout effect has already run for\n // the hydration commit, so getBrowserRouterState() never observes a null ref.\n useLayoutEffect(() => {\n const detach = browserNavigationController.attachBrowserRouterState(\n setTreeStateValue,\n stateRef,\n );\n browserRouterStateHasEverCommitted = true;\n return () => {\n detach();\n setMountedSlotsHeader(null);\n };\n }, [setTreeStateValue]);\n\n useLayoutEffect(() => {\n setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));\n }, [treeState.elements]);\n\n useLayoutEffect(() => {\n if (treeState.renderId !== 0) {\n return;\n }\n\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, treeState.previousNextUrl),\n \"\",\n window.location.href,\n );\n }, [treeState.previousNextUrl, treeState.renderId]);\n\n const innerTree = createElement(\n NavigationCommitSignal,\n { renderId: treeState.renderId },\n createElement(\n ElementsContext.Provider,\n { value: treeState.elements },\n createElement(Slot, { id: treeState.routeId }),\n ),\n );\n\n // In dev, wrap the route tree in a top-level recovery boundary. A render\n // error (e.g. a slot's RSC reference rejects) is caught here instead of\n // tearing down BrowserRoot, so HMR can dispatch the next payload —\n // identified by an incremented renderId, which doubles as the boundary's\n // reset key — without a full page reload. The dev overlay (a separate\n // React root) shows the error itself.\n //\n // onCatch drains the pending pre-paint effect for the failed render so\n // the URL update bound to that navigation still runs. Without this, a\n // soft-nav whose target throws would leave the browser on the previous\n // URL, hiding which route is broken and mis-targeting the next HMR\n // payload (which fetches RSC for window.location.pathname).\n //\n // This file is .ts, not .tsx — children are passed positionally to satisfy\n // both the createElement overload and eslint's no-children-prop rule.\n const committedTree = import.meta.env.DEV\n ? createElement(\n DevRecoveryBoundary,\n {\n resetKey: treeState.renderId,\n onCatch: handleDevRecoveryBoundaryCatch,\n },\n innerTree,\n )\n : innerTree;\n\n const ClientNavigationRenderContext = getClientNavigationRenderContext();\n if (!ClientNavigationRenderContext) {\n return committedTree;\n }\n\n return createElement(\n ClientNavigationRenderContext.Provider,\n { value: treeState.navigationSnapshot },\n committedTree,\n );\n}\n\nfunction restoreHydrationNavigationContext(\n pathname: string,\n searchParams: SearchParamInput,\n params: Record<string, string | string[]>,\n): void {\n setNavigationContext({\n pathname,\n searchParams: new URLSearchParams(searchParams),\n params,\n });\n}\n\nfunction decodeHashFragment(fragment: string): string {\n try {\n return decodeURIComponent(fragment);\n } catch {\n return fragment;\n }\n}\n\nfunction scrollToHashTarget(hash: string): void {\n const fragment = decodeHashFragment(hash.startsWith(\"#\") ? hash.slice(1) : hash);\n\n requestAnimationFrame(() => {\n if (fragment === \"\" || fragment === \"top\") {\n window.scrollTo(0, 0);\n return;\n }\n\n const idElement = document.getElementById(fragment);\n if (idElement) {\n idElement.scrollIntoView({ behavior: \"auto\" });\n return;\n }\n\n document.getElementsByName(fragment)[0]?.scrollIntoView({ behavior: \"auto\" });\n });\n}\n\nfunction restorePopstateScrollPosition(state: unknown): void {\n if (!(state && typeof state === \"object\" && \"__vinext_scrollY\" in state)) {\n if (window.location.hash) {\n scrollToHashTarget(window.location.hash);\n }\n return;\n }\n\n const y = Number(state.__vinext_scrollY);\n const x = \"__vinext_scrollX\" in state ? Number(state.__vinext_scrollX) : 0;\n\n requestAnimationFrame(() => {\n window.scrollTo(x, y);\n });\n}\n\n// Set on pagehide so the RSC navigation catch block can distinguish expected\n// fetch aborts (triggered by the unload itself) from real errors worth logging.\nlet isPageUnloading = false;\n\nconst RSC_RELOAD_KEY = \"__vinext_rsc_initial_reload__\";\n\n// sessionStorage can throw SecurityError in strict-mode iframes, storage-\n// disabled browsers, and some Safari private-browsing configurations. Wrap\n// every access so a recovery path for one error does not crash hydration.\nfunction readReloadFlag(): string | null {\n try {\n return sessionStorage.getItem(RSC_RELOAD_KEY);\n } catch {\n return null;\n }\n}\nfunction writeReloadFlag(path: string): void {\n try {\n sessionStorage.setItem(RSC_RELOAD_KEY, path);\n } catch {}\n}\nfunction clearReloadFlag(): void {\n try {\n sessionStorage.removeItem(RSC_RELOAD_KEY);\n } catch {}\n}\n\n// A non-ok or wrong-content-type RSC response during initial hydration means\n// the server cannot deliver a valid RSC payload for this URL. Parsing the\n// response as RSC causes an opaque parse failure. On the first attempt,\n// reload once so the server has a chance to render the correct error page\n// as HTML. On the second attempt (detected via the sessionStorage flag), the\n// endpoint is persistently broken. Returns null so main() aborts the\n// hydration bootstrap without registering `__VINEXT_RSC_*` globals —\n// including during the brief window between reload() firing and the page\n// actually unloading — so external probes never see a half-hydrated page.\nfunction recoverFromBadInitialRscResponse(reason: string): null {\n const currentPath = window.location.pathname + window.location.search;\n if (readReloadFlag() === currentPath) {\n clearReloadFlag();\n console.error(\n `[vinext] Initial RSC fetch ${reason} after reload; aborting hydration. ` +\n \"Server-rendered HTML remains visible; client components will not hydrate.\",\n );\n return null;\n }\n writeReloadFlag(currentPath);\n // Verify the write persisted. In storage-denied environments (strict-mode\n // iframes, locked-down enterprise policies), every getItem returns null and\n // every setItem silently no-ops, so the reload-loop guard cannot survive\n // the reload — the page would loop forever. Abort instead so the user at\n // least sees the server-rendered HTML.\n if (readReloadFlag() !== currentPath) {\n console.error(\n `[vinext] Initial RSC fetch ${reason}; sessionStorage unavailable so the ` +\n \"reload-loop guard cannot persist — aborting hydration. \" +\n \"Server-rendered HTML remains visible; client components will not hydrate.\",\n );\n return null;\n }\n // One-shot diagnostic so a production reload is traceable. Only fires once\n // per broken path thanks to the sessionStorage flag above; not noisy.\n console.warn(\n `[vinext] Initial RSC fetch ${reason}; reloading once to let the server render the HTML error page`,\n );\n window.location.reload();\n return null;\n}\n\nasync function readInitialRscStream(): Promise<ReadableStream<Uint8Array> | null> {\n const vinext = getVinextBrowserGlobal();\n\n if (vinext.__VINEXT_RSC__ || vinext.__VINEXT_RSC_CHUNKS__ || vinext.__VINEXT_RSC_DONE__) {\n // Reaching the embedded-RSC branch means the server successfully rendered\n // the page — any prior reload flag for this path is stale and must be\n // cleared so a future failure gets its own fresh recovery attempt.\n clearReloadFlag();\n\n if (vinext.__VINEXT_RSC__) {\n const embedData = vinext.__VINEXT_RSC__;\n delete vinext.__VINEXT_RSC__;\n\n const params = embedData.params ?? {};\n if (embedData.params) {\n applyClientParams(embedData.params);\n }\n if (embedData.nav) {\n restoreHydrationNavigationContext(\n embedData.nav.pathname,\n embedData.nav.searchParams,\n params,\n );\n }\n\n return chunksToReadableStream(embedData.rsc);\n }\n\n const params = vinext.__VINEXT_RSC_PARAMS__ ?? {};\n if (vinext.__VINEXT_RSC_PARAMS__) {\n applyClientParams(vinext.__VINEXT_RSC_PARAMS__);\n }\n if (vinext.__VINEXT_RSC_NAV__) {\n restoreHydrationNavigationContext(\n vinext.__VINEXT_RSC_NAV__.pathname,\n vinext.__VINEXT_RSC_NAV__.searchParams,\n params,\n );\n }\n\n return createProgressiveRscStream();\n }\n\n const rscResponse = await fetch(toRscUrl(window.location.pathname + window.location.search));\n\n if (!rscResponse.ok) {\n return recoverFromBadInitialRscResponse(`returned ${rscResponse.status}`);\n }\n // Guard against proxies/CDNs that return 200 with a rewritten Content-Type\n // (e.g. text/html instead of text/x-component). Such responses cannot be\n // parsed as RSC and would throw the same opaque parse error this fallback\n // exists to prevent.\n const contentType = rscResponse.headers.get(\"content-type\") ?? \"\";\n if (!contentType.startsWith(\"text/x-component\")) {\n return recoverFromBadInitialRscResponse(\n `returned non-RSC content-type \"${contentType || \"(missing)\"}\"`,\n );\n }\n // Missing body (e.g. 204 No Content, or an edge worker that returned ok\n // headers without piping the stream) fails the same way downstream.\n // Matches Next.js' `!res.body` branch in fetch-server-response.ts.\n if (!rscResponse.body) {\n return recoverFromBadInitialRscResponse(\"returned empty body\");\n }\n // Successful RSC response clears the guard so a subsequent reload of the\n // same path after a transient failure still gets one recovery attempt.\n clearReloadFlag();\n\n let params: Record<string, string | string[]> = {};\n const paramsHeader = rscResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try {\n params = JSON.parse(decodeURIComponent(paramsHeader)) as Record<string, string | string[]>;\n applyClientParams(params);\n } catch {\n // Ignore malformed param headers and continue with hydration.\n }\n }\n\n restoreHydrationNavigationContext(window.location.pathname, window.location.search, params);\n\n return rscResponse.body;\n}\n\nfunction registerServerActionCallback(): void {\n setServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n const body = await encodeReply(args, { temporaryReferences });\n\n // Carry the interception context + mounted slots from the current router\n // state so the server-action re-render rebuilds the intercepted tree\n // instead of replacing it with the direct page. Parity with Next.js,\n // which sends `Next-URL` on action POSTs when the current tree contains\n // an interception route.\n const currentState = getBrowserRouterState();\n const { headers } = resolveServerActionRequestState({\n actionId: id,\n basePath: __basePath,\n elements: currentState.elements,\n previousNextUrl: currentState.previousNextUrl,\n });\n\n const fetchResponse = await fetch(toRscUrl(window.location.pathname + window.location.search), {\n method: \"POST\",\n headers,\n body,\n });\n\n if (isServerActionNotFoundResponse(fetchResponse)) {\n throw new Error(getServerActionNotFoundClientMessage(id));\n }\n\n const actionRedirect = fetchResponse.headers.get(\"x-action-redirect\");\n if (actionRedirect) {\n if (isDangerousScheme(actionRedirect)) {\n console.error(DANGEROUS_URL_BLOCK_MESSAGE);\n return undefined;\n }\n\n // Check for external URLs that need a hard redirect.\n try {\n const redirectUrl = new URL(actionRedirect, window.location.origin);\n if (redirectUrl.origin !== window.location.origin) {\n window.location.href = actionRedirect;\n return undefined;\n }\n } catch {\n // Fall through to hard redirect below if URL parsing fails.\n }\n\n // Use hard redirect for all action redirects because vinext's server\n // currently returns an empty body for redirect responses. RSC navigation\n // requires a valid RSC payload. This is a known parity gap with Next.js,\n // which pre-renders the redirect target's RSC payload.\n const redirectType = fetchResponse.headers.get(\"x-action-redirect-type\") ?? \"replace\";\n if (redirectType === \"push\") {\n window.location.assign(actionRedirect);\n } else {\n window.location.replace(actionRedirect);\n }\n return undefined;\n }\n\n clearClientNavigationCaches();\n\n const result = await createFromFetch<ServerActionResult | AppWireElements>(\n Promise.resolve(fetchResponse),\n { temporaryReferences },\n );\n\n // Server actions stay on the same URL and use commitSameUrlNavigatePayload()\n // for merge-based dispatch. This path does not call\n // activateNavigationSnapshot() because there is no URL change to commit, so\n // hooks continue reading the live external-store values directly. If server\n // actions ever trigger URL changes via RSC payload (instead of hard\n // redirects), this would need renderNavigationPayload().\n if (isServerActionResult(result)) {\n return commitSameUrlNavigatePayload(\n Promise.resolve(normalizeAppElements(result.root)),\n result.returnValue,\n );\n }\n\n return commitSameUrlNavigatePayload(Promise.resolve(normalizeAppElements(result)));\n });\n}\n\nasync function main(): Promise<void> {\n registerServerActionCallback();\n\n const rscStream = await readInitialRscStream();\n // null signals that readInitialRscStream aborted hydration — either because\n // a reload is in flight (first-attempt recovery) or the endpoint is\n // persistently broken (post-reload). Bootstrap is a separate synchronous\n // helper so the null-branch structurally cannot reach any __VINEXT_RSC_*\n // global assignment, even if a future refactor interposes async work here.\n if (rscStream === null) return;\n bootstrapHydration(rscStream);\n}\n\nfunction bootstrapHydration(rscStream: ReadableStream<Uint8Array>): void {\n if (import.meta.env.DEV) {\n installDevErrorOverlay();\n }\n\n const root = normalizeAppElementsPromise(createFromReadableStream<AppWireElements>(rscStream));\n const initialNavigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, null),\n \"\",\n window.location.href,\n );\n\n // In dev we route uncaught errors into the dev overlay rather than the\n // hard-nav recovery: the overlay is what the developer needs to see, and a\n // recovery nav would wipe it. In prod we keep the recovery hard-nav so the\n // user lands on a renderable URL with the actual error UI.\n const onUncaughtError = import.meta.env.DEV\n ? devOnUncaughtError\n : createOnUncaughtError(() => pendingNavigationRecoveryHref);\n window.__VINEXT_RSC_ROOT__ = hydrateRoot(\n document,\n createElement(BrowserRoot, {\n initialElements: root,\n initialNavigationSnapshot,\n }),\n import.meta.env.DEV\n ? { onCaughtError: devOnCaughtError, onUncaughtError }\n : { onUncaughtError },\n );\n window.__VINEXT_HYDRATED_AT = performance.now();\n\n window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(\n href: string,\n redirectDepth = 0,\n navigationKind: NavigationKind = \"navigate\",\n historyUpdateMode?: HistoryUpdateMode,\n previousNextUrlOverride?: string | null,\n programmaticTransition = false,\n ): Promise<void> {\n let pendingRouterState: PendingBrowserRouterState | null = null;\n // Hoist navId above try so the catch and finally blocks can reference it.\n const navId = browserNavigationController.beginNavigation();\n\n // Loop variables for inline redirect following. On a redirect, these are\n // updated and the loop continues without returning or re-entering navigateRsc,\n // so a single pendingRouterState spans all hops and isPending never flashes.\n let currentHref = href;\n let currentHistoryMode = historyUpdateMode;\n let currentPrevNextUrl = previousNextUrlOverride;\n let redirectCount = redirectDepth;\n\n try {\n if (programmaticTransition && hasBrowserRouterState()) {\n pendingRouterState = beginPendingBrowserRouterState();\n } else {\n await waitForBrowserRouterStateReady();\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n\n if (programmaticTransition) {\n pendingRouterState = beginPendingBrowserRouterState();\n }\n }\n\n while (true) {\n if (redirectCount > 10) {\n console.error(\n \"[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.\",\n );\n window.location.href = currentHref;\n return;\n }\n\n const url = new URL(currentHref, window.location.origin);\n const rscUrl = toRscUrl(url.pathname + url.search);\n const requestState = getRequestState(navigationKind, currentPrevNextUrl);\n const requestInterceptionContext = requestState.interceptionContext;\n const requestPreviousNextUrl = requestState.previousNextUrl;\n\n // Compare against previous pending navigation first, then committed state.\n // This avoids isSameRoute misclassification during rapid back-to-back clicks.\n const navState = getClientNavigationState();\n const currentPath =\n navState?.pendingPathname ??\n navState?.cachedPathname ??\n stripBasePath(window.location.pathname, __basePath);\n\n const targetPath = stripBasePath(url.pathname, __basePath);\n const isSameRoute = targetPath === currentPath;\n\n // Set this navigation as the pending pathname, overwriting any previous.\n // Pass navId so only this navigation (or a newer one) can clear it later.\n setPendingPathname(url.pathname, navId);\n\n const elementsAtNavStart = getBrowserRouterState().elements;\n const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);\n const cachedRoute = getVisitedResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n navigationKind,\n );\n if (cachedRoute) {\n // Check stale-navigation before and after createFromFetch. The pre-check\n // avoids wasted parse work; the post-check catches supersessions that\n // occur during the await. createFromFetch on a buffered response is fast\n // but still async, so the window exists. The non-cached path (below) places\n // its heavyweight async steps (fetch, snapshotRscResponse, createFromFetch)\n // between navId checks consistently; the cached path omits the check between\n // createClientNavigationRenderSnapshot (synchronous) and createFromFetch\n // because there is no await in that gap.\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n const cachedParams = cachedRoute.params;\n // createClientNavigationRenderSnapshot is synchronous (URL parsing + param\n // wrapping only) — no stale-navigation recheck needed between here and the\n // next await.\n const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(\n currentHref,\n cachedParams,\n );\n const cachedPayload = normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(\n Promise.resolve(restoreRscResponse(cachedRoute.response)),\n ),\n );\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n await renderNavigationPayload(\n cachedPayload,\n cachedNavigationSnapshot,\n currentHref,\n navId,\n currentHistoryMode,\n cachedParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n );\n return;\n }\n\n // Continue using the slot state captured at navigation start for fetches\n // and prefetch compatibility decisions.\n\n let navResponse: Response | undefined;\n let navResponseUrl: string | null = null;\n if (navigationKind !== \"refresh\") {\n const prefetchedResponse = consumePrefetchResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n );\n if (prefetchedResponse) {\n navResponse = restoreRscResponse(prefetchedResponse, false);\n navResponseUrl = prefetchedResponse.url;\n }\n }\n\n if (!navResponse) {\n const requestHeaders = createRscRequestHeaders(requestInterceptionContext);\n if (mountedSlotsHeader) {\n requestHeaders.set(\"X-Vinext-Mounted-Slots\", mountedSlotsHeader);\n }\n navResponse = await fetch(rscUrl, {\n headers: requestHeaders,\n credentials: \"include\",\n });\n }\n\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n\n // Any response that isn't a valid RSC payload (non-ok status,\n // missing/rewritten Content-Type, or missing body) means the server\n // returned something we cannot parse — typically an HTML error page\n // or a proxy-rewritten response. Parsing such a body as an RSC stream\n // throws a cryptic \"Connection closed\" error. Match Next.js behavior\n // (fetch-server-response.ts:211, `!isFlightResponse || !res.ok || !res.body`):\n // hard-navigate to the response URL so the server can render the correct\n // error page as HTML. The outer finally handles\n // settlePendingBrowserRouterState and clearPendingPathname on this\n // return path.\n //\n // Prefer the post-redirect response URL over `currentHref`: on a\n // redirect chain like `/old` → 307 → `/new` → 500, the browser's\n // fetch already followed the redirect, so `navResponse.url` is the\n // failing `/new` destination. Hard-navigating there directly avoids\n // bouncing off `/old` just to re-follow the same 307, which would\n // flash the wrong URL in the address bar and mis-key analytics.\n // Matches Next.js' `doMpaNavigation(responseUrl.toString())`. Falls\n // back to `currentHref` when no response URL is available.\n const navContentType = navResponse.headers.get(\"content-type\") ?? \"\";\n const isRscResponse = navContentType.startsWith(\"text/x-component\");\n if (!navResponse.ok || !isRscResponse || !navResponse.body) {\n const responseUrl = navResponseUrl ?? navResponse.url;\n let hardNavTarget = currentHref;\n if (responseUrl) {\n const parsed = new URL(responseUrl, window.location.origin);\n const origUrl = new URL(currentHref, window.location.origin);\n let pathname = parsed.pathname.replace(/\\.rsc$/, \"\");\n // toRscUrl strips trailing slash before appending .rsc, so the\n // response URL loses it on the round-trip. Restore it when the\n // original href had one so sites with trailingSlash:true don't\n // incur an extra 308 to the canonical form on the error path.\n if (\n origUrl.pathname.length > 1 &&\n origUrl.pathname.endsWith(\"/\") &&\n !pathname.endsWith(\"/\")\n ) {\n pathname += \"/\";\n }\n hardNavTarget = pathname + parsed.search;\n // Preserve the hash from the user's clicked href — a .rsc response\n // URL never carries a fragment, so dropping it would silently strip\n // `/foo#section` down to `/foo`.\n if (origUrl.hash) hardNavTarget += origUrl.hash;\n }\n window.location.href = hardNavTarget;\n return;\n }\n\n const finalUrl = new URL(navResponseUrl ?? navResponse.url, window.location.origin);\n const requestedUrl = new URL(rscUrl, window.location.origin);\n\n if (finalUrl.pathname !== requestedUrl.pathname) {\n // Server-side redirect: update the URL in history and loop to fetch\n // the destination without settling pendingRouterState. This keeps\n // isPending true across all redirect hops instead of flashing false.\n const destinationPath = finalUrl.pathname.replace(/\\.rsc$/, \"\") + finalUrl.search;\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(null, requestPreviousNextUrl),\n \"\",\n destinationPath,\n );\n\n currentHref = destinationPath;\n // URL already written above; the commit effect must not push/replace again.\n currentHistoryMode = undefined;\n currentPrevNextUrl = requestPreviousNextUrl;\n redirectCount += 1;\n continue;\n }\n\n let navParams: Record<string, string | string[]> = {};\n const paramsHeader = navResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try {\n navParams = JSON.parse(decodeURIComponent(paramsHeader)) as Record<\n string,\n string | string[]\n >;\n } catch {\n // navParams stays as {}\n }\n }\n // Build snapshot from local params, not latestClientParams\n const navigationSnapshot = createClientNavigationRenderSnapshot(currentHref, navParams);\n\n const responseSnapshot = await snapshotRscResponse(navResponse);\n\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n\n const rscPayload = normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(Promise.resolve(restoreRscResponse(responseSnapshot))),\n );\n\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n\n await renderNavigationPayload(\n rscPayload,\n navigationSnapshot,\n currentHref,\n navId,\n currentHistoryMode,\n navParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n );\n // Don't cache the response if this navigation was superseded during\n // renderNavigationPayload's await — the elements were never dispatched.\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n // Store the visited response only after renderNavigationPayload succeeds.\n // If we stored it before and renderNavigationPayload threw, a future\n // back/forward navigation could replay a snapshot from a navigation that\n // never actually rendered successfully.\n const resolvedElements = await rscPayload;\n const metadata = readAppElementsMetadata(resolvedElements);\n storeVisitedResponseSnapshot(\n rscUrl,\n resolveVisitedResponseInterceptionContext(\n requestInterceptionContext,\n metadata.interceptionContext,\n ),\n responseSnapshot,\n navParams,\n );\n return;\n }\n } catch (error) {\n // Don't hard-navigate to a stale URL if this navigation was superseded by\n // a newer one — the newer navigation is already in flight and would be clobbered.\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n // Suppress the diagnostic when the page is unloading: a hard-nav or anchor\n // click tears down the document and aborts any in-flight RSC fetch, which\n // surfaces here as an error. The page is already going away, so the log\n // is just noise. Mirrors Next.js' isPageUnloading pattern.\n if (!isPageUnloading) {\n console.error(\"[vinext] RSC navigation error:\", error);\n }\n window.location.href = currentHref;\n } finally {\n // Single settlement site: covers normal return, early returns on stale-id\n // checks, and error paths. The finally runs even when the catch returns.\n // settlePendingBrowserRouterState is idempotent via the settled flag.\n browserNavigationController.finalizeNavigation(navId, pendingRouterState);\n }\n };\n\n if (\"scrollRestoration\" in history) {\n history.scrollRestoration = \"manual\";\n }\n\n // Note: This popstate handler runs for App Router (RSC navigation available).\n // It coordinates scroll restoration with the pending RSC navigation.\n // Pages Router scroll restoration is handled in shims/navigation.ts:1289 with\n // microtask-based deferral for compatibility with non-RSC navigation.\n // See: https://github.com/vercel/next.js/discussions/41934#discussioncomment-4602607\n window.addEventListener(\"popstate\", (event) => {\n notifyAppRouterTransitionStart(window.location.href, \"traverse\");\n const pendingNavigation =\n window.__VINEXT_RSC_NAVIGATE__?.(window.location.href, 0, \"traverse\") ?? Promise.resolve();\n window.__VINEXT_RSC_PENDING__ = pendingNavigation;\n void pendingNavigation.finally(() => {\n restorePopstateScrollPosition(event.state);\n if (window.__VINEXT_RSC_PENDING__ === pendingNavigation) {\n window.__VINEXT_RSC_PENDING__ = null;\n }\n });\n });\n\n if (import.meta.hot) {\n import.meta.hot.on(\"rsc:update\", async () => {\n try {\n // If BrowserRoot has been mounted before but isn't now, a render\n // error tore down the tree (e.g. a server route threw). HMR can't\n // dispatch into a missing setter, and waitForBrowserRouterStateReady\n // would block forever — the tree won't remount until the page reloads.\n // Trigger that reload so the user's fix actually lands without a\n // manual refresh. Cleared after a successful mount, so this only\n // fires once per teardown.\n if (\n browserRouterStateHasEverCommitted &&\n !browserNavigationController.hasBrowserRouterState()\n ) {\n window.location.reload();\n return;\n }\n // HMR can also fire before BrowserRoot's layout effect publishes\n // the browser router state (e.g. saving a file while the initial RSC\n // stream is still suspended). Wait for readiness, then re-check the\n // mounted state — readiness can race with cleanup, which nulls it again.\n // Skip silently when the tree is not currently mounted; the next\n // HMR push or full reload will reconcile.\n await waitForBrowserRouterStateReady();\n if (!browserNavigationController.hasBrowserRouterState()) {\n return;\n }\n clearClientNavigationCaches();\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n // Clear stale errors from the dev overlay before dispatching the\n // fresh tree. If the new tree renders cleanly, the overlay stays\n // empty; if it throws again, devOnCaughtError/devOnUncaughtError\n // re-populates it. Without this, an old \"DropZone is not defined\"\n // error would linger after the developer fixed the bug.\n dismissOverlay();\n // Interception context on HMR re-renders is intentionally deferred:\n // preserving intercepted modal state across HMR reloads is out of scope\n // for the previousNextUrl mechanism.\n await browserNavigationController.hmrReplaceTree(\n normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(\n fetch(toRscUrl(window.location.pathname + window.location.search)),\n ),\n ),\n navigationSnapshot,\n );\n } catch (error) {\n console.error(\"[vinext] RSC HMR error:\", error);\n }\n });\n }\n}\n\nif (typeof document !== \"undefined\") {\n window.addEventListener(\"pagehide\", () => {\n isPageUnloading = true;\n });\n // Reset on pageshow so a bfcache-restored document does not resume with\n // the flag stuck at true, which would silently swallow every subsequent\n // RSC navigation error for the lifetime of that tab. Matches Next.js'\n // fetch-server-response.ts handler pair.\n window.addEventListener(\"pageshow\", () => {\n isPageUnloading = false;\n });\n void main();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-browser-entry.js","names":[],"sources":["../../src/server/app-browser-entry.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\n\nimport { createElement, use, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n createFromFetch,\n createFromReadableStream,\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport \"../client/instrumentation-client.js\";\nimport { notifyAppRouterTransitionStart } from \"../client/instrumentation-client-state.js\";\nimport {\n __basePath,\n commitClientNavigationState,\n consumePrefetchResponse,\n createClientNavigationRenderSnapshot,\n getCurrentNextUrl,\n getCurrentInterceptionContext,\n getClientNavigationRenderContext,\n getClientNavigationState,\n getPrefetchCache,\n getPrefetchedUrls,\n pushHistoryStateWithoutNotify,\n replaceClientParamsWithoutNotify,\n replaceHistoryStateWithoutNotify,\n restoreRscResponse,\n setClientParams,\n setPendingPathname,\n snapshotRscResponse,\n setMountedSlotsHeader,\n setNavigationContext,\n type CachedRscResponse,\n type ClientNavigationRenderSnapshot,\n} from \"vinext/shims/navigation\";\nimport { stripBasePath } from \"../utils/base-path.js\";\nimport {\n chunksToReadableStream,\n createProgressiveRscStream,\n getVinextBrowserGlobal,\n} from \"./app-browser-stream.js\";\nimport {\n createAppBrowserNavigationController,\n type HistoryUpdateMode,\n type NavigationPayloadOutcome,\n type PendingBrowserRouterState,\n} from \"./app-browser-navigation-controller.js\";\nimport {\n AppElementsWire,\n getMountedSlotIdsHeader,\n resolveVisitedResponseInterceptionContext,\n type AppElements,\n type AppWireElements,\n} from \"./app-elements.js\";\nimport {\n createHistoryStateWithPreviousNextUrl,\n readHistoryStatePreviousNextUrl,\n resolveInterceptionContextFromPreviousNextUrl,\n resolveServerActionRequestState,\n type AppRouterState,\n type OperationLane,\n} from \"./app-browser-state.js\";\nimport { DevRecoveryBoundary } from \"vinext/shims/error-boundary\";\nimport { ElementsContext, Slot } from \"vinext/shims/slot\";\nimport { createOnUncaughtError } from \"./app-browser-error.js\";\nimport {\n devOnCaughtError,\n devOnUncaughtError,\n dismissOverlay,\n installDevErrorOverlay,\n} from \"./dev-error-overlay.js\";\nimport { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from \"vinext/shims/url-safety\";\nimport {\n getServerActionNotFoundClientMessage,\n isServerActionNotFoundResponse,\n} from \"./server-action-not-found.js\";\nimport {\n createRscRequestHeaders,\n createRscRequestUrl,\n stripRscCacheBustingSearchParam,\n stripRscSuffix,\n VINEXT_RSC_CONTENT_TYPE,\n VINEXT_RSC_MOUNTED_SLOTS_HEADER,\n} from \"./app-rsc-cache-busting.js\";\n\ntype SearchParamInput = ConstructorParameters<typeof URLSearchParams>[0];\n\ntype ServerActionResult = {\n root: AppWireElements;\n returnValue?: {\n ok: boolean;\n data: unknown;\n };\n};\n\ntype NavigationKind = \"navigate\" | \"traverse\" | \"refresh\";\n\n// Maps NavigationKind to the AppRouterAction type used by the reducer.\n// \"refresh\" is intentionally treated as \"navigate\" (merge, preserve absent slots).\n// Both call sites must stay in sync — update here if NavigationKind gains new values.\nfunction toActionType(kind: NavigationKind): \"navigate\" | \"traverse\" {\n return kind === \"traverse\" ? \"traverse\" : \"navigate\";\n}\n\nfunction toOperationLane(kind: NavigationKind): OperationLane {\n switch (kind) {\n case \"navigate\":\n return \"navigation\";\n case \"refresh\":\n return \"refresh\";\n case \"traverse\":\n return \"traverse\";\n default: {\n const _exhaustive: never = kind;\n throw new Error(\"[vinext] Unknown navigation kind: \" + String(_exhaustive));\n }\n }\n}\n\ntype VisitedResponseCacheEntry = {\n params: Record<string, string | string[]>;\n expiresAt: number;\n response: CachedRscResponse;\n};\n\nconst MAX_VISITED_RESPONSE_CACHE_SIZE = 50;\nconst VISITED_RESPONSE_CACHE_TTL = 5 * 60_000;\nconst MAX_TRAVERSAL_CACHE_TTL = 30 * 60_000;\nconst browserNavigationController = createAppBrowserNavigationController();\nconst NavigationCommitSignal = browserNavigationController.NavigationCommitSignal;\n\n// Parses a URI-encoded JSON value carried in a response header (e.g.\n// `X-Vinext-Params`). Returns `null` on missing or malformed input so callers\n// can fall back to their own defaults. Silent by design — these headers are\n// best-effort hydration data and a parse failure should not break navigation.\nfunction parseEncodedJsonHeader<T>(value: string | null): T | null {\n if (!value) return null;\n try {\n return JSON.parse(decodeURIComponent(value)) as T;\n } catch {\n return null;\n }\n}\n\nfunction isRouterStatePromise(\n value: AppRouterState | Promise<AppRouterState>,\n): value is Promise<AppRouterState> {\n return value instanceof Promise;\n}\n\nlet latestClientParams: Record<string, string | string[]> = {};\nconst visitedResponseCache = new Map<string, VisitedResponseCacheEntry>();\n// Sticky bit: stays true once BrowserRoot has committed at least once. Used by\n// the HMR handler to distinguish \"still hydrating\" (wait) from \"was up, then\n// torn down by a render error\" (full reload to recover).\nlet browserRouterStateHasEverCommitted = false;\n// Most recent navigation target that has been dispatched but not yet committed.\n// Read by the onUncaughtError handler so a render error tearing down the tree\n// can land the browser on the URL the user was actually navigating to, instead\n// of stranding them on the previous URL with a blank page. Cleared once the\n// commit effect runs (URL update succeeded) or the navigation is superseded.\nlet pendingNavigationRecoveryHref: string | null = null;\n\nfunction isServerActionResult(value: unknown): value is ServerActionResult {\n return !!value && typeof value === \"object\" && \"root\" in value;\n}\n\nfunction getBrowserRouterState(): AppRouterState {\n return browserNavigationController.getBrowserRouterState();\n}\n\nfunction hasBrowserRouterState(): boolean {\n return browserNavigationController.hasBrowserRouterState();\n}\n\nfunction waitForBrowserRouterStateReady(): Promise<void> {\n return browserNavigationController.waitForBrowserRouterStateReady();\n}\n\nfunction beginPendingBrowserRouterState(): PendingBrowserRouterState {\n return browserNavigationController.beginPendingBrowserRouterState();\n}\n\nfunction applyClientParams(params: Record<string, string | string[]>): void {\n latestClientParams = params;\n setClientParams(params);\n}\n\nfunction stageClientParams(params: Record<string, string | string[]>): void {\n // NB: latestClientParams diverges from ClientNavigationState.clientParams\n // between staging and commit. Server action snapshots (same-URL\n // commitSameUrlNavigatePayload() calls inside registerServerActionCallback)\n // read latestClientParams, so a\n // server action fired during this window would get the pending (not yet\n // committed) params. This is acceptable because the commit effect fires\n // before hooks observe the new URL state, keeping the window vanishingly small.\n latestClientParams = params;\n replaceClientParamsWithoutNotify(params);\n}\n\nfunction clearVisitedResponseCache(): void {\n visitedResponseCache.clear();\n}\n\nfunction clearPrefetchState(): void {\n getPrefetchCache().clear();\n getPrefetchedUrls().clear();\n}\n\nfunction clearClientNavigationCaches(): void {\n clearVisitedResponseCache();\n clearPrefetchState();\n}\n\nfunction createNavigationCommitEffect(options: {\n href: string;\n historyUpdateMode: HistoryUpdateMode | undefined;\n navId: number;\n params: Record<string, string | string[]>;\n previousNextUrl: string | null;\n}): () => void {\n const { href, historyUpdateMode, navId, params, previousNextUrl } = options;\n\n return () => {\n // Only update URL if this is still the active navigation.\n // A newer navigation would have superseded this navigation id.\n if (!browserNavigationController.isCurrentNavigation(navId)) {\n // This transition was superseded before commit; balance the active\n // snapshot counter without clearing pendingPathname ownership.\n commitClientNavigationState(undefined, { releaseSnapshot: true });\n return;\n }\n\n const targetHref = new URL(href, window.location.origin).href;\n stageClientParams(params);\n const preserveExistingState = historyUpdateMode === \"replace\";\n const historyState = createHistoryStateWithPreviousNextUrl(\n preserveExistingState ? window.history.state : null,\n previousNextUrl,\n );\n\n if (historyUpdateMode === \"replace\" && window.location.href !== targetHref) {\n replaceHistoryStateWithoutNotify(historyState, \"\", href);\n } else if (historyUpdateMode === \"push\" && window.location.href !== targetHref) {\n pushHistoryStateWithoutNotify(historyState, \"\", href);\n }\n\n // URL has been updated; the recovery hard-nav target is no longer needed.\n pendingNavigationRecoveryHref = null;\n commitClientNavigationState(navId);\n };\n}\n\nasync function renderNavigationPayload(\n payload: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n targetHref: string,\n navId: number,\n historyUpdateMode: HistoryUpdateMode | undefined,\n params: Record<string, string | string[]>,\n previousNextUrl: string | null,\n pendingRouterState: PendingBrowserRouterState | null,\n useTransition = true,\n actionType: \"navigate\" | \"replace\" | \"traverse\" = \"navigate\",\n operationLane: OperationLane = \"navigation\",\n): Promise<NavigationPayloadOutcome> {\n try {\n return await browserNavigationController.renderNavigationPayload({\n actionType,\n createNavigationCommitEffect: (options) => {\n pendingNavigationRecoveryHref = options.href;\n return createNavigationCommitEffect(options);\n },\n historyUpdateMode,\n navigationSnapshot,\n nextElements: payload,\n operationLane,\n params,\n pendingRouterState,\n previousNextUrl,\n targetHref,\n navId,\n useTransition,\n });\n } catch (error) {\n pendingNavigationRecoveryHref = null;\n throw error;\n }\n}\n\nasync function commitSameUrlNavigatePayload(\n nextElements: Promise<AppElements>,\n returnValue?: ServerActionResult[\"returnValue\"],\n actionInitiationState?: AppRouterState,\n): Promise<unknown> {\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n return browserNavigationController.commitSameUrlNavigatePayload(\n nextElements,\n navigationSnapshot,\n returnValue,\n actionInitiationState,\n );\n}\n\nfunction evictVisitedResponseCacheIfNeeded(): void {\n while (visitedResponseCache.size >= MAX_VISITED_RESPONSE_CACHE_SIZE) {\n const oldest = visitedResponseCache.keys().next().value;\n if (oldest === undefined) {\n return;\n }\n visitedResponseCache.delete(oldest);\n }\n}\n\nfunction getVisitedResponse(\n rscUrl: string,\n interceptionContext: string | null,\n mountedSlotsHeader: string | null,\n navigationKind: NavigationKind,\n): VisitedResponseCacheEntry | null {\n const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);\n const cached = visitedResponseCache.get(cacheKey);\n if (!cached) {\n return null;\n }\n\n if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n\n if (navigationKind === \"refresh\") {\n return null;\n }\n\n if (navigationKind === \"traverse\") {\n const createdAt = cached.expiresAt - VISITED_RESPONSE_CACHE_TTL;\n if (Date.now() - createdAt >= MAX_TRAVERSAL_CACHE_TTL) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n // LRU: promote to most-recently-used (delete + re-insert moves to end of Map)\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n if (cached.expiresAt > Date.now()) {\n // LRU: promote to most-recently-used\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n visitedResponseCache.delete(cacheKey);\n return null;\n}\n\nfunction storeVisitedResponseSnapshot(\n rscUrl: string,\n interceptionContext: string | null,\n snapshot: CachedRscResponse,\n params: Record<string, string | string[]>,\n): void {\n const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);\n visitedResponseCache.delete(cacheKey);\n evictVisitedResponseCacheIfNeeded();\n const now = Date.now();\n visitedResponseCache.set(cacheKey, {\n params,\n expiresAt: now + VISITED_RESPONSE_CACHE_TTL,\n response: snapshot,\n });\n}\n\ntype NavigationRequestState = {\n interceptionContext: string | null;\n previousNextUrl: string | null;\n};\n\nfunction getRequestState(\n navigationKind: NavigationKind,\n previousNextUrlOverride?: string | null,\n): NavigationRequestState {\n if (previousNextUrlOverride !== undefined) {\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrlOverride,\n __basePath,\n ),\n previousNextUrl: previousNextUrlOverride,\n };\n }\n\n switch (navigationKind) {\n case \"navigate\":\n return {\n interceptionContext: getCurrentInterceptionContext(),\n previousNextUrl: getCurrentNextUrl(),\n };\n case \"traverse\": {\n const previousNextUrl = readHistoryStatePreviousNextUrl(window.history.state);\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrl,\n __basePath,\n ),\n previousNextUrl,\n };\n }\n case \"refresh\": {\n const currentPreviousNextUrl = getBrowserRouterState().previousNextUrl;\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n currentPreviousNextUrl,\n __basePath,\n ),\n previousNextUrl: currentPreviousNextUrl,\n };\n }\n default: {\n const _exhaustive: never = navigationKind;\n throw new Error(\"[vinext] Unknown navigation kind: \" + String(_exhaustive));\n }\n }\n}\n\n// Dev-only callback invoked when DevRecoveryBoundary catches. The replaced\n// subtree means NavigationCommitSignal's useLayoutEffect never fires, so the\n// URL update for the in-flight navigation would otherwise be lost. Force-drain\n// the queued pre-paint effect for this renderId so the URL still moves to the\n// navigation target, the dev overlay shows which URL is broken, and HMR's\n// rsc:update fetches the right payload after the bug is fixed.\nfunction handleDevRecoveryBoundaryCatch(resetKey: number): void {\n // React's onCaughtError option already routes the error to the dev overlay.\n // Our job here is purely to drive the URL update for the in-flight\n // navigation that this failed render belonged to.\n browserNavigationController.drainPrePaintEffects(resetKey);\n}\n\nfunction decodeAppElementsPromise(payload: Promise<AppWireElements>): Promise<AppElements> {\n // Wrap in Promise.resolve() because createFromReadableStream() returns a\n // React Flight thenable whose .then() returns undefined (not a new Promise).\n // Without the wrap, chaining .then() produces undefined → use() crashes.\n return Promise.resolve(payload).then((elements) => AppElementsWire.decode(elements));\n}\n\nfunction BrowserRoot({\n initialElements,\n initialNavigationSnapshot,\n}: {\n initialElements: Promise<AppElements>;\n initialNavigationSnapshot: ClientNavigationRenderSnapshot;\n}) {\n const resolvedElements = use(initialElements);\n const initialMetadata = AppElementsWire.readMetadata(resolvedElements);\n const [treeStateValue, setTreeStateValue] = useState<AppRouterState | Promise<AppRouterState>>({\n activeOperation: null,\n elements: resolvedElements,\n interceptionContext: initialMetadata.interceptionContext,\n layoutFlags: initialMetadata.layoutFlags,\n navigationSnapshot: initialNavigationSnapshot,\n previousNextUrl: null,\n renderId: 0,\n rootLayoutTreePath: initialMetadata.rootLayoutTreePath,\n routeId: initialMetadata.routeId,\n visibleCommitVersion: 0,\n });\n const treeState = isRouterStatePromise(treeStateValue) ? use(treeStateValue) : treeStateValue;\n\n // Keep the latest router state in a ref so external callers (navigate(),\n // server actions, HMR) always read the current state. Safe: those readers\n // run from events/effects, never from React render itself.\n // Note: stateRef.current is written during render, not in an effect, to\n // avoid a stale-read window between commit and layout effects. This mirrors\n // the same render-phase ref update pattern used by Next.js's own router.\n const stateRef = useRef(treeState);\n stateRef.current = treeState;\n\n // Publish the stable ref object and dispatch during layout commit. This keeps\n // the module-level escape hatches aligned with React's committed tree without\n // performing module writes during render. __VINEXT_RSC_NAVIGATE__ is assigned\n // after hydrateRoot() returns; by then this layout effect has already run for\n // the hydration commit, so getBrowserRouterState() never observes a null ref.\n useLayoutEffect(() => {\n const detach = browserNavigationController.attachBrowserRouterState(\n setTreeStateValue,\n stateRef,\n );\n browserRouterStateHasEverCommitted = true;\n return () => {\n detach();\n setMountedSlotsHeader(null);\n };\n }, [setTreeStateValue]);\n\n useLayoutEffect(() => {\n setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));\n }, [treeState.elements]);\n\n useLayoutEffect(() => {\n if (treeState.renderId !== 0) {\n return;\n }\n\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, treeState.previousNextUrl),\n \"\",\n window.location.href,\n );\n }, [treeState.previousNextUrl, treeState.renderId]);\n\n const innerTree = createElement(\n NavigationCommitSignal,\n { renderId: treeState.renderId },\n createElement(\n ElementsContext.Provider,\n { value: treeState.elements },\n createElement(Slot, { id: treeState.routeId }),\n ),\n );\n\n // In dev, wrap the route tree in a top-level recovery boundary. A render\n // error (e.g. a slot's RSC reference rejects) is caught here instead of\n // tearing down BrowserRoot, so HMR can dispatch the next payload —\n // identified by an incremented renderId, which doubles as the boundary's\n // reset key — without a full page reload. The dev overlay (a separate\n // React root) shows the error itself.\n //\n // onCatch drains the pending pre-paint effect for the failed render so\n // the URL update bound to that navigation still runs. Without this, a\n // soft-nav whose target throws would leave the browser on the previous\n // URL, hiding which route is broken and mis-targeting the next HMR\n // payload (which fetches RSC for window.location.pathname).\n //\n // This file is .ts, not .tsx — children are passed positionally to satisfy\n // both the createElement overload and eslint's no-children-prop rule.\n const committedTree = import.meta.env.DEV\n ? createElement(\n DevRecoveryBoundary,\n {\n resetKey: treeState.renderId,\n onCatch: handleDevRecoveryBoundaryCatch,\n },\n innerTree,\n )\n : innerTree;\n\n const ClientNavigationRenderContext = getClientNavigationRenderContext();\n if (!ClientNavigationRenderContext) {\n return committedTree;\n }\n\n return createElement(\n ClientNavigationRenderContext.Provider,\n { value: treeState.navigationSnapshot },\n committedTree,\n );\n}\n\nfunction restoreHydrationNavigationContext(\n pathname: string,\n searchParams: SearchParamInput,\n params: Record<string, string | string[]>,\n): void {\n setNavigationContext({\n pathname,\n searchParams: new URLSearchParams(searchParams),\n params,\n });\n}\n\nfunction decodeHashFragment(fragment: string): string {\n try {\n return decodeURIComponent(fragment);\n } catch {\n return fragment;\n }\n}\n\nfunction scrollToHashTarget(hash: string): void {\n const fragment = decodeHashFragment(hash.startsWith(\"#\") ? hash.slice(1) : hash);\n\n requestAnimationFrame(() => {\n if (fragment === \"\" || fragment === \"top\") {\n window.scrollTo(0, 0);\n return;\n }\n\n const idElement = document.getElementById(fragment);\n if (idElement) {\n idElement.scrollIntoView({ behavior: \"auto\" });\n return;\n }\n\n document.getElementsByName(fragment)[0]?.scrollIntoView({ behavior: \"auto\" });\n });\n}\n\nfunction restorePopstateScrollPosition(state: unknown): void {\n if (!(state && typeof state === \"object\" && \"__vinext_scrollY\" in state)) {\n if (window.location.hash) {\n scrollToHashTarget(window.location.hash);\n }\n return;\n }\n\n const y = Number(state.__vinext_scrollY);\n const x = \"__vinext_scrollX\" in state ? Number(state.__vinext_scrollX) : 0;\n\n requestAnimationFrame(() => {\n window.scrollTo(x, y);\n });\n}\n\n// Set on pagehide so the RSC navigation catch block can distinguish expected\n// fetch aborts (triggered by the unload itself) from real errors worth logging.\nlet isPageUnloading = false;\n\nconst RSC_RELOAD_KEY = \"__vinext_rsc_initial_reload__\";\n\n// sessionStorage can throw SecurityError in strict-mode iframes, storage-\n// disabled browsers, and some Safari private-browsing configurations. Wrap\n// every access so a recovery path for one error does not crash hydration.\nfunction readReloadFlag(): string | null {\n try {\n return sessionStorage.getItem(RSC_RELOAD_KEY);\n } catch {\n return null;\n }\n}\nfunction writeReloadFlag(path: string): void {\n try {\n sessionStorage.setItem(RSC_RELOAD_KEY, path);\n } catch {}\n}\nfunction clearReloadFlag(): void {\n try {\n sessionStorage.removeItem(RSC_RELOAD_KEY);\n } catch {}\n}\n\n// A non-ok or wrong-content-type RSC response during initial hydration means\n// the server cannot deliver a valid RSC payload for this URL. Parsing the\n// response as RSC causes an opaque parse failure. On the first attempt,\n// reload once so the server has a chance to render the correct error page\n// as HTML. On the second attempt (detected via the sessionStorage flag), the\n// endpoint is persistently broken. Returns null so main() aborts the\n// hydration bootstrap without registering `__VINEXT_RSC_*` globals —\n// including during the brief window between reload() firing and the page\n// actually unloading — so external probes never see a half-hydrated page.\nfunction recoverFromBadInitialRscResponse(reason: string): null {\n const currentPath = window.location.pathname + window.location.search;\n if (readReloadFlag() === currentPath) {\n clearReloadFlag();\n console.error(\n `[vinext] Initial RSC fetch ${reason} after reload; aborting hydration. ` +\n \"Server-rendered HTML remains visible; client components will not hydrate.\",\n );\n return null;\n }\n writeReloadFlag(currentPath);\n // Verify the write persisted. In storage-denied environments (strict-mode\n // iframes, locked-down enterprise policies), every getItem returns null and\n // every setItem silently no-ops, so the reload-loop guard cannot survive\n // the reload — the page would loop forever. Abort instead so the user at\n // least sees the server-rendered HTML.\n if (readReloadFlag() !== currentPath) {\n console.error(\n `[vinext] Initial RSC fetch ${reason}; sessionStorage unavailable so the ` +\n \"reload-loop guard cannot persist — aborting hydration. \" +\n \"Server-rendered HTML remains visible; client components will not hydrate.\",\n );\n return null;\n }\n // One-shot diagnostic so a production reload is traceable. Only fires once\n // per broken path thanks to the sessionStorage flag above; not noisy.\n console.warn(\n `[vinext] Initial RSC fetch ${reason}; reloading once to let the server render the HTML error page`,\n );\n window.location.reload();\n return null;\n}\n\nasync function readInitialRscStream(): Promise<ReadableStream<Uint8Array> | null> {\n const vinext = getVinextBrowserGlobal();\n\n if (vinext.__VINEXT_RSC__ || vinext.__VINEXT_RSC_CHUNKS__ || vinext.__VINEXT_RSC_DONE__) {\n // Reaching the embedded-RSC branch means the server successfully rendered\n // the page — any prior reload flag for this path is stale and must be\n // cleared so a future failure gets its own fresh recovery attempt.\n clearReloadFlag();\n\n if (vinext.__VINEXT_RSC__) {\n const embedData = vinext.__VINEXT_RSC__;\n delete vinext.__VINEXT_RSC__;\n\n const params = embedData.params ?? {};\n if (embedData.params) {\n applyClientParams(embedData.params);\n }\n if (embedData.nav) {\n restoreHydrationNavigationContext(\n embedData.nav.pathname,\n embedData.nav.searchParams,\n params,\n );\n }\n\n return chunksToReadableStream(embedData.rsc);\n }\n\n const params = vinext.__VINEXT_RSC_PARAMS__ ?? {};\n if (vinext.__VINEXT_RSC_PARAMS__) {\n applyClientParams(vinext.__VINEXT_RSC_PARAMS__);\n }\n if (vinext.__VINEXT_RSC_NAV__) {\n restoreHydrationNavigationContext(\n vinext.__VINEXT_RSC_NAV__.pathname,\n vinext.__VINEXT_RSC_NAV__.searchParams,\n params,\n );\n }\n\n return createProgressiveRscStream();\n }\n\n const rscHeaders = createRscRequestHeaders();\n const rscResponse = await fetch(\n await createRscRequestUrl(window.location.pathname + window.location.search, rscHeaders),\n { credentials: \"include\", headers: rscHeaders },\n );\n\n if (!rscResponse.ok) {\n return recoverFromBadInitialRscResponse(`returned ${rscResponse.status}`);\n }\n // Guard against proxies/CDNs that return 200 with a rewritten Content-Type\n // (e.g. text/html instead of text/x-component). Such responses cannot be\n // parsed as RSC and would throw the same opaque parse error this fallback\n // exists to prevent.\n const contentType = rscResponse.headers.get(\"content-type\") ?? \"\";\n if (!contentType.startsWith(VINEXT_RSC_CONTENT_TYPE)) {\n return recoverFromBadInitialRscResponse(\n `returned non-RSC content-type \"${contentType || \"(missing)\"}\"`,\n );\n }\n // Missing body (e.g. 204 No Content, or an edge worker that returned ok\n // headers without piping the stream) fails the same way downstream.\n // Matches Next.js' `!res.body` branch in fetch-server-response.ts.\n if (!rscResponse.body) {\n return recoverFromBadInitialRscResponse(\"returned empty body\");\n }\n // Successful RSC response clears the guard so a subsequent reload of the\n // same path after a transient failure still gets one recovery attempt.\n clearReloadFlag();\n\n // Ignore malformed param headers and continue with hydration. The original\n // try/catch also swallowed errors from applyClientParams; preserve that.\n const parsedParams = parseEncodedJsonHeader<Record<string, string | string[]>>(\n rscResponse.headers.get(\"X-Vinext-Params\"),\n );\n const params: Record<string, string | string[]> = parsedParams ?? {};\n if (parsedParams) {\n try {\n applyClientParams(parsedParams);\n } catch {\n // Ignore — matches the previous combined try/catch behavior.\n }\n }\n\n restoreHydrationNavigationContext(window.location.pathname, window.location.search, params);\n\n return rscResponse.body;\n}\n\nfunction registerServerActionCallback(): void {\n setServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n const body = await encodeReply(args, { temporaryReferences });\n\n // Carry the interception context + mounted slots from the current router\n // state so the server-action re-render rebuilds the intercepted tree\n // instead of replacing it with the direct page. Parity with Next.js,\n // which sends `Next-URL` on action POSTs when the current tree contains\n // an interception route.\n const currentState = getBrowserRouterState();\n const { headers } = resolveServerActionRequestState({\n actionId: id,\n basePath: __basePath,\n elements: currentState.elements,\n previousNextUrl: currentState.previousNextUrl,\n });\n\n const fetchResponse = await fetch(\n await createRscRequestUrl(window.location.pathname + window.location.search, headers),\n {\n method: \"POST\",\n headers,\n body,\n },\n );\n\n if (isServerActionNotFoundResponse(fetchResponse)) {\n throw new Error(getServerActionNotFoundClientMessage(id));\n }\n\n const actionRedirect = fetchResponse.headers.get(\"x-action-redirect\");\n if (actionRedirect) {\n if (isDangerousScheme(actionRedirect)) {\n console.error(DANGEROUS_URL_BLOCK_MESSAGE);\n return undefined;\n }\n\n // Check for external URLs that need a hard redirect.\n try {\n const redirectUrl = new URL(actionRedirect, window.location.origin);\n if (redirectUrl.origin !== window.location.origin) {\n window.location.href = actionRedirect;\n return undefined;\n }\n } catch {\n // Fall through to hard redirect below if URL parsing fails.\n }\n\n // Use hard redirect for all action redirects because vinext's server\n // currently returns an empty body for redirect responses. RSC navigation\n // requires a valid RSC payload. This is a known parity gap with Next.js,\n // which pre-renders the redirect target's RSC payload.\n const redirectType = fetchResponse.headers.get(\"x-action-redirect-type\") ?? \"replace\";\n if (redirectType === \"push\") {\n window.location.assign(actionRedirect);\n } else {\n window.location.replace(actionRedirect);\n }\n return undefined;\n }\n\n clearClientNavigationCaches();\n\n const result = await createFromFetch<ServerActionResult | AppWireElements>(\n Promise.resolve(fetchResponse),\n { temporaryReferences },\n );\n\n // Server actions stay on the same URL and use commitSameUrlNavigatePayload()\n // for merge-based dispatch. This path does not call\n // activateNavigationSnapshot() because there is no URL change to commit, so\n // hooks continue reading the live external-store values directly. If server\n // actions ever trigger URL changes via RSC payload (instead of hard\n // redirects), this would need renderNavigationPayload().\n if (isServerActionResult(result)) {\n return commitSameUrlNavigatePayload(\n Promise.resolve(AppElementsWire.decode(result.root)),\n result.returnValue,\n currentState,\n );\n }\n\n return commitSameUrlNavigatePayload(\n Promise.resolve(AppElementsWire.decode(result)),\n undefined,\n currentState,\n );\n });\n}\n\nasync function main(): Promise<void> {\n registerServerActionCallback();\n\n const rscStream = await readInitialRscStream();\n // null signals that readInitialRscStream aborted hydration — either because\n // a reload is in flight (first-attempt recovery) or the endpoint is\n // persistently broken (post-reload). Bootstrap is a separate synchronous\n // helper so the null-branch structurally cannot reach any __VINEXT_RSC_*\n // global assignment, even if a future refactor interposes async work here.\n if (rscStream === null) return;\n bootstrapHydration(rscStream);\n}\n\nfunction bootstrapHydration(rscStream: ReadableStream<Uint8Array>): void {\n if (import.meta.env.DEV) {\n installDevErrorOverlay();\n }\n\n const root = decodeAppElementsPromise(createFromReadableStream<AppWireElements>(rscStream));\n const initialNavigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, null),\n \"\",\n window.location.href,\n );\n\n // In dev we route uncaught errors into the dev overlay rather than the\n // hard-nav recovery: the overlay is what the developer needs to see, and a\n // recovery nav would wipe it. In prod we keep the recovery hard-nav so the\n // user lands on a renderable URL with the actual error UI.\n const onUncaughtError = import.meta.env.DEV\n ? devOnUncaughtError\n : createOnUncaughtError(() => pendingNavigationRecoveryHref);\n window.__VINEXT_RSC_ROOT__ = hydrateRoot(\n document,\n createElement(BrowserRoot, {\n initialElements: root,\n initialNavigationSnapshot,\n }),\n import.meta.env.DEV\n ? { onCaughtError: devOnCaughtError, onUncaughtError }\n : { onUncaughtError },\n );\n window.__VINEXT_HYDRATED_AT = performance.now();\n\n window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(\n href: string,\n redirectDepth = 0,\n navigationKind: NavigationKind = \"navigate\",\n historyUpdateMode?: HistoryUpdateMode,\n previousNextUrlOverride?: string | null,\n programmaticTransition = false,\n ): Promise<void> {\n let pendingRouterState: PendingBrowserRouterState | null = null;\n // Hoist navId above try so the catch and finally blocks can reference it.\n const navId = browserNavigationController.beginNavigation();\n\n // Loop variables for inline redirect following. On a redirect, these are\n // updated and the loop continues without returning or re-entering navigateRsc,\n // so a single pendingRouterState spans all hops and isPending never flashes.\n let currentHref = href;\n let currentHistoryMode = historyUpdateMode;\n let currentPrevNextUrl = previousNextUrlOverride;\n let redirectCount = redirectDepth;\n\n try {\n if (programmaticTransition && hasBrowserRouterState()) {\n pendingRouterState = beginPendingBrowserRouterState();\n } else {\n await waitForBrowserRouterStateReady();\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n\n if (programmaticTransition) {\n pendingRouterState = beginPendingBrowserRouterState();\n }\n }\n\n while (true) {\n if (redirectCount > 10) {\n console.error(\n \"[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.\",\n );\n window.location.href = currentHref;\n return;\n }\n\n const url = new URL(currentHref, window.location.origin);\n const requestState = getRequestState(navigationKind, currentPrevNextUrl);\n const requestInterceptionContext = requestState.interceptionContext;\n const requestPreviousNextUrl = requestState.previousNextUrl;\n\n // Compare against previous pending navigation first, then committed state.\n // This avoids isSameRoute misclassification during rapid back-to-back clicks.\n const navState = getClientNavigationState();\n const currentPath =\n navState?.pendingPathname ??\n navState?.cachedPathname ??\n stripBasePath(window.location.pathname, __basePath);\n\n const targetPath = stripBasePath(url.pathname, __basePath);\n const isSameRoute = targetPath === currentPath;\n\n // Set this navigation as the pending pathname, overwriting any previous.\n // Pass navId so only this navigation (or a newer one) can clear it later.\n setPendingPathname(url.pathname, navId);\n\n const elementsAtNavStart = getBrowserRouterState().elements;\n const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);\n const requestHeaders = createRscRequestHeaders({\n interceptionContext: requestInterceptionContext,\n });\n if (mountedSlotsHeader) {\n requestHeaders.set(VINEXT_RSC_MOUNTED_SLOTS_HEADER, mountedSlotsHeader);\n }\n const rscUrl = await createRscRequestUrl(url.pathname + url.search, requestHeaders);\n const cachedRoute = getVisitedResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n navigationKind,\n );\n if (cachedRoute) {\n // Check stale-navigation before and after createFromFetch. The pre-check\n // avoids wasted parse work; the post-check catches supersessions that\n // occur during the await. createFromFetch on a buffered response is fast\n // but still async, so the window exists. The non-cached path (below) places\n // its heavyweight async steps (fetch, snapshotRscResponse, createFromFetch)\n // between navId checks consistently; the cached path omits the check between\n // createClientNavigationRenderSnapshot (synchronous) and createFromFetch\n // because there is no await in that gap.\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n const cachedParams = cachedRoute.params;\n // createClientNavigationRenderSnapshot is synchronous (URL parsing + param\n // wrapping only) — no stale-navigation recheck needed between here and the\n // next await.\n const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(\n currentHref,\n cachedParams,\n );\n const cachedPayload = decodeAppElementsPromise(\n createFromFetch<AppWireElements>(\n Promise.resolve(restoreRscResponse(cachedRoute.response)),\n ),\n );\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n await renderNavigationPayload(\n cachedPayload,\n cachedNavigationSnapshot,\n currentHref,\n navId,\n currentHistoryMode,\n cachedParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n toOperationLane(navigationKind),\n );\n return;\n }\n\n // Continue using the slot state captured at navigation start for fetches\n // and prefetch compatibility decisions.\n\n let navResponse: Response | undefined;\n let navResponseUrl: string | null = null;\n if (navigationKind !== \"refresh\") {\n const prefetchedResponse = consumePrefetchResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n );\n if (prefetchedResponse) {\n navResponse = restoreRscResponse(prefetchedResponse, false);\n navResponseUrl = prefetchedResponse.url;\n }\n }\n\n if (!navResponse) {\n navResponse = await fetch(rscUrl, {\n headers: requestHeaders,\n credentials: \"include\",\n });\n }\n\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n\n // Any response that isn't a valid RSC payload (non-ok status,\n // missing/rewritten Content-Type, or missing body) means the server\n // returned something we cannot parse — typically an HTML error page\n // or a proxy-rewritten response. Parsing such a body as an RSC stream\n // throws a cryptic \"Connection closed\" error. Match Next.js behavior\n // (fetch-server-response.ts:211, `!isFlightResponse || !res.ok || !res.body`):\n // hard-navigate to the response URL so the server can render the correct\n // error page as HTML. The outer finally handles\n // settlePendingBrowserRouterState and clearPendingPathname on this\n // return path.\n //\n // Prefer the post-redirect response URL over `currentHref`: on a\n // redirect chain like `/old` → 307 → `/new` → 500, the browser's\n // fetch already followed the redirect, so `navResponse.url` is the\n // failing `/new` destination. Hard-navigating there directly avoids\n // bouncing off `/old` just to re-follow the same 307, which would\n // flash the wrong URL in the address bar and mis-key analytics.\n // Matches Next.js' `doMpaNavigation(responseUrl.toString())`. Falls\n // back to `currentHref` when no response URL is available.\n const navContentType = navResponse.headers.get(\"content-type\") ?? \"\";\n const isRscResponse = navContentType.startsWith(\"text/x-component\");\n if (!navResponse.ok || !isRscResponse || !navResponse.body) {\n const responseUrl = navResponseUrl ?? navResponse.url;\n let hardNavTarget = currentHref;\n if (responseUrl) {\n const parsed = new URL(responseUrl, window.location.origin);\n stripRscCacheBustingSearchParam(parsed);\n const origUrl = new URL(currentHref, window.location.origin);\n let pathname = stripRscSuffix(parsed.pathname);\n // createRscRequestUrl strips trailing slash before appending .rsc,\n // so the response URL loses it on the round-trip. Restore it when\n // the original href had one so sites with trailingSlash:true don't\n // incur an extra 308 to the canonical form on the error path.\n if (\n origUrl.pathname.length > 1 &&\n origUrl.pathname.endsWith(\"/\") &&\n !pathname.endsWith(\"/\")\n ) {\n pathname += \"/\";\n }\n hardNavTarget = pathname + parsed.search;\n // Preserve the hash from the user's clicked href — a .rsc response\n // URL never carries a fragment, so dropping it would silently strip\n // `/foo#section` down to `/foo`.\n if (origUrl.hash) hardNavTarget += origUrl.hash;\n }\n window.location.href = hardNavTarget;\n return;\n }\n\n const finalUrl = new URL(navResponseUrl ?? navResponse.url, window.location.origin);\n stripRscCacheBustingSearchParam(finalUrl);\n const requestedUrl = new URL(rscUrl, window.location.origin);\n\n if (finalUrl.pathname !== requestedUrl.pathname) {\n // Server-side redirect: update the URL in history and loop to fetch\n // the destination without settling pendingRouterState. This keeps\n // isPending true across all redirect hops instead of flashing false.\n const destinationPath = stripRscSuffix(finalUrl.pathname) + finalUrl.search;\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(null, requestPreviousNextUrl),\n \"\",\n destinationPath,\n );\n\n currentHref = destinationPath;\n // URL already written above; the commit effect must not push/replace again.\n currentHistoryMode = undefined;\n currentPrevNextUrl = requestPreviousNextUrl;\n redirectCount += 1;\n continue;\n }\n\n // navParams falls back to {} on a missing or malformed header.\n const navParams: Record<string, string | string[]> =\n parseEncodedJsonHeader<Record<string, string | string[]>>(\n navResponse.headers.get(\"X-Vinext-Params\"),\n ) ?? {};\n // Build snapshot from local params, not latestClientParams\n const navigationSnapshot = createClientNavigationRenderSnapshot(currentHref, navParams);\n\n const responseSnapshot = await snapshotRscResponse(navResponse);\n\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n\n const rscPayload = decodeAppElementsPromise(\n createFromFetch<AppWireElements>(Promise.resolve(restoreRscResponse(responseSnapshot))),\n );\n\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n\n const renderOutcome = await renderNavigationPayload(\n rscPayload,\n navigationSnapshot,\n currentHref,\n navId,\n currentHistoryMode,\n navParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n toOperationLane(navigationKind),\n );\n if (renderOutcome !== \"committed\") return;\n // Don't cache the response if this navigation was superseded during\n // renderNavigationPayload's await — the elements were never dispatched.\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n // Store the visited response only after renderNavigationPayload succeeds.\n // If we stored it before and renderNavigationPayload threw, a future\n // back/forward navigation could replay a snapshot from a navigation that\n // never actually rendered successfully.\n const resolvedElements = await rscPayload;\n const metadata = AppElementsWire.readMetadata(resolvedElements);\n storeVisitedResponseSnapshot(\n rscUrl,\n resolveVisitedResponseInterceptionContext(\n requestInterceptionContext,\n metadata.interceptionContext,\n ),\n responseSnapshot,\n navParams,\n );\n return;\n }\n } catch (error) {\n // Don't hard-navigate to a stale URL if this navigation was superseded by\n // a newer one — the newer navigation is already in flight and would be clobbered.\n if (!browserNavigationController.isCurrentNavigation(navId)) return;\n // Suppress the diagnostic when the page is unloading: a hard-nav or anchor\n // click tears down the document and aborts any in-flight RSC fetch, which\n // surfaces here as an error. The page is already going away, so the log\n // is just noise. Mirrors Next.js' isPageUnloading pattern.\n if (!isPageUnloading) {\n console.error(\"[vinext] RSC navigation error:\", error);\n }\n window.location.href = currentHref;\n } finally {\n // Single settlement site: covers normal return, early returns on stale-id\n // checks, and error paths. The finally runs even when the catch returns.\n // settlePendingBrowserRouterState is idempotent via the settled flag.\n browserNavigationController.finalizeNavigation(navId, pendingRouterState);\n }\n };\n\n if (\"scrollRestoration\" in history) {\n history.scrollRestoration = \"manual\";\n }\n\n // Note: This popstate handler runs for App Router (RSC navigation available).\n // It coordinates scroll restoration with the pending RSC navigation.\n // Pages Router scroll restoration is handled in shims/navigation.ts:1289 with\n // microtask-based deferral for compatibility with non-RSC navigation.\n // See: https://github.com/vercel/next.js/discussions/41934#discussioncomment-4602607\n window.addEventListener(\"popstate\", (event) => {\n notifyAppRouterTransitionStart(window.location.href, \"traverse\");\n const pendingNavigation =\n window.__VINEXT_RSC_NAVIGATE__?.(window.location.href, 0, \"traverse\") ?? Promise.resolve();\n window.__VINEXT_RSC_PENDING__ = pendingNavigation;\n void pendingNavigation.finally(() => {\n restorePopstateScrollPosition(event.state);\n if (window.__VINEXT_RSC_PENDING__ === pendingNavigation) {\n window.__VINEXT_RSC_PENDING__ = null;\n }\n });\n });\n\n if (import.meta.hot) {\n import.meta.hot.on(\"rsc:update\", async () => {\n try {\n // If BrowserRoot has been mounted before but isn't now, a render\n // error tore down the tree (e.g. a server route threw). HMR can't\n // dispatch into a missing setter, and waitForBrowserRouterStateReady\n // would block forever — the tree won't remount until the page reloads.\n // Trigger that reload so the user's fix actually lands without a\n // manual refresh. Cleared after a successful mount, so this only\n // fires once per teardown.\n if (\n browserRouterStateHasEverCommitted &&\n !browserNavigationController.hasBrowserRouterState()\n ) {\n window.location.reload();\n return;\n }\n // HMR can also fire before BrowserRoot's layout effect publishes\n // the browser router state (e.g. saving a file while the initial RSC\n // stream is still suspended). Wait for readiness, then re-check the\n // mounted state — readiness can race with cleanup, which nulls it again.\n // Skip silently when the tree is not currently mounted; the next\n // HMR push or full reload will reconcile.\n await waitForBrowserRouterStateReady();\n if (!browserNavigationController.hasBrowserRouterState()) {\n return;\n }\n clearClientNavigationCaches();\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n // Clear stale errors from the dev overlay before dispatching the\n // fresh tree. If the new tree renders cleanly, the overlay stays\n // empty; if it throws again, devOnCaughtError/devOnUncaughtError\n // re-populates it. Without this, an old \"DropZone is not defined\"\n // error would linger after the developer fixed the bug.\n dismissOverlay();\n // Interception context on HMR re-renders is intentionally deferred:\n // preserving intercepted modal state across HMR reloads is out of scope\n // for the previousNextUrl mechanism.\n const hmrHeaders = createRscRequestHeaders();\n await browserNavigationController.hmrReplaceTree(\n decodeAppElementsPromise(\n createFromFetch<AppWireElements>(\n fetch(\n await createRscRequestUrl(\n window.location.pathname + window.location.search,\n hmrHeaders,\n ),\n { headers: hmrHeaders },\n ),\n ),\n ),\n navigationSnapshot,\n );\n } catch (error) {\n console.error(\"[vinext] RSC HMR error:\", error);\n }\n });\n }\n}\n\nif (typeof document !== \"undefined\") {\n window.addEventListener(\"pagehide\", () => {\n isPageUnloading = true;\n });\n // Reset on pageshow so a bfcache-restored document does not resume with\n // the flag stuck at true, which would silently swallow every subsequent\n // RSC navigation error for the lifetime of that tab. Matches Next.js'\n // fetch-server-response.ts handler pair.\n window.addEventListener(\"pageshow\", () => {\n isPageUnloading = false;\n });\n void main();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAqGA,SAAS,aAAa,MAA+C;AACnE,QAAO,SAAS,aAAa,aAAa;;AAG5C,SAAS,gBAAgB,MAAqC;AAC5D,SAAQ,MAAR;EACE,KAAK,WACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,WACH,QAAO;EACT,QAEE,OAAM,IAAI,MAAM,uCAAuC,OAD5B,KAC+C,CAAC;;;AAWjF,MAAM,kCAAkC;AACxC,MAAM,6BAA6B,IAAI;AACvC,MAAM,0BAA0B,KAAK;AACrC,MAAM,8BAA8B,sCAAsC;AAC1E,MAAM,yBAAyB,4BAA4B;AAM3D,SAAS,uBAA0B,OAAgC;AACjE,KAAI,CAAC,MAAO,QAAO;AACnB,KAAI;AACF,SAAO,KAAK,MAAM,mBAAmB,MAAM,CAAC;SACtC;AACN,SAAO;;;AAIX,SAAS,qBACP,OACkC;AAClC,QAAO,iBAAiB;;AAG1B,IAAI,qBAAwD,EAAE;AAC9D,MAAM,uCAAuB,IAAI,KAAwC;AAIzE,IAAI,qCAAqC;AAMzC,IAAI,gCAA+C;AAEnD,SAAS,qBAAqB,OAA6C;AACzE,QAAO,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,UAAU;;AAG3D,SAAS,wBAAwC;AAC/C,QAAO,4BAA4B,uBAAuB;;AAG5D,SAAS,wBAAiC;AACxC,QAAO,4BAA4B,uBAAuB;;AAG5D,SAAS,iCAAgD;AACvD,QAAO,4BAA4B,gCAAgC;;AAGrE,SAAS,iCAA4D;AACnE,QAAO,4BAA4B,gCAAgC;;AAGrE,SAAS,kBAAkB,QAAiD;AAC1E,sBAAqB;AACrB,iBAAgB,OAAO;;AAGzB,SAAS,kBAAkB,QAAiD;AAQ1E,sBAAqB;AACrB,kCAAiC,OAAO;;AAG1C,SAAS,4BAAkC;AACzC,sBAAqB,OAAO;;AAG9B,SAAS,qBAA2B;AAClC,mBAAkB,CAAC,OAAO;AAC1B,oBAAmB,CAAC,OAAO;;AAG7B,SAAS,8BAAoC;AAC3C,4BAA2B;AAC3B,qBAAoB;;AAGtB,SAAS,6BAA6B,SAMvB;CACb,MAAM,EAAE,MAAM,mBAAmB,OAAO,QAAQ,oBAAoB;AAEpE,cAAa;AAGX,MAAI,CAAC,4BAA4B,oBAAoB,MAAM,EAAE;AAG3D,+BAA4B,KAAA,GAAW,EAAE,iBAAiB,MAAM,CAAC;AACjE;;EAGF,MAAM,aAAa,IAAI,IAAI,MAAM,OAAO,SAAS,OAAO,CAAC;AACzD,oBAAkB,OAAO;EAEzB,MAAM,eAAe,sCADS,sBAAsB,YAE1B,OAAO,QAAQ,QAAQ,MAC/C,gBACD;AAED,MAAI,sBAAsB,aAAa,OAAO,SAAS,SAAS,WAC9D,kCAAiC,cAAc,IAAI,KAAK;WAC/C,sBAAsB,UAAU,OAAO,SAAS,SAAS,WAClE,+BAA8B,cAAc,IAAI,KAAK;AAIvD,kCAAgC;AAChC,8BAA4B,MAAM;;;AAItC,eAAe,wBACb,SACA,oBACA,YACA,OACA,mBACA,QACA,iBACA,oBACA,gBAAgB,MAChB,aAAkD,YAClD,gBAA+B,cACI;AACnC,KAAI;AACF,SAAO,MAAM,4BAA4B,wBAAwB;GAC/D;GACA,+BAA+B,YAAY;AACzC,oCAAgC,QAAQ;AACxC,WAAO,6BAA6B,QAAQ;;GAE9C;GACA;GACA,cAAc;GACd;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;UACK,OAAO;AACd,kCAAgC;AAChC,QAAM;;;AAIV,eAAe,6BACb,cACA,aACA,uBACkB;CAClB,MAAM,qBAAqB,qCACzB,OAAO,SAAS,MAChB,mBACD;AACD,QAAO,4BAA4B,6BACjC,cACA,oBACA,aACA,sBACD;;AAGH,SAAS,oCAA0C;AACjD,QAAO,qBAAqB,QAAQ,iCAAiC;EACnE,MAAM,SAAS,qBAAqB,MAAM,CAAC,MAAM,CAAC;AAClD,MAAI,WAAW,KAAA,EACb;AAEF,uBAAqB,OAAO,OAAO;;;AAIvC,SAAS,mBACP,QACA,qBACA,oBACA,gBACkC;CAClC,MAAM,WAAW,gBAAgB,eAAe,QAAQ,oBAAoB;CAC5E,MAAM,SAAS,qBAAqB,IAAI,SAAS;AACjD,KAAI,CAAC,OACH,QAAO;AAGT,MAAK,OAAO,SAAS,sBAAsB,UAAU,oBAAoB;AACvE,uBAAqB,OAAO,SAAS;AACrC,SAAO;;AAGT,KAAI,mBAAmB,UACrB,QAAO;AAGT,KAAI,mBAAmB,YAAY;EACjC,MAAM,YAAY,OAAO,YAAY;AACrC,MAAI,KAAK,KAAK,GAAG,aAAa,yBAAyB;AACrD,wBAAqB,OAAO,SAAS;AACrC,UAAO;;AAGT,uBAAqB,OAAO,SAAS;AACrC,uBAAqB,IAAI,UAAU,OAAO;AAC1C,SAAO;;AAGT,KAAI,OAAO,YAAY,KAAK,KAAK,EAAE;AAEjC,uBAAqB,OAAO,SAAS;AACrC,uBAAqB,IAAI,UAAU,OAAO;AAC1C,SAAO;;AAGT,sBAAqB,OAAO,SAAS;AACrC,QAAO;;AAGT,SAAS,6BACP,QACA,qBACA,UACA,QACM;CACN,MAAM,WAAW,gBAAgB,eAAe,QAAQ,oBAAoB;AAC5E,sBAAqB,OAAO,SAAS;AACrC,oCAAmC;CACnC,MAAM,MAAM,KAAK,KAAK;AACtB,sBAAqB,IAAI,UAAU;EACjC;EACA,WAAW,MAAM;EACjB,UAAU;EACX,CAAC;;AAQJ,SAAS,gBACP,gBACA,yBACwB;AACxB,KAAI,4BAA4B,KAAA,EAC9B,QAAO;EACL,qBAAqB,8CACnB,yBACA,WACD;EACD,iBAAiB;EAClB;AAGH,SAAQ,gBAAR;EACE,KAAK,WACH,QAAO;GACL,qBAAqB,+BAA+B;GACpD,iBAAiB,mBAAmB;GACrC;EACH,KAAK,YAAY;GACf,MAAM,kBAAkB,gCAAgC,OAAO,QAAQ,MAAM;AAC7E,UAAO;IACL,qBAAqB,8CACnB,iBACA,WACD;IACD;IACD;;EAEH,KAAK,WAAW;GACd,MAAM,yBAAyB,uBAAuB,CAAC;AACvD,UAAO;IACL,qBAAqB,8CACnB,wBACA,WACD;IACD,iBAAiB;IAClB;;EAEH,QAEE,OAAM,IAAI,MAAM,uCAAuC,OAD5B,eAC+C,CAAC;;;AAWjF,SAAS,+BAA+B,UAAwB;AAI9D,6BAA4B,qBAAqB,SAAS;;AAG5D,SAAS,yBAAyB,SAAyD;AAIzF,QAAO,QAAQ,QAAQ,QAAQ,CAAC,MAAM,aAAa,gBAAgB,OAAO,SAAS,CAAC;;AAGtF,SAAS,YAAY,EACnB,iBACA,6BAIC;CACD,MAAM,mBAAmB,IAAI,gBAAgB;CAC7C,MAAM,kBAAkB,gBAAgB,aAAa,iBAAiB;CACtE,MAAM,CAAC,gBAAgB,qBAAqB,SAAmD;EAC7F,iBAAiB;EACjB,UAAU;EACV,qBAAqB,gBAAgB;EACrC,aAAa,gBAAgB;EAC7B,oBAAoB;EACpB,iBAAiB;EACjB,UAAU;EACV,oBAAoB,gBAAgB;EACpC,SAAS,gBAAgB;EACzB,sBAAsB;EACvB,CAAC;CACF,MAAM,YAAY,qBAAqB,eAAe,GAAG,IAAI,eAAe,GAAG;CAQ/E,MAAM,WAAW,OAAO,UAAU;AAClC,UAAS,UAAU;AAOnB,uBAAsB;EACpB,MAAM,SAAS,4BAA4B,yBACzC,mBACA,SACD;AACD,uCAAqC;AACrC,eAAa;AACX,WAAQ;AACR,yBAAsB,KAAK;;IAE5B,CAAC,kBAAkB,CAAC;AAEvB,uBAAsB;AACpB,wBAAsB,wBAAwB,SAAS,QAAQ,SAAS,CAAC;IACxE,CAAC,UAAU,SAAS,CAAC;AAExB,uBAAsB;AACpB,MAAI,UAAU,aAAa,EACzB;AAGF,mCACE,sCAAsC,OAAO,QAAQ,OAAO,UAAU,gBAAgB,EACtF,IACA,OAAO,SAAS,KACjB;IACA,CAAC,UAAU,iBAAiB,UAAU,SAAS,CAAC;CAEnD,MAAM,YAAY,cAChB,wBACA,EAAE,UAAU,UAAU,UAAU,EAChC,cACE,gBAAgB,UAChB,EAAE,OAAO,UAAU,UAAU,EAC7B,cAAc,MAAM,EAAE,IAAI,UAAU,SAAS,CAAC,CAC/C,CACF;CAiBD,MAAM,gBAAgB,OAAO,KAAK,IAAI,MAClC,cACE,qBACA;EACE,UAAU,UAAU;EACpB,SAAS;EACV,EACD,UACD,GACD;CAEJ,MAAM,gCAAgC,kCAAkC;AACxE,KAAI,CAAC,8BACH,QAAO;AAGT,QAAO,cACL,8BAA8B,UAC9B,EAAE,OAAO,UAAU,oBAAoB,EACvC,cACD;;AAGH,SAAS,kCACP,UACA,cACA,QACM;AACN,sBAAqB;EACnB;EACA,cAAc,IAAI,gBAAgB,aAAa;EAC/C;EACD,CAAC;;AAGJ,SAAS,mBAAmB,UAA0B;AACpD,KAAI;AACF,SAAO,mBAAmB,SAAS;SAC7B;AACN,SAAO;;;AAIX,SAAS,mBAAmB,MAAoB;CAC9C,MAAM,WAAW,mBAAmB,KAAK,WAAW,IAAI,GAAG,KAAK,MAAM,EAAE,GAAG,KAAK;AAEhF,6BAA4B;AAC1B,MAAI,aAAa,MAAM,aAAa,OAAO;AACzC,UAAO,SAAS,GAAG,EAAE;AACrB;;EAGF,MAAM,YAAY,SAAS,eAAe,SAAS;AACnD,MAAI,WAAW;AACb,aAAU,eAAe,EAAE,UAAU,QAAQ,CAAC;AAC9C;;AAGF,WAAS,kBAAkB,SAAS,CAAC,IAAI,eAAe,EAAE,UAAU,QAAQ,CAAC;GAC7E;;AAGJ,SAAS,8BAA8B,OAAsB;AAC3D,KAAI,EAAE,SAAS,OAAO,UAAU,YAAY,sBAAsB,QAAQ;AACxE,MAAI,OAAO,SAAS,KAClB,oBAAmB,OAAO,SAAS,KAAK;AAE1C;;CAGF,MAAM,IAAI,OAAO,MAAM,iBAAiB;CACxC,MAAM,IAAI,sBAAsB,QAAQ,OAAO,MAAM,iBAAiB,GAAG;AAEzE,6BAA4B;AAC1B,SAAO,SAAS,GAAG,EAAE;GACrB;;AAKJ,IAAI,kBAAkB;AAEtB,MAAM,iBAAiB;AAKvB,SAAS,iBAAgC;AACvC,KAAI;AACF,SAAO,eAAe,QAAQ,eAAe;SACvC;AACN,SAAO;;;AAGX,SAAS,gBAAgB,MAAoB;AAC3C,KAAI;AACF,iBAAe,QAAQ,gBAAgB,KAAK;SACtC;;AAEV,SAAS,kBAAwB;AAC/B,KAAI;AACF,iBAAe,WAAW,eAAe;SACnC;;AAYV,SAAS,iCAAiC,QAAsB;CAC9D,MAAM,cAAc,OAAO,SAAS,WAAW,OAAO,SAAS;AAC/D,KAAI,gBAAgB,KAAK,aAAa;AACpC,mBAAiB;AACjB,UAAQ,MACN,8BAA8B,OAAO,8GAEtC;AACD,SAAO;;AAET,iBAAgB,YAAY;AAM5B,KAAI,gBAAgB,KAAK,aAAa;AACpC,UAAQ,MACN,8BAA8B,OAAO,sKAGtC;AACD,SAAO;;AAIT,SAAQ,KACN,8BAA8B,OAAO,+DACtC;AACD,QAAO,SAAS,QAAQ;AACxB,QAAO;;AAGT,eAAe,uBAAmE;CAChF,MAAM,SAAS,wBAAwB;AAEvC,KAAI,OAAO,kBAAkB,OAAO,yBAAyB,OAAO,qBAAqB;AAIvF,mBAAiB;AAEjB,MAAI,OAAO,gBAAgB;GACzB,MAAM,YAAY,OAAO;AACzB,UAAO,OAAO;GAEd,MAAM,SAAS,UAAU,UAAU,EAAE;AACrC,OAAI,UAAU,OACZ,mBAAkB,UAAU,OAAO;AAErC,OAAI,UAAU,IACZ,mCACE,UAAU,IAAI,UACd,UAAU,IAAI,cACd,OACD;AAGH,UAAO,uBAAuB,UAAU,IAAI;;EAG9C,MAAM,SAAS,OAAO,yBAAyB,EAAE;AACjD,MAAI,OAAO,sBACT,mBAAkB,OAAO,sBAAsB;AAEjD,MAAI,OAAO,mBACT,mCACE,OAAO,mBAAmB,UAC1B,OAAO,mBAAmB,cAC1B,OACD;AAGH,SAAO,4BAA4B;;CAGrC,MAAM,aAAa,yBAAyB;CAC5C,MAAM,cAAc,MAAM,MACxB,MAAM,oBAAoB,OAAO,SAAS,WAAW,OAAO,SAAS,QAAQ,WAAW,EACxF;EAAE,aAAa;EAAW,SAAS;EAAY,CAChD;AAED,KAAI,CAAC,YAAY,GACf,QAAO,iCAAiC,YAAY,YAAY,SAAS;CAM3E,MAAM,cAAc,YAAY,QAAQ,IAAI,eAAe,IAAI;AAC/D,KAAI,CAAC,YAAY,WAAA,mBAAmC,CAClD,QAAO,iCACL,kCAAkC,eAAe,YAAY,GAC9D;AAKH,KAAI,CAAC,YAAY,KACf,QAAO,iCAAiC,sBAAsB;AAIhE,kBAAiB;CAIjB,MAAM,eAAe,uBACnB,YAAY,QAAQ,IAAI,kBAAkB,CAC3C;CACD,MAAM,SAA4C,gBAAgB,EAAE;AACpE,KAAI,aACF,KAAI;AACF,oBAAkB,aAAa;SACzB;AAKV,mCAAkC,OAAO,SAAS,UAAU,OAAO,SAAS,QAAQ,OAAO;AAE3F,QAAO,YAAY;;AAGrB,SAAS,+BAAqC;AAC5C,mBAAkB,OAAO,IAAI,SAAS;EACpC,MAAM,sBAAsB,6BAA6B;EACzD,MAAM,OAAO,MAAM,YAAY,MAAM,EAAE,qBAAqB,CAAC;EAO7D,MAAM,eAAe,uBAAuB;EAC5C,MAAM,EAAE,YAAY,gCAAgC;GAClD,UAAU;GACV,UAAU;GACV,UAAU,aAAa;GACvB,iBAAiB,aAAa;GAC/B,CAAC;EAEF,MAAM,gBAAgB,MAAM,MAC1B,MAAM,oBAAoB,OAAO,SAAS,WAAW,OAAO,SAAS,QAAQ,QAAQ,EACrF;GACE,QAAQ;GACR;GACA;GACD,CACF;AAED,MAAI,+BAA+B,cAAc,CAC/C,OAAM,IAAI,MAAM,qCAAqC,GAAG,CAAC;EAG3D,MAAM,iBAAiB,cAAc,QAAQ,IAAI,oBAAoB;AACrE,MAAI,gBAAgB;AAClB,OAAI,kBAAkB,eAAe,EAAE;AACrC,YAAQ,MAAM,4BAA4B;AAC1C;;AAIF,OAAI;AAEF,QADoB,IAAI,IAAI,gBAAgB,OAAO,SAAS,OAAO,CACnD,WAAW,OAAO,SAAS,QAAQ;AACjD,YAAO,SAAS,OAAO;AACvB;;WAEI;AASR,QADqB,cAAc,QAAQ,IAAI,yBAAyB,IAAI,eACvD,OACnB,QAAO,SAAS,OAAO,eAAe;OAEtC,QAAO,SAAS,QAAQ,eAAe;AAEzC;;AAGF,+BAA6B;EAE7B,MAAM,SAAS,MAAM,gBACnB,QAAQ,QAAQ,cAAc,EAC9B,EAAE,qBAAqB,CACxB;AAQD,MAAI,qBAAqB,OAAO,CAC9B,QAAO,6BACL,QAAQ,QAAQ,gBAAgB,OAAO,OAAO,KAAK,CAAC,EACpD,OAAO,aACP,aACD;AAGH,SAAO,6BACL,QAAQ,QAAQ,gBAAgB,OAAO,OAAO,CAAC,EAC/C,KAAA,GACA,aACD;GACD;;AAGJ,eAAe,OAAsB;AACnC,+BAA8B;CAE9B,MAAM,YAAY,MAAM,sBAAsB;AAM9C,KAAI,cAAc,KAAM;AACxB,oBAAmB,UAAU;;AAG/B,SAAS,mBAAmB,WAA6C;AACvE,KAAI,OAAO,KAAK,IAAI,IAClB,yBAAwB;CAG1B,MAAM,OAAO,yBAAyB,yBAA0C,UAAU,CAAC;CAC3F,MAAM,4BAA4B,qCAChC,OAAO,SAAS,MAChB,mBACD;AACD,kCACE,sCAAsC,OAAO,QAAQ,OAAO,KAAK,EACjE,IACA,OAAO,SAAS,KACjB;CAMD,MAAM,kBAAkB,OAAO,KAAK,IAAI,MACpC,qBACA,4BAA4B,8BAA8B;AAC9D,QAAO,sBAAsB,YAC3B,UACA,cAAc,aAAa;EACzB,iBAAiB;EACjB;EACD,CAAC,EACF,OAAO,KAAK,IAAI,MACZ;EAAE,eAAe;EAAkB;EAAiB,GACpD,EAAE,iBAAiB,CACxB;AACD,QAAO,uBAAuB,YAAY,KAAK;AAE/C,QAAO,0BAA0B,eAAe,YAC9C,MACA,gBAAgB,GAChB,iBAAiC,YACjC,mBACA,yBACA,yBAAyB,OACV;EACf,IAAI,qBAAuD;EAE3D,MAAM,QAAQ,4BAA4B,iBAAiB;EAK3D,IAAI,cAAc;EAClB,IAAI,qBAAqB;EACzB,IAAI,qBAAqB;EACzB,IAAI,gBAAgB;AAEpB,MAAI;AACF,OAAI,0BAA0B,uBAAuB,CACnD,sBAAqB,gCAAgC;QAChD;AACL,UAAM,gCAAgC;AACtC,QAAI,CAAC,4BAA4B,oBAAoB,MAAM,CAAE;AAE7D,QAAI,uBACF,sBAAqB,gCAAgC;;AAIzD,UAAO,MAAM;AACX,QAAI,gBAAgB,IAAI;AACtB,aAAQ,MACN,kFACD;AACD,YAAO,SAAS,OAAO;AACvB;;IAGF,MAAM,MAAM,IAAI,IAAI,aAAa,OAAO,SAAS,OAAO;IACxD,MAAM,eAAe,gBAAgB,gBAAgB,mBAAmB;IACxE,MAAM,6BAA6B,aAAa;IAChD,MAAM,yBAAyB,aAAa;IAI5C,MAAM,WAAW,0BAA0B;IAC3C,MAAM,cACJ,UAAU,mBACV,UAAU,kBACV,cAAc,OAAO,SAAS,UAAU,WAAW;IAGrD,MAAM,cADa,cAAc,IAAI,UAAU,WAAW,KACvB;AAInC,uBAAmB,IAAI,UAAU,MAAM;IAEvC,MAAM,qBAAqB,uBAAuB,CAAC;IACnD,MAAM,qBAAqB,wBAAwB,mBAAmB;IACtE,MAAM,iBAAiB,wBAAwB,EAC7C,qBAAqB,4BACtB,CAAC;AACF,QAAI,mBACF,gBAAe,IAAI,iCAAiC,mBAAmB;IAEzE,MAAM,SAAS,MAAM,oBAAoB,IAAI,WAAW,IAAI,QAAQ,eAAe;IACnF,MAAM,cAAc,mBAClB,QACA,4BACA,oBACA,eACD;AACD,QAAI,aAAa;AASf,SAAI,CAAC,4BAA4B,oBAAoB,MAAM,CAAE;KAC7D,MAAM,eAAe,YAAY;KAIjC,MAAM,2BAA2B,qCAC/B,aACA,aACD;KACD,MAAM,gBAAgB,yBACpB,gBACE,QAAQ,QAAQ,mBAAmB,YAAY,SAAS,CAAC,CAC1D,CACF;AACD,SAAI,CAAC,4BAA4B,oBAAoB,MAAM,CAAE;AAC7D,WAAM,wBACJ,eACA,0BACA,aACA,OACA,oBACA,cACA,wBACA,oBACA,aACA,aAAa,eAAe,EAC5B,gBAAgB,eAAe,CAChC;AACD;;IAMF,IAAI;IACJ,IAAI,iBAAgC;AACpC,QAAI,mBAAmB,WAAW;KAChC,MAAM,qBAAqB,wBACzB,QACA,4BACA,mBACD;AACD,SAAI,oBAAoB;AACtB,oBAAc,mBAAmB,oBAAoB,MAAM;AAC3D,uBAAiB,mBAAmB;;;AAIxC,QAAI,CAAC,YACH,eAAc,MAAM,MAAM,QAAQ;KAChC,SAAS;KACT,aAAa;KACd,CAAC;AAGJ,QAAI,CAAC,4BAA4B,oBAAoB,MAAM,CAAE;IAsB7D,MAAM,iBADiB,YAAY,QAAQ,IAAI,eAAe,IAAI,IAC7B,WAAW,mBAAmB;AACnE,QAAI,CAAC,YAAY,MAAM,CAAC,iBAAiB,CAAC,YAAY,MAAM;KAC1D,MAAM,cAAc,kBAAkB,YAAY;KAClD,IAAI,gBAAgB;AACpB,SAAI,aAAa;MACf,MAAM,SAAS,IAAI,IAAI,aAAa,OAAO,SAAS,OAAO;AAC3D,sCAAgC,OAAO;MACvC,MAAM,UAAU,IAAI,IAAI,aAAa,OAAO,SAAS,OAAO;MAC5D,IAAI,WAAW,eAAe,OAAO,SAAS;AAK9C,UACE,QAAQ,SAAS,SAAS,KAC1B,QAAQ,SAAS,SAAS,IAAI,IAC9B,CAAC,SAAS,SAAS,IAAI,CAEvB,aAAY;AAEd,sBAAgB,WAAW,OAAO;AAIlC,UAAI,QAAQ,KAAM,kBAAiB,QAAQ;;AAE7C,YAAO,SAAS,OAAO;AACvB;;IAGF,MAAM,WAAW,IAAI,IAAI,kBAAkB,YAAY,KAAK,OAAO,SAAS,OAAO;AACnF,oCAAgC,SAAS;IACzC,MAAM,eAAe,IAAI,IAAI,QAAQ,OAAO,SAAS,OAAO;AAE5D,QAAI,SAAS,aAAa,aAAa,UAAU;KAI/C,MAAM,kBAAkB,eAAe,SAAS,SAAS,GAAG,SAAS;AACrE,sCACE,sCAAsC,MAAM,uBAAuB,EACnE,IACA,gBACD;AAED,mBAAc;AAEd,0BAAqB,KAAA;AACrB,0BAAqB;AACrB,sBAAiB;AACjB;;IAIF,MAAM,YACJ,uBACE,YAAY,QAAQ,IAAI,kBAAkB,CAC3C,IAAI,EAAE;IAET,MAAM,qBAAqB,qCAAqC,aAAa,UAAU;IAEvF,MAAM,mBAAmB,MAAM,oBAAoB,YAAY;AAE/D,QAAI,CAAC,4BAA4B,oBAAoB,MAAM,CAAE;IAE7D,MAAM,aAAa,yBACjB,gBAAiC,QAAQ,QAAQ,mBAAmB,iBAAiB,CAAC,CAAC,CACxF;AAED,QAAI,CAAC,4BAA4B,oBAAoB,MAAM,CAAE;AAe7D,QAbsB,MAAM,wBAC1B,YACA,oBACA,aACA,OACA,oBACA,WACA,wBACA,oBACA,aACA,aAAa,eAAe,EAC5B,gBAAgB,eAAe,CAChC,KACqB,YAAa;AAGnC,QAAI,CAAC,4BAA4B,oBAAoB,MAAM,CAAE;IAK7D,MAAM,mBAAmB,MAAM;AAE/B,iCACE,QACA,0CACE,4BAJa,gBAAgB,aAAa,iBAAiB,CAKlD,oBACV,EACD,kBACA,UACD;AACD;;WAEK,OAAO;AAGd,OAAI,CAAC,4BAA4B,oBAAoB,MAAM,CAAE;AAK7D,OAAI,CAAC,gBACH,SAAQ,MAAM,kCAAkC,MAAM;AAExD,UAAO,SAAS,OAAO;YACf;AAIR,+BAA4B,mBAAmB,OAAO,mBAAmB;;;AAI7E,KAAI,uBAAuB,QACzB,SAAQ,oBAAoB;AAQ9B,QAAO,iBAAiB,aAAa,UAAU;AAC7C,iCAA+B,OAAO,SAAS,MAAM,WAAW;EAChE,MAAM,oBACJ,OAAO,0BAA0B,OAAO,SAAS,MAAM,GAAG,WAAW,IAAI,QAAQ,SAAS;AAC5F,SAAO,yBAAyB;AAC3B,oBAAkB,cAAc;AACnC,iCAA8B,MAAM,MAAM;AAC1C,OAAI,OAAO,2BAA2B,kBACpC,QAAO,yBAAyB;IAElC;GACF;AAEF,KAAI,OAAO,KAAK,IACd,QAAO,KAAK,IAAI,GAAG,cAAc,YAAY;AAC3C,MAAI;AAQF,OACE,sCACA,CAAC,4BAA4B,uBAAuB,EACpD;AACA,WAAO,SAAS,QAAQ;AACxB;;AAQF,SAAM,gCAAgC;AACtC,OAAI,CAAC,4BAA4B,uBAAuB,CACtD;AAEF,gCAA6B;GAC7B,MAAM,qBAAqB,qCACzB,OAAO,SAAS,MAChB,mBACD;AAMD,mBAAgB;GAIhB,MAAM,aAAa,yBAAyB;AAC5C,SAAM,4BAA4B,eAChC,yBACE,gBACE,MACE,MAAM,oBACJ,OAAO,SAAS,WAAW,OAAO,SAAS,QAC3C,WACD,EACD,EAAE,SAAS,YAAY,CACxB,CACF,CACF,EACD,mBACD;WACM,OAAO;AACd,WAAQ,MAAM,2BAA2B,MAAM;;GAEjD;;AAIN,IAAI,OAAO,aAAa,aAAa;AACnC,QAAO,iBAAiB,kBAAkB;AACxC,oBAAkB;GAClB;AAKF,QAAO,iBAAiB,kBAAkB;AACxC,oBAAkB;GAClB;AACG,OAAM"}
|