vinext 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/README.md +2 -5
  2. package/dist/build/client-build-config.d.ts +7 -1
  3. package/dist/build/client-build-config.js +9 -1
  4. package/dist/build/prerender.d.ts +9 -1
  5. package/dist/build/prerender.js +41 -12
  6. package/dist/build/run-prerender.d.ts +10 -2
  7. package/dist/build/run-prerender.js +15 -1
  8. package/dist/check.js +4 -3
  9. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  10. package/dist/client/app-nav-failure-handler.js +44 -0
  11. package/dist/client/navigation-runtime.d.ts +3 -2
  12. package/dist/client/vinext-next-data.d.ts +18 -1
  13. package/dist/client/window-next.d.ts +8 -5
  14. package/dist/client/window-next.js +12 -1
  15. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  16. package/dist/config/config-matchers.d.ts +11 -4
  17. package/dist/config/config-matchers.js +88 -16
  18. package/dist/config/next-config.d.ts +59 -4
  19. package/dist/config/next-config.js +149 -48
  20. package/dist/deploy.d.ts +30 -11
  21. package/dist/deploy.js +189 -101
  22. package/dist/entries/app-browser-entry.d.ts +9 -3
  23. package/dist/entries/app-browser-entry.js +21 -3
  24. package/dist/entries/app-rsc-entry.d.ts +2 -0
  25. package/dist/entries/app-rsc-entry.js +71 -6
  26. package/dist/entries/app-rsc-manifest.js +2 -0
  27. package/dist/entries/app-ssr-entry.js +1 -1
  28. package/dist/entries/pages-client-entry.js +54 -9
  29. package/dist/entries/pages-server-entry.js +48 -11
  30. package/dist/index.d.ts +0 -2
  31. package/dist/index.js +285 -139
  32. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  33. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  34. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  35. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  36. package/dist/plugins/og-assets.js +2 -2
  37. package/dist/plugins/optimize-imports.d.ts +10 -5
  38. package/dist/plugins/optimize-imports.js +27 -21
  39. package/dist/plugins/postcss.js +7 -7
  40. package/dist/plugins/sass.d.ts +53 -24
  41. package/dist/plugins/sass.js +249 -1
  42. package/dist/plugins/typeof-window.d.ts +14 -0
  43. package/dist/plugins/typeof-window.js +150 -0
  44. package/dist/plugins/wasm-module-import.d.ts +15 -0
  45. package/dist/plugins/wasm-module-import.js +50 -0
  46. package/dist/routing/app-route-graph.d.ts +25 -2
  47. package/dist/routing/app-route-graph.js +91 -22
  48. package/dist/routing/file-matcher.d.ts +10 -1
  49. package/dist/routing/file-matcher.js +23 -2
  50. package/dist/routing/pages-router.js +3 -3
  51. package/dist/routing/utils.d.ts +35 -6
  52. package/dist/routing/utils.js +59 -7
  53. package/dist/server/api-handler.d.ts +6 -1
  54. package/dist/server/api-handler.js +21 -15
  55. package/dist/server/app-browser-action-result.d.ts +19 -6
  56. package/dist/server/app-browser-action-result.js +19 -10
  57. package/dist/server/app-browser-entry.js +269 -297
  58. package/dist/server/app-browser-error.d.ts +10 -3
  59. package/dist/server/app-browser-error.js +47 -6
  60. package/dist/server/app-browser-history-controller.d.ts +104 -0
  61. package/dist/server/app-browser-history-controller.js +210 -0
  62. package/dist/server/app-browser-hydration.d.ts +2 -0
  63. package/dist/server/app-browser-hydration.js +1 -0
  64. package/dist/server/app-browser-navigation-controller.d.ts +7 -4
  65. package/dist/server/app-browser-navigation-controller.js +33 -9
  66. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  67. package/dist/server/app-browser-rsc-redirect.js +30 -8
  68. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  69. package/dist/server/app-browser-server-action-navigation.js +9 -0
  70. package/dist/server/app-browser-state.js +4 -7
  71. package/dist/server/app-browser-stream.js +86 -43
  72. package/dist/server/app-browser-visible-commit.js +1 -1
  73. package/dist/server/app-elements-wire.d.ts +6 -1
  74. package/dist/server/app-elements-wire.js +14 -4
  75. package/dist/server/app-elements.d.ts +2 -2
  76. package/dist/server/app-elements.js +2 -2
  77. package/dist/server/app-fallback-renderer.d.ts +3 -1
  78. package/dist/server/app-fallback-renderer.js +6 -2
  79. package/dist/server/app-middleware.js +1 -0
  80. package/dist/server/app-optimistic-routing.js +24 -3
  81. package/dist/server/app-page-boundary-render.d.ts +3 -1
  82. package/dist/server/app-page-boundary-render.js +31 -16
  83. package/dist/server/app-page-cache-render.d.ts +53 -0
  84. package/dist/server/app-page-cache-render.js +91 -0
  85. package/dist/server/app-page-cache.d.ts +16 -2
  86. package/dist/server/app-page-cache.js +71 -8
  87. package/dist/server/app-page-dispatch.d.ts +34 -0
  88. package/dist/server/app-page-dispatch.js +167 -97
  89. package/dist/server/app-page-element-builder.d.ts +23 -2
  90. package/dist/server/app-page-element-builder.js +42 -10
  91. package/dist/server/app-page-execution.d.ts +7 -2
  92. package/dist/server/app-page-execution.js +53 -18
  93. package/dist/server/app-page-probe.d.ts +1 -0
  94. package/dist/server/app-page-probe.js +4 -0
  95. package/dist/server/app-page-render-observation.d.ts +3 -1
  96. package/dist/server/app-page-render-observation.js +17 -1
  97. package/dist/server/app-page-render.d.ts +13 -2
  98. package/dist/server/app-page-render.js +48 -17
  99. package/dist/server/app-page-request.d.ts +3 -0
  100. package/dist/server/app-page-request.js +5 -3
  101. package/dist/server/app-page-response.js +1 -1
  102. package/dist/server/app-page-route-wiring.d.ts +5 -1
  103. package/dist/server/app-page-route-wiring.js +21 -11
  104. package/dist/server/app-page-stream.d.ts +16 -9
  105. package/dist/server/app-page-stream.js +12 -9
  106. package/dist/server/app-pages-bridge.d.ts +18 -0
  107. package/dist/server/app-pages-bridge.js +22 -5
  108. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  109. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  110. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  111. package/dist/server/app-ppr-fallback-shell.js +8 -1
  112. package/dist/server/app-route-handler-dispatch.js +9 -2
  113. package/dist/server/app-route-handler-policy.d.ts +1 -0
  114. package/dist/server/app-route-handler-response.js +11 -10
  115. package/dist/server/app-route-handler-runtime.js +12 -1
  116. package/dist/server/app-router-entry.js +5 -0
  117. package/dist/server/app-rsc-cache-busting.js +2 -0
  118. package/dist/server/app-rsc-handler.d.ts +25 -0
  119. package/dist/server/app-rsc-handler.js +153 -53
  120. package/dist/server/app-rsc-response-finalizer.js +1 -1
  121. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  122. package/dist/server/app-rsc-route-matching.js +2 -0
  123. package/dist/server/app-segment-config.d.ts +9 -1
  124. package/dist/server/app-segment-config.js +12 -3
  125. package/dist/server/app-server-action-execution.d.ts +12 -0
  126. package/dist/server/app-server-action-execution.js +47 -15
  127. package/dist/server/app-ssr-entry.d.ts +2 -0
  128. package/dist/server/app-ssr-entry.js +81 -8
  129. package/dist/server/app-ssr-stream.js +9 -1
  130. package/dist/server/cache-control.js +4 -0
  131. package/dist/server/dev-lockfile.js +2 -1
  132. package/dist/server/dev-server.d.ts +2 -2
  133. package/dist/server/dev-server.js +287 -63
  134. package/dist/server/headers.d.ts +8 -1
  135. package/dist/server/headers.js +8 -1
  136. package/dist/server/hybrid-route-priority.d.ts +22 -0
  137. package/dist/server/hybrid-route-priority.js +33 -0
  138. package/dist/server/image-optimization.d.ts +18 -9
  139. package/dist/server/image-optimization.js +37 -23
  140. package/dist/server/implicit-tags.d.ts +2 -1
  141. package/dist/server/implicit-tags.js +4 -1
  142. package/dist/server/instrumentation-runtime.d.ts +6 -0
  143. package/dist/server/instrumentation-runtime.js +8 -0
  144. package/dist/server/isr-decision.d.ts +79 -0
  145. package/dist/server/isr-decision.js +70 -0
  146. package/dist/server/metadata-route-response.js +5 -3
  147. package/dist/server/middleware-runtime.d.ts +13 -0
  148. package/dist/server/middleware-runtime.js +11 -7
  149. package/dist/server/middleware.js +1 -0
  150. package/dist/server/navigation-planner.d.ts +186 -22
  151. package/dist/server/navigation-planner.js +302 -0
  152. package/dist/server/navigation-trace.d.ts +18 -1
  153. package/dist/server/navigation-trace.js +18 -1
  154. package/dist/server/normalize-path.d.ts +0 -8
  155. package/dist/server/normalize-path.js +3 -1
  156. package/dist/server/otel-tracer-extension.d.ts +45 -0
  157. package/dist/server/otel-tracer-extension.js +89 -0
  158. package/dist/server/pages-api-route.d.ts +20 -3
  159. package/dist/server/pages-api-route.js +19 -3
  160. package/dist/server/pages-asset-tags.d.ts +16 -4
  161. package/dist/server/pages-asset-tags.js +22 -12
  162. package/dist/server/pages-data-route.d.ts +8 -1
  163. package/dist/server/pages-data-route.js +16 -3
  164. package/dist/server/pages-get-initial-props.d.ts +54 -4
  165. package/dist/server/pages-get-initial-props.js +43 -1
  166. package/dist/server/pages-node-compat.d.ts +3 -11
  167. package/dist/server/pages-node-compat.js +175 -122
  168. package/dist/server/pages-page-data.d.ts +39 -2
  169. package/dist/server/pages-page-data.js +261 -46
  170. package/dist/server/pages-page-handler.d.ts +5 -2
  171. package/dist/server/pages-page-handler.js +78 -25
  172. package/dist/server/pages-page-response.d.ts +47 -2
  173. package/dist/server/pages-page-response.js +73 -9
  174. package/dist/server/pages-readiness.d.ts +1 -1
  175. package/dist/server/pages-request-pipeline.d.ts +16 -1
  176. package/dist/server/pages-request-pipeline.js +96 -38
  177. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  178. package/dist/server/pregenerated-concrete-paths.js +2 -19
  179. package/dist/server/prerender-manifest.d.ts +33 -0
  180. package/dist/server/prerender-manifest.js +54 -0
  181. package/dist/server/prerender-route-params.d.ts +1 -2
  182. package/dist/server/prod-server.d.ts +39 -1
  183. package/dist/server/prod-server.js +107 -37
  184. package/dist/server/request-pipeline.d.ts +3 -15
  185. package/dist/server/request-pipeline.js +58 -47
  186. package/dist/server/rsc-stream-hints.d.ts +5 -1
  187. package/dist/server/rsc-stream-hints.js +6 -1
  188. package/dist/server/seed-cache.js +10 -18
  189. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  190. package/dist/shims/app-router-scroll-state.js +14 -2
  191. package/dist/shims/app-router-scroll.d.ts +3 -0
  192. package/dist/shims/app-router-scroll.js +28 -18
  193. package/dist/shims/cache-runtime.js +12 -4
  194. package/dist/shims/cache.d.ts +1 -0
  195. package/dist/shims/cache.js +1 -1
  196. package/dist/shims/cdn-cache.d.ts +5 -5
  197. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  198. package/dist/shims/dynamic-preload-chunks.js +79 -0
  199. package/dist/shims/dynamic.d.ts +4 -0
  200. package/dist/shims/dynamic.js +4 -2
  201. package/dist/shims/error-boundary.d.ts +6 -4
  202. package/dist/shims/error-boundary.js +7 -0
  203. package/dist/shims/error.js +38 -11
  204. package/dist/shims/error.react-server.d.ts +9 -0
  205. package/dist/shims/error.react-server.js +6 -0
  206. package/dist/shims/fetch-cache.d.ts +11 -1
  207. package/dist/shims/fetch-cache.js +55 -20
  208. package/dist/shims/hash-scroll.js +6 -1
  209. package/dist/shims/head.js +6 -1
  210. package/dist/shims/headers.d.ts +16 -2
  211. package/dist/shims/headers.js +66 -5
  212. package/dist/shims/image-config.js +7 -1
  213. package/dist/shims/internal/als-registry.js +28 -1
  214. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  215. package/dist/shims/internal/app-route-detection.js +18 -23
  216. package/dist/shims/internal/app-router-context.d.ts +5 -0
  217. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  218. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  219. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  220. package/dist/shims/internal/navigation-untracked.js +55 -0
  221. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  222. package/dist/shims/internal/pages-data-target.js +17 -8
  223. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  224. package/dist/shims/internal/pages-router-accessor.js +13 -0
  225. package/dist/shims/internal/router-context.d.ts +2 -1
  226. package/dist/shims/internal/router-context.js +3 -1
  227. package/dist/shims/link.js +12 -5
  228. package/dist/shims/metadata.d.ts +6 -2
  229. package/dist/shims/metadata.js +32 -14
  230. package/dist/shims/navigation.d.ts +14 -17
  231. package/dist/shims/navigation.js +93 -46
  232. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  233. package/dist/shims/ppr-fallback-shell.js +28 -7
  234. package/dist/shims/router.d.ts +13 -2
  235. package/dist/shims/router.js +434 -116
  236. package/dist/shims/script-nonce-context.d.ts +1 -1
  237. package/dist/shims/script-nonce-context.js +11 -3
  238. package/dist/shims/server.d.ts +33 -2
  239. package/dist/shims/server.js +75 -18
  240. package/dist/shims/slot.js +1 -1
  241. package/dist/shims/unified-request-context.js +2 -0
  242. package/dist/typegen.js +1 -0
  243. package/dist/utils/built-asset-url.d.ts +4 -0
  244. package/dist/utils/built-asset-url.js +11 -0
  245. package/dist/utils/client-build-manifest.js +15 -5
  246. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  247. package/dist/utils/client-runtime-metadata.js +63 -0
  248. package/dist/utils/commonjs-loader.d.ts +16 -0
  249. package/dist/utils/commonjs-loader.js +100 -0
  250. package/dist/utils/deployment-id.d.ts +8 -0
  251. package/dist/utils/deployment-id.js +22 -0
  252. package/dist/utils/hash.d.ts +17 -1
  253. package/dist/utils/hash.js +36 -1
  254. package/dist/utils/html-limited-bots.d.ts +18 -1
  255. package/dist/utils/html-limited-bots.js +23 -1
  256. package/dist/utils/lazy-chunks.d.ts +27 -1
  257. package/dist/utils/lazy-chunks.js +65 -1
  258. package/dist/utils/manifest-paths.d.ts +20 -2
  259. package/dist/utils/manifest-paths.js +38 -3
  260. package/dist/utils/parse-cookie.d.ts +13 -0
  261. package/dist/utils/parse-cookie.js +52 -0
  262. package/dist/utils/path.d.ts +8 -1
  263. package/dist/utils/path.js +13 -1
  264. package/package.json +2 -2
  265. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  266. package/dist/shims/internal/parse-cookie-header.js +0 -30
@@ -1,5 +1,5 @@
1
1
  import { splitPathSegments } from "../routing/utils.js";
2
- import { stripBasePath } from "../utils/base-path.js";
2
+ import { removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
3
3
  import { assertSafeNavigationUrl } from "./url-safety.js";
4
4
  import { matchRoutePattern, routePatternParts } from "../routing/route-pattern.js";
5
5
  import { isUnknownRecord } from "../utils/record.js";
@@ -9,16 +9,18 @@ import { applyVinextLocaleGlobals, extractVinextNextDataJson, parseVinextNextDat
9
9
  import { isValidModulePath } from "../client/validate-module-path.js";
10
10
  import { addLocalePrefix, getDomainLocaleUrl, getLocalePathPrefix } from "../utils/domain-locale.js";
11
11
  import { buildPagesDataHref } from "./internal/pages-data-url.js";
12
+ import { dedupedPagesDataFetch } from "./internal/pages-data-fetch-dedup.js";
13
+ import { NEXT_DEPLOYMENT_ID_HEADER, getDeploymentId } from "../utils/deployment-id.js";
12
14
  import { prefetchPagesData, resolvePagesDataNavigationTarget } from "./internal/pages-data-target.js";
15
+ import { addQueryParam, appendSearchParamsToUrl, mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
16
+ import { resolveHybridClientRouteOwner } from "./internal/hybrid-client-route-owner.js";
13
17
  import { getPagesRouterComponentsMap, markAppRouteDetectedOnPrefetch } from "./internal/app-route-detection.js";
14
- import { dedupedPagesDataFetch } from "./internal/pages-data-fetch-dedup.js";
15
18
  import { installWindowNext } from "../client/window-next.js";
16
19
  import { getWindowOrigin, isAbsoluteOrProtocolRelativeUrl, isHashOnlyBrowserUrlChange, normalizePathTrailingSlash, toBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
17
- import { addQueryParam, appendSearchParamsToUrl, mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
18
20
  import { scrollToHashTarget } from "./hash-scroll.js";
19
- import { setPagesRouterPopStateHandler, setStampInitialHistoryState } from "./pages-router-runtime.js";
21
+ import { installPagesRouterRuntime, setPagesRouterPopStateHandler, setStampInitialHistoryState } from "./pages-router-runtime.js";
20
22
  import { getCurrentBrowserLocale } from "./client-locale.js";
21
- import { createElement, useContext, useEffect, useMemo, useState } from "react";
23
+ import { Component, Fragment, createElement, useContext, useEffect, useLayoutEffect, useMemo, useState } from "react";
22
24
  //#region src/shims/router.ts
23
25
  /**
24
26
  * next/router shim
@@ -31,6 +33,134 @@ import { createElement, useContext, useEffect, useMemo, useState } from "react";
31
33
  const __basePath = process.env.__NEXT_ROUTER_BASEPATH ?? "";
32
34
  /** trailingSlash from next.config.js, injected by the plugin at build time */
33
35
  const __trailingSlash = process.env.__VINEXT_TRAILING_SLASH === "true";
36
+ /** experimental.scrollRestoration from next.config.js, injected by the plugin at build time */
37
+ const __scrollRestoration = process.env.__NEXT_SCROLL_RESTORATION === "true";
38
+ const noopCommit = () => {};
39
+ const SCROLL_RESTORE_MAX_FRAMES = 60;
40
+ const SCROLL_RESTORE_TOLERANCE_PX = 1;
41
+ /**
42
+ * A version of useLayoutEffect that doesn't warn during SSR.
43
+ * `wrapWithRouterContext` is shared with the server-side Pages Router render
44
+ * path, where a raw useLayoutEffect would log React's "useLayoutEffect does
45
+ * nothing on the server" warning on every render. Same pattern as
46
+ * `shims/image.tsx`; Next.js only runs the commit callback on the client.
47
+ */
48
+ const useNonWarningLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
49
+ var PagesRouterCommitBoundary = class extends Component {
50
+ componentDidCatch(error) {
51
+ this.props.onError(error);
52
+ }
53
+ render() {
54
+ return createElement(PagesRouterCommitBoundaryHelper, { onCommit: this.props.onCommit }, this.props.children);
55
+ }
56
+ };
57
+ function PagesRouterCommitBoundaryHelper({ children, onCommit }) {
58
+ useNonWarningLayoutEffect(() => {
59
+ onCommit();
60
+ }, [onCommit]);
61
+ return createElement(Fragment, null, children);
62
+ }
63
+ function renderPagesRouterElement(element, scroll) {
64
+ const root = window.__VINEXT_ROOT__;
65
+ if (!root) return Promise.resolve();
66
+ cancelPreviousRenderCommit();
67
+ return new Promise((resolve, reject) => {
68
+ const cancel = () => {
69
+ if (routerRuntimeState.cancelPendingRenderCommit === cancel) routerRuntimeState.cancelPendingRenderCommit = null;
70
+ reject(new NavigationCancelledError("superseded"));
71
+ };
72
+ routerRuntimeState.cancelPendingRenderCommit = cancel;
73
+ const clearIfCurrent = () => {
74
+ if (routerRuntimeState.cancelPendingRenderCommit === cancel) routerRuntimeState.cancelPendingRenderCommit = null;
75
+ };
76
+ const isCurrent = () => routerRuntimeState.cancelPendingRenderCommit === cancel;
77
+ const scrollHandler = async () => {
78
+ if (scroll) await restorePagesRouterScrollPosition(scroll, isCurrent);
79
+ };
80
+ root.render(wrapWithRouterContext(element, () => {
81
+ (async () => {
82
+ if (!isCurrent()) return;
83
+ try {
84
+ await scrollHandler();
85
+ if (!isCurrent()) return;
86
+ clearIfCurrent();
87
+ resolve();
88
+ } catch (err) {
89
+ clearIfCurrent();
90
+ reject(err);
91
+ }
92
+ })();
93
+ }, (error) => {
94
+ clearIfCurrent();
95
+ reject(error);
96
+ }));
97
+ if (!hasBrowserDocument()) {
98
+ clearIfCurrent();
99
+ resolve();
100
+ }
101
+ });
102
+ }
103
+ function hasBrowserDocument() {
104
+ return typeof document !== "undefined" && document.documentElement !== void 0;
105
+ }
106
+ async function restorePagesRouterScrollPosition(scroll, shouldContinue) {
107
+ if (!shouldContinue()) return;
108
+ scrollToPagesRouterPosition(scroll);
109
+ if (isAtScrollPosition(scroll)) return;
110
+ let previousScrollPosition = getWindowScrollPosition();
111
+ for (let frame = 0; frame < SCROLL_RESTORE_MAX_FRAMES; frame += 1) {
112
+ await waitForNextAnimationFrame();
113
+ if (!shouldContinue()) return;
114
+ scrollToPagesRouterPosition(scroll);
115
+ if (isAtScrollPosition(scroll)) return;
116
+ const currentScrollPosition = getWindowScrollPosition();
117
+ if (currentScrollPosition.x === previousScrollPosition.x && currentScrollPosition.y === previousScrollPosition.y) break;
118
+ previousScrollPosition = currentScrollPosition;
119
+ }
120
+ }
121
+ function scrollToPagesRouterPosition({ x, y }) {
122
+ if (!hasBrowserDocument()) {
123
+ window.scrollTo(x, y);
124
+ return;
125
+ }
126
+ const htmlElement = document.documentElement;
127
+ if (!(htmlElement.dataset.scrollBehavior === "smooth")) {
128
+ window.scrollTo(x, y);
129
+ return;
130
+ }
131
+ const previousScrollBehavior = htmlElement.style.scrollBehavior;
132
+ htmlElement.style.scrollBehavior = "auto";
133
+ htmlElement.getClientRects();
134
+ window.scrollTo(x, y);
135
+ htmlElement.style.scrollBehavior = previousScrollBehavior;
136
+ }
137
+ function isAtScrollPosition({ x, y }) {
138
+ return Math.abs(window.scrollX - x) <= SCROLL_RESTORE_TOLERANCE_PX && Math.abs(window.scrollY - y) <= SCROLL_RESTORE_TOLERANCE_PX;
139
+ }
140
+ function waitForNextAnimationFrame() {
141
+ return new Promise((resolve) => {
142
+ if (typeof requestAnimationFrame === "function") {
143
+ requestAnimationFrame(() => resolve());
144
+ return;
145
+ }
146
+ setTimeout(resolve, 16);
147
+ });
148
+ }
149
+ function canUseSessionStorageForScrollRestoration() {
150
+ if (typeof window === "undefined") return false;
151
+ try {
152
+ const key = "__next";
153
+ window.sessionStorage.setItem(key, key);
154
+ window.sessionStorage.removeItem(key);
155
+ return true;
156
+ } catch {
157
+ return false;
158
+ }
159
+ }
160
+ const manualScrollRestoration = __scrollRestoration && typeof window !== "undefined" && window.next?.appDir !== true && "scrollRestoration" in window.history && canUseSessionStorageForScrollRestoration();
161
+ function installManualScrollRestoration() {
162
+ if (manualScrollRestoration) window.history.scrollRestoration = "manual";
163
+ }
34
164
  function createRouterEvents() {
35
165
  const listeners = /* @__PURE__ */ new Map();
36
166
  return {
@@ -46,7 +176,42 @@ function createRouterEvents() {
46
176
  }
47
177
  };
48
178
  }
49
- const routerEvents = createRouterEvents();
179
+ const PAGES_ROUTER_RUNTIME_STATE_KEY = Symbol.for("vinext.pagesRouter.runtimeState");
180
+ function createPagesRouterRuntimeState() {
181
+ return {
182
+ events: createRouterEvents(),
183
+ historyKeyCounter: 0,
184
+ navigationId: 0,
185
+ activeAbortController: null,
186
+ cancelPendingRenderCommit: null,
187
+ lastPathnameAndSearch: typeof window !== "undefined" ? window.location.pathname + window.location.search : "",
188
+ isFirstPopStateEvent: true,
189
+ routerDidNavigate: false,
190
+ deprecatedEventBridgeInstalled: false,
191
+ pagesRouterReady: typeof window === "undefined" || !shouldDeferInitialPagesRouterReady()
192
+ };
193
+ }
194
+ function getPagesRouterRuntimeState() {
195
+ if (typeof window === "undefined") return createPagesRouterRuntimeState();
196
+ const globalObject = window;
197
+ const existing = globalObject[PAGES_ROUTER_RUNTIME_STATE_KEY];
198
+ if (existing) return existing;
199
+ const state = createPagesRouterRuntimeState();
200
+ globalObject[PAGES_ROUTER_RUNTIME_STATE_KEY] = state;
201
+ return state;
202
+ }
203
+ const routerRuntimeState = getPagesRouterRuntimeState();
204
+ const routerEvents = routerRuntimeState.events;
205
+ function getPagesRouterRuntimeComponents() {
206
+ const existing = routerRuntimeState.components;
207
+ if (existing) return existing;
208
+ const components = {
209
+ CommitBoundary: PagesRouterCommitBoundary,
210
+ Provider: PagesRouterProvider
211
+ };
212
+ routerRuntimeState.components = components;
213
+ return components;
214
+ }
50
215
  function resolveUrl(url) {
51
216
  if (typeof url === "string") return url;
52
217
  let result = url.pathname ?? "/";
@@ -201,8 +366,16 @@ function buildInitialRouterState() {
201
366
  * locale stamped before any push could overwrite the active locale global.
202
367
  */
203
368
  function stampInitialHistoryState() {
204
- if (window.history.state !== null && window.history.state !== void 0) return;
205
- window.history.replaceState(buildInitialRouterState(), "");
369
+ installManualScrollRestoration();
370
+ if (!window.history) return;
371
+ const existingState = window.history.state;
372
+ if (existingState !== null && existingState !== void 0) {
373
+ routerRuntimeState.currentHistoryKey = getRouterStateKey(existingState) ?? routerRuntimeState.currentHistoryKey;
374
+ return;
375
+ }
376
+ const initialState = buildInitialRouterState();
377
+ routerRuntimeState.currentHistoryKey = initialState.key;
378
+ window.history.replaceState(initialState, "");
206
379
  }
207
380
  setStampInitialHistoryState(stampInitialHistoryState);
208
381
  /** Save current scroll position into history state for back/forward restoration.
@@ -213,22 +386,62 @@ setStampInitialHistoryState(stampInitialHistoryState);
213
386
  * minting the same shape here so the entry isn't treated as foreign.
214
387
  */
215
388
  function saveScrollPosition() {
216
- const existing = typeof window.history.state === "object" && window.history.state !== null ? window.history.state : null;
389
+ const position = getWindowScrollPosition();
390
+ const existing = isUnknownRecord(window.history.state) ? window.history.state : null;
217
391
  const scroll = {
218
- __vinext_scrollX: window.scrollX,
219
- __vinext_scrollY: window.scrollY
392
+ __vinext_scrollX: position.x,
393
+ __vinext_scrollY: position.y
220
394
  };
221
395
  const base = existing ?? buildInitialRouterState();
396
+ const key = getRouterStateKey(base);
397
+ if (key !== void 0) {
398
+ routerRuntimeState.currentHistoryKey = key;
399
+ saveScrollPositionToSessionStorage(key, position);
400
+ }
222
401
  window.history.replaceState({
223
402
  ...base,
224
403
  ...scroll
225
404
  }, "");
226
405
  }
227
- /** Restore scroll position from history state */
228
- function restoreScrollPosition(state) {
229
- if (state && typeof state === "object" && "__vinext_scrollY" in state) {
230
- const { __vinext_scrollX: x, __vinext_scrollY: y } = state;
231
- requestAnimationFrame(() => window.scrollTo(x, y));
406
+ function getWindowScrollPosition() {
407
+ return {
408
+ x: window.scrollX,
409
+ y: window.scrollY
410
+ };
411
+ }
412
+ function getScrollStorageKey(historyKey) {
413
+ return `__next_scroll_${historyKey}`;
414
+ }
415
+ function readScrollPosition(value) {
416
+ if (!isUnknownRecord(value)) return null;
417
+ const nextX = value.x;
418
+ const nextY = value.y;
419
+ if (typeof nextX === "number" && typeof nextY === "number") return {
420
+ x: nextX,
421
+ y: nextY
422
+ };
423
+ const vinextX = value.__vinext_scrollX;
424
+ const vinextY = value.__vinext_scrollY;
425
+ if (typeof vinextX === "number" && typeof vinextY === "number") return {
426
+ x: vinextX,
427
+ y: vinextY
428
+ };
429
+ return null;
430
+ }
431
+ function saveScrollPositionToSessionStorage(key, position) {
432
+ if (!manualScrollRestoration) return;
433
+ try {
434
+ window.sessionStorage.setItem(getScrollStorageKey(key), JSON.stringify(position));
435
+ } catch {}
436
+ }
437
+ function readScrollPositionFromSessionStorage(key) {
438
+ if (!manualScrollRestoration) return null;
439
+ try {
440
+ const value = window.sessionStorage.getItem(getScrollStorageKey(key));
441
+ if (value === null) return null;
442
+ return readScrollPosition(JSON.parse(value));
443
+ } catch {
444
+ return null;
232
445
  }
233
446
  }
234
447
  let _ssrContext = null;
@@ -380,6 +593,11 @@ function getRouteParamsFromQuery(pattern, query) {
380
593
  function getRouteQueryFromNextData(nextData, resolvedPath) {
381
594
  const routeQuery = {};
382
595
  if (!nextData?.query || !nextData.page) return routeQuery;
596
+ if (extractRouteParamsFromPath(nextData.page, resolvedPath) === null) {
597
+ for (const [key, value] of Object.entries(nextData.query)) if (typeof value === "string") routeQuery[key] = value;
598
+ else if (Array.isArray(value)) routeQuery[key] = [...value];
599
+ return routeQuery;
600
+ }
383
601
  const routeParamNames = extractRouteParamNames(nextData.page);
384
602
  if (routeParamNames.length === 0) return routeQuery;
385
603
  const currentRouteParams = extractRouteParamsFromPath(nextData.page, resolvedPath);
@@ -439,9 +657,8 @@ function shouldDeferInitialPagesRouterReady() {
439
657
  if (!nextData) return false;
440
658
  return !getPagesNavigationIsReadyFromSerializedState(nextData.page, window.location.search, nextData);
441
659
  }
442
- let _pagesRouterReady = typeof window === "undefined" ? true : !shouldDeferInitialPagesRouterReady();
443
660
  function isPagesRouterReady() {
444
- return _pagesRouterReady;
661
+ return routerRuntimeState.pagesRouterReady;
445
662
  }
446
663
  function isPagesRouterDocumentActive() {
447
664
  if (typeof window === "undefined") return true;
@@ -451,10 +668,24 @@ function isPagesRouterDocumentActive() {
451
668
  return Boolean(window.__VINEXT_APP__ || window.__VINEXT_APP_LOADER__);
452
669
  }
453
670
  function markPagesRouterReady() {
454
- if (typeof window === "undefined" || _pagesRouterReady) return false;
455
- _pagesRouterReady = true;
671
+ if (typeof window === "undefined" || routerRuntimeState.pagesRouterReady) return false;
672
+ routerRuntimeState.pagesRouterReady = true;
456
673
  return true;
457
674
  }
675
+ function markPagesRouterHydrated() {
676
+ if (typeof window === "undefined" || window.__NEXT_HYDRATED === true) return;
677
+ const hydratedAt = performance.now();
678
+ window.__VINEXT_HYDRATED_AT = hydratedAt;
679
+ window.__NEXT_HYDRATED = true;
680
+ window.__NEXT_HYDRATED_AT = hydratedAt;
681
+ window.__NEXT_HYDRATED_CB?.();
682
+ }
683
+ function PagesRouterHydrationMarker() {
684
+ useEffect(() => {
685
+ markPagesRouterHydrated();
686
+ }, []);
687
+ return null;
688
+ }
458
689
  function getRouterSnapshot() {
459
690
  const isReady = typeof window === "undefined" ? _getSSRContext()?.navigationIsReady ?? true : isPagesRouterReady();
460
691
  return {
@@ -488,20 +719,10 @@ var HardNavigationScheduledError = class extends Error {
488
719
  this.name = "HardNavigationScheduledError";
489
720
  }
490
721
  };
491
- /**
492
- * Monotonically increasing ID for tracking the current navigation.
493
- * Each call to navigateClient() increments this and captures the value.
494
- * After each async boundary, the navigation checks whether it is still
495
- * the active one. If a newer navigation has started, the stale one
496
- * throws NavigationCancelledError so the caller can emit routeChangeError
497
- * and skip routeChangeComplete.
498
- *
499
- * Replaces the old boolean `_navInProgress` guard which silently dropped
500
- * the second navigation, causing URL/content mismatch.
501
- */
502
- let _navigationId = 0;
503
- /** AbortController for the in-flight fetch, so superseded navigations abort network I/O. */
504
- let _activeAbortController = null;
722
+ function cancelPreviousRenderCommit() {
723
+ routerRuntimeState.cancelPendingRenderCommit?.();
724
+ routerRuntimeState.cancelPendingRenderCommit = null;
725
+ }
505
726
  function scheduleHardNavigationAndThrow(url, message) {
506
727
  if (typeof window === "undefined") throw new HardNavigationScheduledError(message);
507
728
  window.location.href = url;
@@ -566,15 +787,20 @@ function getMiddlewarePagesDataFetchUrl(browserUrl) {
566
787
  if (parsed.origin !== getWindowOrigin()) return null;
567
788
  return buildPagesDataHref(__basePath, buildId, stripBasePath(parsed.pathname, __basePath), parsed.search);
568
789
  }
569
- async function resolveMiddlewareDataRedirect(browserUrl, signal) {
790
+ async function resolveMiddlewareDataEffect(browserUrl, signal) {
570
791
  const dataUrl = getMiddlewarePagesDataFetchUrl(browserUrl);
571
792
  if (!dataUrl) return null;
572
793
  if (signal.aborted) throw new DOMException("Aborted", "AbortError");
573
794
  try {
574
- return (await dedupedPagesDataFetch(dataUrl, { headers: {
795
+ const res = await dedupedPagesDataFetch(dataUrl, { headers: {
575
796
  Accept: "application/json",
576
797
  "x-nextjs-data": "1"
577
- } })).headers.get("x-nextjs-redirect");
798
+ } });
799
+ return {
800
+ redirectLocation: res.headers.get("x-nextjs-redirect"),
801
+ rewriteTarget: res.headers.get("x-nextjs-rewrite"),
802
+ response: res
803
+ };
578
804
  } catch {
579
805
  return null;
580
806
  }
@@ -611,19 +837,21 @@ function handleDataRedirect(destination, redirectBasePath, mode = "push") {
611
837
  * data endpoint returns 404 and the client lands on the new build via a
612
838
  * full document load.
613
839
  */
614
- async function navigateClientData(url, target, controller, navId, assertStillCurrent, options = {}) {
615
- const root = window.__VINEXT_ROOT__;
616
- if (!root) {
840
+ async function navigateClientData(url, initialTarget, controller, navId, assertStillCurrent, options = {}, prefetchedResponse) {
841
+ if (!window.__VINEXT_ROOT__) {
617
842
  window.location.href = url;
618
843
  return;
619
844
  }
620
845
  if (controller.signal.aborted) throw new NavigationCancelledError(url);
621
- let res;
622
- try {
623
- res = await dedupedPagesDataFetch(target.dataHref, { headers: {
846
+ let res = prefetchedResponse;
847
+ if (!res) try {
848
+ const headers = {
624
849
  Accept: "application/json",
625
850
  "x-nextjs-data": "1"
626
- } });
851
+ };
852
+ const deploymentId = getDeploymentId();
853
+ if (deploymentId) headers[NEXT_DEPLOYMENT_ID_HEADER] = deploymentId;
854
+ res = await dedupedPagesDataFetch(initialTarget.dataHref, { headers });
627
855
  } catch (err) {
628
856
  if (err instanceof DOMException && err.name === "AbortError") throw new NavigationCancelledError(url);
629
857
  throw err;
@@ -634,11 +862,14 @@ async function navigateClientData(url, target, controller, navId, assertStillCur
634
862
  const redirectedUrl = resolveLocalRedirectUrl(softRedirect);
635
863
  if (!redirectedUrl) scheduleHardNavigationAndThrow(softRedirect, "Navigation redirected externally");
636
864
  window.history.replaceState(window.history.state ?? {}, "", redirectedUrl);
637
- _lastPathnameAndSearch = window.location.pathname + window.location.search;
865
+ routerRuntimeState.lastPathnameAndSearch = window.location.pathname + window.location.search;
638
866
  await navigateClientHtml(redirectedUrl, redirectedUrl, controller, navId, assertStillCurrent);
639
867
  return;
640
868
  }
641
869
  if (!res.ok) scheduleHardNavigationAndThrow(url, `Data navigation failed: ${res.status} ${res.statusText}`);
870
+ const rewriteTarget = res.headers.get("x-nextjs-rewrite");
871
+ const target = rewriteTarget ? resolvePagesDataNavigationTarget(rewriteTarget, __basePath) : initialTarget;
872
+ if (!target) scheduleHardNavigationAndThrow(url, "Data navigation failed: rewrite target has no page loader");
642
873
  let body;
643
874
  try {
644
875
  body = await res.json();
@@ -646,7 +877,9 @@ async function navigateClientData(url, target, controller, navId, assertStillCur
646
877
  scheduleHardNavigationAndThrow(url, "Data navigation failed: invalid JSON response");
647
878
  }
648
879
  assertStillCurrent();
649
- const pageProps = body.pageProps && typeof body.pageProps === "object" ? body.pageProps : {};
880
+ const props = isUnknownRecord(body) ? body : {};
881
+ const rawPageProps = props.pageProps;
882
+ const pageProps = isUnknownRecord(rawPageProps) ? rawPageProps : {};
650
883
  const redirectDestination = pageProps.__N_REDIRECT;
651
884
  if (typeof redirectDestination === "string") {
652
885
  handleDataRedirect(redirectDestination, pageProps.__N_REDIRECT_BASE_PATH, options.mode);
@@ -673,17 +906,18 @@ async function navigateClientData(url, target, controller, navId, assertStillCur
673
906
  assertStillCurrent();
674
907
  let element;
675
908
  if (AppComponent) element = React.createElement(AppComponent, {
909
+ ...props,
676
910
  Component: PageComponent,
677
- pageProps
911
+ pageProps: rawPageProps,
912
+ router: Router
678
913
  });
679
914
  else element = React.createElement(PageComponent, pageProps);
680
- element = wrapWithRouterContext(element);
681
915
  const mergedQuery = mergeRouteParamsIntoQuery(parseQueryString(target.search), target.params);
682
916
  const prev = window.__NEXT_DATA__;
683
917
  const nextLocale = (window.__VINEXT_LOCALES__?.length ?? 0) > 0 ? target.locale ?? window.__VINEXT_DEFAULT_LOCALE__ : prev?.locale;
684
918
  const nextData = {
685
919
  ...prev,
686
- props: { pageProps },
920
+ props,
687
921
  page: target.pattern,
688
922
  query: mergedQuery,
689
923
  buildId: target.buildId,
@@ -692,7 +926,8 @@ async function navigateClientData(url, target, controller, navId, assertStillCur
692
926
  };
693
927
  window.__NEXT_DATA__ = nextData;
694
928
  applyVinextLocaleGlobals(window, nextData);
695
- root.render(element);
929
+ await renderPagesRouterElement(element, options.scroll);
930
+ assertStillCurrent();
696
931
  }
697
932
  /**
698
933
  * Perform client-side navigation by fetching the page's full HTML and
@@ -707,8 +942,7 @@ async function navigateClientData(url, target, controller, navId, assertStillCur
707
942
  async function navigateClientHtml(url, fetchUrl, controller, navId, assertStillCurrent, options = {}) {
708
943
  let browserUrl = url;
709
944
  let pendingRedirectHistoryUrl = fetchUrl === url ? null : url;
710
- const root = window.__VINEXT_ROOT__;
711
- if (!root) {
945
+ if (!window.__VINEXT_ROOT__) {
712
946
  window.location.href = browserUrl;
713
947
  return;
714
948
  }
@@ -736,7 +970,9 @@ async function navigateClientHtml(url, fetchUrl, controller, navId, assertStillC
736
970
  const nextDataJson = extractVinextNextDataJson(html);
737
971
  if (!nextDataJson) scheduleHardNavigationAndThrow(url, "Navigation failed: missing __NEXT_DATA__ in response");
738
972
  const nextData = parseVinextNextDataJson(nextDataJson);
739
- const { pageProps } = nextData.props;
973
+ const props = nextData.props && typeof nextData.props === "object" ? nextData.props : {};
974
+ const rawPageProps = props.pageProps;
975
+ const pageProps = isUnknownRecord(rawPageProps) ? rawPageProps : {};
740
976
  let pageModuleUrl = nextData.__vinext?.pageModuleUrl;
741
977
  if (!pageModuleUrl) {
742
978
  const moduleMatch = html.match(/import\("([^"]+)"\);\s*\n\s*const PageComponent/);
@@ -744,11 +980,10 @@ async function navigateClientHtml(url, fetchUrl, controller, navId, assertStillC
744
980
  pageModuleUrl = moduleMatch?.[1] ?? altMatch?.[1] ?? void 0;
745
981
  }
746
982
  let pageModule;
747
- if (!pageModuleUrl) {
748
- const loader = window.__VINEXT_PAGE_LOADERS__?.[nextData.page];
749
- if (!loader) scheduleHardNavigationAndThrow(browserUrl, "Navigation failed: no page module URL found");
750
- pageModule = await loader();
751
- } else {
983
+ const loader = window.__VINEXT_PAGE_LOADERS__?.[nextData.page];
984
+ if (loader) pageModule = await loader();
985
+ else if (!pageModuleUrl) scheduleHardNavigationAndThrow(browserUrl, "Navigation failed: no page module URL found");
986
+ else {
752
987
  if (!isValidModulePath(pageModuleUrl)) {
753
988
  console.error("[vinext] Blocked import of invalid page module path:", pageModuleUrl);
754
989
  scheduleHardNavigationAndThrow(browserUrl, "Navigation failed: invalid page module path");
@@ -777,18 +1012,20 @@ async function navigateClientHtml(url, fetchUrl, controller, navId, assertStillC
777
1012
  assertStillCurrent();
778
1013
  let element;
779
1014
  if (AppComponent) element = React.createElement(AppComponent, {
1015
+ ...props,
780
1016
  Component: PageComponent,
781
- pageProps
1017
+ pageProps: rawPageProps,
1018
+ router: Router
782
1019
  });
783
1020
  else element = React.createElement(PageComponent, pageProps);
784
- element = wrapWithRouterContext(element);
785
1021
  if (pendingRedirectHistoryUrl) {
786
1022
  window.history.replaceState(window.history.state ?? {}, "", pendingRedirectHistoryUrl);
787
- _lastPathnameAndSearch = window.location.pathname + window.location.search;
1023
+ routerRuntimeState.lastPathnameAndSearch = window.location.pathname + window.location.search;
788
1024
  }
789
1025
  window.__NEXT_DATA__ = nextData;
790
1026
  applyVinextLocaleGlobals(window, nextData);
791
- root.render(element);
1027
+ await renderPagesRouterElement(element, options.scroll);
1028
+ assertStillCurrent();
792
1029
  }
793
1030
  /**
794
1031
  * Perform client-side navigation. Prefers the JSON data endpoint when the
@@ -806,43 +1043,49 @@ async function navigateClientHtml(url, fetchUrl, controller, navId, assertStillC
806
1043
  */
807
1044
  async function navigateClient(url, fetchUrl = url, options = {}) {
808
1045
  if (typeof window === "undefined") return;
809
- _activeAbortController?.abort();
1046
+ routerRuntimeState.activeAbortController?.abort();
1047
+ cancelPreviousRenderCommit();
810
1048
  const controller = new AbortController();
811
- _activeAbortController = controller;
812
- const navId = ++_navigationId;
1049
+ routerRuntimeState.activeAbortController = controller;
1050
+ const navId = ++routerRuntimeState.navigationId;
813
1051
  /** Check if this navigation is still the active one. If not, throw. */
814
1052
  function assertStillCurrent() {
815
- if (navId !== _navigationId) throw new NavigationCancelledError(url);
1053
+ if (navId !== routerRuntimeState.navigationId) throw new NavigationCancelledError(url);
816
1054
  }
817
1055
  try {
818
1056
  if (options.allowNotFoundResponse === true) await navigateClientHtml(url, fetchUrl, controller, navId, assertStillCurrent, options);
819
1057
  else {
820
1058
  let browserUrl = url;
821
1059
  let htmlFetchUrl = fetchUrl;
822
- const dataTarget = resolvePagesDataNavigationTarget(browserUrl, __basePath);
1060
+ let dataTarget = resolvePagesDataNavigationTarget(browserUrl, __basePath);
1061
+ let middlewareDataResponse;
823
1062
  if (!dataTarget) {
824
- let redirectLocation;
1063
+ let middlewareEffect;
825
1064
  try {
826
- redirectLocation = await resolveMiddlewareDataRedirect(browserUrl, controller.signal);
1065
+ middlewareEffect = await resolveMiddlewareDataEffect(browserUrl, controller.signal);
827
1066
  } catch (err) {
828
1067
  if (err instanceof DOMException && err.name === "AbortError") throw new NavigationCancelledError(browserUrl);
829
1068
  throw err;
830
1069
  }
831
1070
  assertStillCurrent();
1071
+ const redirectLocation = middlewareEffect?.redirectLocation ?? null;
832
1072
  if (redirectLocation) {
833
1073
  const redirectedUrl = resolveLocalRedirectUrl(redirectLocation);
834
1074
  if (!redirectedUrl) scheduleHardNavigationAndThrow(redirectLocation, "Navigation redirected externally");
835
1075
  window.history.replaceState(window.history.state ?? {}, "", redirectedUrl);
836
- _lastPathnameAndSearch = window.location.pathname + window.location.search;
1076
+ routerRuntimeState.lastPathnameAndSearch = window.location.pathname + window.location.search;
837
1077
  browserUrl = redirectedUrl;
838
1078
  htmlFetchUrl = redirectedUrl;
1079
+ } else if (middlewareEffect?.rewriteTarget) {
1080
+ dataTarget = resolvePagesDataNavigationTarget(middlewareEffect.rewriteTarget, __basePath);
1081
+ if (dataTarget) middlewareDataResponse = middlewareEffect.response;
839
1082
  }
840
1083
  }
841
- if (dataTarget) await navigateClientData(browserUrl, dataTarget, controller, navId, assertStillCurrent, options);
1084
+ if (dataTarget) await navigateClientData(browserUrl, dataTarget, controller, navId, assertStillCurrent, options, middlewareDataResponse);
842
1085
  else await navigateClientHtml(browserUrl, htmlFetchUrl, controller, navId, assertStillCurrent, options);
843
1086
  }
844
1087
  } finally {
845
- if (navId === _navigationId) _activeAbortController = null;
1088
+ if (navId === routerRuntimeState.navigationId) routerRuntimeState.activeAbortController = null;
846
1089
  }
847
1090
  }
848
1091
  /**
@@ -928,8 +1171,8 @@ function dispatchNavigateEvent() {
928
1171
  * locale and the canonical app-relative `as` path.
929
1172
  */
930
1173
  function updateHistory(mode, fullUrl, navState) {
931
- const previousState = typeof window.history.state === "object" && window.history.state !== null ? window.history.state : null;
932
- const key = mode === "push" ? createHistoryKey() : previousState?.key ?? createHistoryKey();
1174
+ const previousKey = getRouterStateKey(window.history.state);
1175
+ const key = mode === "push" ? createHistoryKey() : previousKey ?? routerRuntimeState.currentHistoryKey ?? createHistoryKey();
933
1176
  const state = {
934
1177
  url: navState?.url ?? fullUrl,
935
1178
  as: navState?.as ?? fullUrl,
@@ -939,13 +1182,13 @@ function updateHistory(mode, fullUrl, navState) {
939
1182
  };
940
1183
  if (mode === "push") window.history.pushState(state, "", fullUrl);
941
1184
  else window.history.replaceState(state, "", fullUrl);
942
- _lastPathnameAndSearch = window.location.pathname + window.location.search;
943
- _routerDidNavigate = true;
1185
+ routerRuntimeState.currentHistoryKey = key;
1186
+ routerRuntimeState.lastPathnameAndSearch = window.location.pathname + window.location.search;
1187
+ routerRuntimeState.routerDidNavigate = true;
944
1188
  }
945
- let _historyKeyCounter = 0;
946
1189
  function createHistoryKey() {
947
- _historyKeyCounter += 1;
948
- return `vinext_${_historyKeyCounter.toString(36)}_${Math.random().toString(36).slice(2, 9)}`;
1190
+ routerRuntimeState.historyKeyCounter += 1;
1191
+ return `vinext_${routerRuntimeState.historyKeyCounter.toString(36)}_${Math.random().toString(36).slice(2, 9)}`;
949
1192
  }
950
1193
  /**
951
1194
  * Throw the canonical "no router instance" error used when a Pages Router
@@ -993,12 +1236,21 @@ async function performNavigation(url, as, options, mode, onStateUpdate) {
993
1236
  const full = normalizePathTrailingSlash(toBrowserNavigationHref(resolved, window.location.href, __basePath), __trailingSlash);
994
1237
  const errorRouteHtmlFetchUrl = resolvePagesErrorHtmlFetchUrl(url, navigationLocale);
995
1238
  const htmlFetchUrl = errorRouteHtmlFetchUrl ?? getPagesHtmlFetchUrl(full, navigationLocale);
996
- const navigateOptions = errorRouteHtmlFetchUrl ? {
997
- allowNotFoundResponse: true,
998
- mode
999
- } : { mode };
1000
1239
  const shallow = options?.shallow ?? false;
1001
1240
  const doScroll = options?.scroll !== false;
1241
+ const hash = extractHash(resolved);
1242
+ const scrollTarget = doScroll ? {
1243
+ x: 0,
1244
+ y: 0
1245
+ } : null;
1246
+ const navigateOptions = errorRouteHtmlFetchUrl ? {
1247
+ allowNotFoundResponse: true,
1248
+ mode,
1249
+ scroll: scrollTarget
1250
+ } : {
1251
+ mode,
1252
+ scroll: scrollTarget
1253
+ };
1002
1254
  const navStateOptions = { shallow };
1003
1255
  if (navigationLocale !== void 0) navStateOptions.locale = navigationLocale;
1004
1256
  const resolvedNoHash = stripHash(resolved);
@@ -1007,7 +1259,8 @@ async function performNavigation(url, as, options, mode, onStateUpdate) {
1007
1259
  as: resolvedNoHash,
1008
1260
  options: navStateOptions
1009
1261
  };
1010
- if (isHashOnlyChange(full)) {
1262
+ if (options?._h !== 1 && isHashOnlyChange(full)) {
1263
+ if (mode === "push") saveScrollPosition();
1011
1264
  const eventUrl = resolveHashUrl(full);
1012
1265
  routerEvents.emit("hashChangeStart", eventUrl, { shallow });
1013
1266
  updateHistory(mode, resolved.startsWith("#") ? resolved : full, navState);
@@ -1017,20 +1270,28 @@ async function performNavigation(url, as, options, mode, onStateUpdate) {
1017
1270
  dispatchNavigateEvent();
1018
1271
  return true;
1019
1272
  }
1273
+ const appPath = getLocalPathname(resolved);
1274
+ const appPathNorm = appPath !== null ? removeTrailingSlash(appPath) : null;
1275
+ const appPathEntry = appPathNorm !== null ? getPagesRouterComponentsMap()[appPathNorm] : void 0;
1276
+ if (appPathEntry !== void 0 && "__appRouter" in appPathEntry && appPathEntry.__appRouter || ["app", "document"].includes(resolveHybridClientRouteOwner(resolved, __basePath) ?? "")) {
1277
+ if (mode === "push") window.location.assign(full);
1278
+ else window.location.replace(full);
1279
+ return new Promise(() => {});
1280
+ }
1020
1281
  if (mode === "push") saveScrollPosition();
1021
- routerEvents.emit("routeChangeStart", resolved, { shallow });
1282
+ const isQueryUpdating = options?._h === 1;
1283
+ if (!isQueryUpdating) routerEvents.emit("routeChangeStart", resolved, { shallow });
1022
1284
  routerEvents.emit("beforeHistoryChange", resolved, { shallow });
1023
1285
  updateHistory(mode, full, navState);
1024
1286
  if (!shallow) {
1025
1287
  const result = await runNavigateClient(full, resolved, htmlFetchUrl, navigateOptions);
1026
1288
  if (result === "cancelled") return true;
1027
1289
  if (result === "failed") return false;
1028
- }
1029
- onStateUpdate?.();
1030
- routerEvents.emit("routeChangeComplete", resolved, { shallow });
1031
- const hash = extractHash(resolved);
1032
- if (doScroll) if (hash) scrollToHashTarget(hash);
1290
+ } else if (doScroll) if (hash) scrollToHashTarget(hash);
1033
1291
  else window.scrollTo(0, 0);
1292
+ onStateUpdate?.();
1293
+ if (!isQueryUpdating) routerEvents.emit("routeChangeComplete", resolved, { shallow });
1294
+ if (doScroll && hash && !shallow) scrollToHashTarget(hash);
1034
1295
  dispatchNavigateEvent();
1035
1296
  return true;
1036
1297
  }
@@ -1075,8 +1336,9 @@ async function prefetchUrl(url) {
1075
1336
  */
1076
1337
  function useRouter() {
1077
1338
  const router = useContext(RouterContext);
1078
- if (!router) throw new Error("NextRouter was not mounted. https://nextjs.org/docs/messages/next-router-not-mounted");
1079
- return router;
1339
+ if (router) return router;
1340
+ if (typeof window !== "undefined" && window.__VINEXT_PAGE_LOADERS__ !== void 0) return Router;
1341
+ throw new Error("NextRouter was not mounted. https://nextjs.org/docs/messages/next-router-not-mounted");
1080
1342
  }
1081
1343
  function PagesRouterProvider({ children }) {
1082
1344
  const [{ pathname, query, asPath, isReady }, setState] = useState(getRouterSnapshot);
@@ -1087,9 +1349,11 @@ function PagesRouterProvider({ children }) {
1087
1349
  window.addEventListener("vinext:navigate", onNavigate);
1088
1350
  let cancelled = false;
1089
1351
  const readyTimer = window.setTimeout(() => {
1090
- if (cancelled || !markPagesRouterReady()) return;
1091
- setState(getRouterSnapshot());
1092
- notifyNextNavigationPagesContext();
1352
+ if (cancelled) return;
1353
+ if (markPagesRouterReady()) {
1354
+ setState(getRouterSnapshot());
1355
+ notifyNextNavigationPagesContext();
1356
+ }
1093
1357
  }, 0);
1094
1358
  return () => {
1095
1359
  cancelled = true;
@@ -1132,36 +1396,47 @@ function PagesRouterProvider({ children }) {
1132
1396
  Router.prefetch(href);
1133
1397
  }
1134
1398
  }), []);
1135
- const content = createElement(RouterContext.Provider, { value: router }, children);
1399
+ const content = createElement(RouterContext.Provider, { value: router }, createElement(Fragment, null, children, createElement(PagesRouterHydrationMarker)));
1136
1400
  return AppRouterContext ? createElement(AppRouterContext.Provider, { value: appRouter }, content) : content;
1137
1401
  }
1138
- let _beforePopStateCb;
1139
- let _lastPathnameAndSearch = typeof window !== "undefined" ? window.location.pathname + window.location.search : "";
1140
- let _isFirstPopStateEvent = true;
1141
- let _routerDidNavigate = false;
1142
1402
  function isNextRouterState(state) {
1143
1403
  return typeof state === "object" && state !== null && "__N" in state && state.__N === true;
1144
1404
  }
1405
+ function getRouterStateKey(state) {
1406
+ if (!isNextRouterState(state)) return void 0;
1407
+ return typeof state.key === "string" ? state.key : void 0;
1408
+ }
1145
1409
  function handlePagesRouterPopState(e) {
1146
1410
  const browserUrl = window.location.pathname + window.location.search;
1147
1411
  const appUrl = stripBasePath(window.location.pathname, __basePath) + window.location.search;
1148
1412
  const state = e.state;
1149
- const wasFirst = _isFirstPopStateEvent;
1150
- _isFirstPopStateEvent = false;
1413
+ const wasFirst = routerRuntimeState.isFirstPopStateEvent;
1414
+ routerRuntimeState.isFirstPopStateEvent = false;
1151
1415
  if (state !== null && state !== void 0 && !isNextRouterState(state)) return;
1152
- if (wasFirst && !_routerDidNavigate && isNextRouterState(state)) {
1416
+ if (wasFirst && !routerRuntimeState.routerDidNavigate && isNextRouterState(state)) {
1153
1417
  const currentLocale = window.__VINEXT_LOCALE__;
1154
- if (state.options?.locale === currentLocale && typeof state.as === "string" && withBasePath(state.as, __basePath) === _lastPathnameAndSearch) return;
1418
+ if (state.options?.locale === currentLocale && typeof state.as === "string" && withBasePath(state.as, __basePath) === routerRuntimeState.lastPathnameAndSearch) return;
1419
+ }
1420
+ const isHashOnly = browserUrl === routerRuntimeState.lastPathnameAndSearch;
1421
+ const targetKey = getRouterStateKey(state);
1422
+ let forcedScroll;
1423
+ if (manualScrollRestoration) {
1424
+ const currentKey = routerRuntimeState.currentHistoryKey;
1425
+ if (currentKey !== void 0 && currentKey !== targetKey) saveScrollPositionToSessionStorage(currentKey, getWindowScrollPosition());
1426
+ if (targetKey !== void 0 && currentKey !== targetKey) forcedScroll = readScrollPositionFromSessionStorage(targetKey) ?? {
1427
+ x: 0,
1428
+ y: 0
1429
+ };
1155
1430
  }
1156
- const isHashOnly = browserUrl === _lastPathnameAndSearch;
1157
- if (_beforePopStateCb !== void 0) {
1158
- if (!_beforePopStateCb({
1431
+ if (routerRuntimeState.beforePopStateCb !== void 0) {
1432
+ if (!routerRuntimeState.beforePopStateCb({
1159
1433
  url: appUrl,
1160
1434
  as: appUrl,
1161
1435
  options: { shallow: false }
1162
1436
  })) return;
1163
1437
  }
1164
- _lastPathnameAndSearch = browserUrl;
1438
+ if (targetKey !== void 0) routerRuntimeState.currentHistoryKey = targetKey;
1439
+ routerRuntimeState.lastPathnameAndSearch = browserUrl;
1165
1440
  if (isHashOnly) {
1166
1441
  const hashUrl = appUrl + window.location.hash;
1167
1442
  routerEvents.emit("hashChangeStart", hashUrl, { shallow: false });
@@ -1175,9 +1450,12 @@ function handlePagesRouterPopState(e) {
1175
1450
  routerEvents.emit("routeChangeStart", fullAppUrl, { shallow: false });
1176
1451
  routerEvents.emit("beforeHistoryChange", fullAppUrl, { shallow: false });
1177
1452
  (async () => {
1178
- if (await runNavigateClient(browserUrl, fullAppUrl, getPagesHtmlFetchUrl(browserUrl, effectiveLocale)) === "completed") {
1453
+ const scrollTarget = manualScrollRestoration ? forcedScroll ?? readScrollPosition(state) ?? {
1454
+ x: 0,
1455
+ y: 0
1456
+ } : readScrollPosition(state);
1457
+ if (await runNavigateClient(browserUrl, fullAppUrl, getPagesHtmlFetchUrl(browserUrl, effectiveLocale), { scroll: scrollTarget }) === "completed") {
1179
1458
  routerEvents.emit("routeChangeComplete", fullAppUrl, { shallow: false });
1180
- restoreScrollPosition(e.state);
1181
1459
  dispatchNavigateEvent();
1182
1460
  }
1183
1461
  })();
@@ -1190,9 +1468,22 @@ setPagesRouterPopStateHandler(handlePagesRouterPopState);
1190
1468
  * The provider owns the reactive Pages Router snapshot so next/router and
1191
1469
  * next/compat/router consumers share one context value instead of each hook
1192
1470
  * installing its own global URL-change listener.
1471
+ *
1472
+ * The PagesRouterCommitBoundary exists for client navigations: its layout
1473
+ * callback runs scroll restoration at commit time and resolves the navigation
1474
+ * at the same root-commit boundary Next.js awaits before routeChangeComplete.
1475
+ * Its onError rejection drives the hard-navigation fallback in runNavigateClient.
1476
+ * The same boundary intentionally also wraps SSR and initial hydration, where
1477
+ * callbacks default to noopCommit: a hydration-time render error is caught
1478
+ * here (React still console.error's it) instead of propagating, matching the
1479
+ * navigation-path containment.
1193
1480
  */
1194
- function wrapWithRouterContext(element) {
1195
- return createElement(PagesRouterProvider, null, element);
1481
+ function wrapWithRouterContext(element, onCommit = noopCommit, onError = noopCommit) {
1482
+ const { CommitBoundary, Provider } = getPagesRouterRuntimeComponents();
1483
+ return createElement(CommitBoundary, {
1484
+ onCommit,
1485
+ onError
1486
+ }, createElement(Provider, null, element));
1196
1487
  }
1197
1488
  /**
1198
1489
  * Higher-order component that injects the Pages Router `router` instance as
@@ -1255,7 +1546,7 @@ const RouterMethods = {
1255
1546
  },
1256
1547
  beforePopState: (cb) => {
1257
1548
  if (typeof window === "undefined") throwNoRouterInstance();
1258
- _beforePopStateCb = cb;
1549
+ routerRuntimeState.beforePopStateCb = cb;
1259
1550
  },
1260
1551
  events: routerEvents
1261
1552
  };
@@ -1322,7 +1613,7 @@ const Router = Object.defineProperties(RouterMethods, {
1322
1613
  isReady: {
1323
1614
  enumerable: true,
1324
1615
  get() {
1325
- return isPagesRouterReady();
1616
+ return isPagesRouterReady() && (typeof window === "undefined" || window.__NEXT_HYDRATED === true);
1326
1617
  }
1327
1618
  },
1328
1619
  isPreview: {
@@ -1338,8 +1629,35 @@ const Router = Object.defineProperties(RouterMethods, {
1338
1629
  }
1339
1630
  }
1340
1631
  });
1341
- if (typeof window !== "undefined") installWindowNext({ router: Router });
1632
+ routerRuntimeState.publicRouter = Router;
1633
+ const deprecatedRouterEvents = [
1634
+ "routeChangeStart",
1635
+ "beforeHistoryChange",
1636
+ "routeChangeComplete",
1637
+ "routeChangeError",
1638
+ "hashChangeStart",
1639
+ "hashChangeComplete"
1640
+ ];
1641
+ if (!routerRuntimeState.deprecatedEventBridgeInstalled) {
1642
+ routerRuntimeState.deprecatedEventBridgeInstalled = true;
1643
+ for (const event of deprecatedRouterEvents) {
1644
+ const eventField = `on${event.charAt(0).toUpperCase()}${event.substring(1)}`;
1645
+ routerEvents.on(event, (...args) => {
1646
+ const handler = (routerRuntimeState.publicRouter ?? Router)[eventField];
1647
+ if (typeof handler === "function") try {
1648
+ handler(...args);
1649
+ } catch (err) {
1650
+ console.error(`Error when running the Router event: ${eventField}`);
1651
+ console.error(err instanceof Error ? `${err.message}\n${err.stack}` : String(err));
1652
+ }
1653
+ });
1654
+ }
1655
+ }
1656
+ if (typeof window !== "undefined") {
1657
+ installPagesRouterRuntime();
1658
+ installWindowNext({ router: Router });
1659
+ }
1342
1660
  const _PAGES_NAVIGATION_ACCESSOR_KEY = Symbol.for("vinext.navigation.pagesNavigationContextAccessor");
1343
1661
  globalThis[_PAGES_NAVIGATION_ACCESSOR_KEY] = getPagesNavigationContext;
1344
1662
  //#endregion
1345
- export { _registerRouterStateAccessors, applyNavigationLocale, Router as default, getPagesNavigationContext, getPagesNavigationIsReadyFromSerializedState, isExternalUrl, isHashOnlyChange, setSSRContext, useRouter, withRouter, wrapWithRouterContext };
1663
+ export { markPagesRouterReady as _markPagesRouterReady, _registerRouterStateAccessors, applyNavigationLocale, Router as default, getPagesNavigationContext, getPagesNavigationIsReadyFromSerializedState, isExternalUrl, isHashOnlyChange, setSSRContext, useRouter, withRouter, wrapWithRouterContext };