vinext 1.0.0-beta.1 → 1.0.0-beta.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 (234) hide show
  1. package/README.md +10 -10
  2. package/dist/build/client-build-config.js +8 -1
  3. package/dist/build/report.d.ts +8 -1
  4. package/dist/build/report.js +12 -2
  5. package/dist/check.js +19 -2
  6. package/dist/cli.js +3 -2
  7. package/dist/config/config-matchers.d.ts +13 -37
  8. package/dist/config/config-matchers.js +35 -122
  9. package/dist/config/next-config.d.ts +15 -5
  10. package/dist/config/next-config.js +7 -1
  11. package/dist/config/request-context.d.ts +14 -0
  12. package/dist/config/request-context.js +26 -0
  13. package/dist/entries/app-browser-entry.d.ts +4 -10
  14. package/dist/entries/app-browser-entry.js +20 -4
  15. package/dist/entries/app-rsc-entry.js +30 -9
  16. package/dist/entries/app-rsc-manifest.js +36 -0
  17. package/dist/entries/pages-client-entry.js +0 -1
  18. package/dist/entries/pages-server-entry.js +13 -5
  19. package/dist/index.js +194 -101
  20. package/dist/init-cloudflare.d.ts +3 -1
  21. package/dist/init-cloudflare.js +59 -5
  22. package/dist/init.d.ts +6 -4
  23. package/dist/init.js +20 -22
  24. package/dist/plugins/extensionless-dynamic-import.js +23 -18
  25. package/dist/plugins/ignore-dynamic-requests.js +3 -1
  26. package/dist/plugins/import-meta-url.js +17 -6
  27. package/dist/plugins/og-assets.js +1 -1
  28. package/dist/plugins/require-context.js +20 -15
  29. package/dist/plugins/transform-cache.d.ts +19 -0
  30. package/dist/plugins/transform-cache.js +36 -0
  31. package/dist/routing/app-route-graph.d.ts +27 -11
  32. package/dist/routing/app-route-graph.js +158 -22
  33. package/dist/routing/app-router.js +12 -6
  34. package/dist/routing/file-matcher.d.ts +11 -22
  35. package/dist/routing/file-matcher.js +21 -33
  36. package/dist/routing/pages-router.js +23 -29
  37. package/dist/routing/route-matching.d.ts +14 -1
  38. package/dist/routing/route-matching.js +13 -1
  39. package/dist/routing/route-pattern.d.ts +2 -1
  40. package/dist/routing/route-pattern.js +7 -4
  41. package/dist/routing/route-trie.d.ts +5 -1
  42. package/dist/routing/route-trie.js +5 -2
  43. package/dist/server/api-handler.d.ts +2 -0
  44. package/dist/server/api-handler.js +3 -3
  45. package/dist/server/app-browser-entry.js +110 -37
  46. package/dist/server/app-browser-history-controller.d.ts +1 -1
  47. package/dist/server/app-browser-history-controller.js +3 -3
  48. package/dist/server/app-browser-navigation-controller.d.ts +23 -21
  49. package/dist/server/app-browser-navigation-controller.js +2 -2
  50. package/dist/server/app-browser-state.js +1 -1
  51. package/dist/server/app-browser-visible-commit.js +1 -1
  52. package/dist/server/app-fallback-renderer.d.ts +3 -0
  53. package/dist/server/app-fallback-renderer.js +4 -2
  54. package/dist/server/app-middleware.js +2 -1
  55. package/dist/server/app-page-boundary-render.d.ts +12 -1
  56. package/dist/server/app-page-boundary-render.js +84 -2
  57. package/dist/server/app-page-cache-finalizer.d.ts +1 -1
  58. package/dist/server/app-page-cache-finalizer.js +1 -1
  59. package/dist/server/app-page-cache.d.ts +2 -2
  60. package/dist/server/app-page-cache.js +16 -2
  61. package/dist/server/app-page-dispatch.d.ts +19 -2
  62. package/dist/server/app-page-dispatch.js +45 -23
  63. package/dist/server/app-page-element-builder.d.ts +9 -2
  64. package/dist/server/app-page-element-builder.js +144 -33
  65. package/dist/server/app-page-head.d.ts +56 -4
  66. package/dist/server/app-page-head.js +216 -85
  67. package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
  68. package/dist/server/app-page-http-access-fallback-metadata.js +114 -0
  69. package/dist/server/app-page-probe.d.ts +4 -0
  70. package/dist/server/app-page-probe.js +6 -2
  71. package/dist/server/app-page-render.d.ts +2 -2
  72. package/dist/server/app-page-render.js +1 -1
  73. package/dist/server/app-page-request.d.ts +15 -0
  74. package/dist/server/app-page-request.js +134 -14
  75. package/dist/server/app-page-response.js +1 -1
  76. package/dist/server/app-page-route-wiring.d.ts +16 -0
  77. package/dist/server/app-page-route-wiring.js +254 -52
  78. package/dist/server/app-pages-bridge.d.ts +1 -1
  79. package/dist/server/app-pages-bridge.js +2 -1
  80. package/dist/server/app-post-middleware-context.d.ts +1 -1
  81. package/dist/server/app-post-middleware-context.js +1 -1
  82. package/dist/server/app-route-handler-cache.js +4 -0
  83. package/dist/server/app-route-handler-dispatch.js +40 -20
  84. package/dist/server/app-route-handler-execution.d.ts +6 -1
  85. package/dist/server/app-route-handler-execution.js +42 -16
  86. package/dist/server/app-route-handler-policy.d.ts +2 -0
  87. package/dist/server/app-route-handler-policy.js +3 -3
  88. package/dist/server/app-route-handler-response.js +1 -1
  89. package/dist/server/app-route-module-loader.d.ts +9 -1
  90. package/dist/server/app-route-module-loader.js +4 -0
  91. package/dist/server/app-router-entry.js +6 -3
  92. package/dist/server/app-rsc-cache-busting.d.ts +1 -1
  93. package/dist/server/app-rsc-errors.d.ts +1 -1
  94. package/dist/server/app-rsc-errors.js +22 -2
  95. package/dist/server/app-rsc-handler.d.ts +10 -5
  96. package/dist/server/app-rsc-handler.js +73 -33
  97. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  98. package/dist/server/app-rsc-request-normalization.js +8 -2
  99. package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
  100. package/dist/server/app-rsc-response-finalizer.js +5 -11
  101. package/dist/server/app-rsc-route-matching.d.ts +29 -0
  102. package/dist/server/app-rsc-route-matching.js +93 -11
  103. package/dist/server/app-segment-config.js +13 -3
  104. package/dist/server/app-server-action-execution.d.ts +3 -1
  105. package/dist/server/app-server-action-execution.js +9 -7
  106. package/dist/server/app-ssr-entry.js +6 -6
  107. package/dist/server/app-ssr-stream.d.ts +1 -7
  108. package/dist/server/app-ssr-stream.js +2 -10
  109. package/dist/server/cache-control.d.ts +2 -2
  110. package/dist/server/cache-control.js +2 -1
  111. package/dist/server/config-headers.d.ts +24 -0
  112. package/dist/server/config-headers.js +52 -0
  113. package/dist/server/dev-initial-server-error.d.ts +1 -1
  114. package/dist/server/dev-server.d.ts +3 -1
  115. package/dist/server/dev-server.js +170 -321
  116. package/dist/server/headers.d.ts +2 -2
  117. package/dist/server/headers.js +4 -3
  118. package/dist/server/isr-cache.d.ts +11 -34
  119. package/dist/server/isr-cache.js +33 -43
  120. package/dist/server/isr-decision.d.ts +2 -2
  121. package/dist/server/middleware-matcher-pattern.d.ts +22 -0
  122. package/dist/server/middleware-matcher-pattern.js +219 -0
  123. package/dist/server/middleware-matcher.d.ts +2 -7
  124. package/dist/server/middleware-matcher.js +13 -60
  125. package/dist/server/middleware-path-to-regexp.d.ts +14 -0
  126. package/dist/server/middleware-path-to-regexp.js +228 -0
  127. package/dist/server/middleware-runtime.js +4 -3
  128. package/dist/server/middleware.d.ts +1 -1
  129. package/dist/server/middleware.js +2 -1
  130. package/dist/server/pages-api-route.d.ts +2 -0
  131. package/dist/server/pages-api-route.js +4 -1
  132. package/dist/server/pages-data-route.d.ts +11 -1
  133. package/dist/server/pages-data-route.js +16 -1
  134. package/dist/server/pages-dev-hydration.js +0 -1
  135. package/dist/server/pages-get-initial-props.d.ts +16 -3
  136. package/dist/server/pages-get-initial-props.js +17 -10
  137. package/dist/server/pages-i18n.js +64 -16
  138. package/dist/server/pages-node-compat.d.ts +2 -0
  139. package/dist/server/pages-node-compat.js +7 -3
  140. package/dist/server/pages-page-data.d.ts +64 -10
  141. package/dist/server/pages-page-data.js +349 -80
  142. package/dist/server/pages-page-handler.d.ts +9 -3
  143. package/dist/server/pages-page-handler.js +131 -36
  144. package/dist/server/pages-page-response.d.ts +5 -3
  145. package/dist/server/pages-page-response.js +24 -27
  146. package/dist/server/pages-readiness.d.ts +3 -3
  147. package/dist/server/pages-request-pipeline.d.ts +8 -0
  148. package/dist/server/pages-request-pipeline.js +30 -12
  149. package/dist/server/pages-revalidate.d.ts +1 -1
  150. package/dist/server/pages-revalidate.js +54 -8
  151. package/dist/server/pages-router-entry.d.ts +1 -0
  152. package/dist/server/pages-router-entry.js +16 -4
  153. package/dist/server/prerender-route-params.js +2 -2
  154. package/dist/server/prod-server.d.ts +3 -5
  155. package/dist/server/prod-server.js +72 -35
  156. package/dist/server/request-pipeline.d.ts +15 -29
  157. package/dist/server/request-pipeline.js +24 -59
  158. package/dist/server/revalidation-host.d.ts +11 -0
  159. package/dist/server/revalidation-host.js +19 -0
  160. package/dist/server/rsc-stream-hints.js +122 -18
  161. package/dist/server/worker-revalidation-context.d.ts +13 -0
  162. package/dist/server/worker-revalidation-context.js +29 -0
  163. package/dist/shims/app.d.ts +1 -1
  164. package/dist/shims/cache-handler.d.ts +1 -1
  165. package/dist/shims/cache-handler.js +10 -7
  166. package/dist/shims/cache-request-state.d.ts +27 -1
  167. package/dist/shims/cache-request-state.js +60 -1
  168. package/dist/shims/cache-runtime.d.ts +18 -1
  169. package/dist/shims/cache-runtime.js +26 -8
  170. package/dist/shims/cache.d.ts +5 -5
  171. package/dist/shims/cache.js +27 -11
  172. package/dist/shims/document.d.ts +42 -83
  173. package/dist/shims/document.js +62 -53
  174. package/dist/shims/dynamic.d.ts +5 -25
  175. package/dist/shims/dynamic.js +29 -8
  176. package/dist/shims/error.d.ts +1 -1
  177. package/dist/shims/error.js +2 -2
  178. package/dist/shims/fetch-cache.js +13 -4
  179. package/dist/shims/font-google-base.d.ts +11 -4
  180. package/dist/shims/font-google-base.js +17 -8
  181. package/dist/shims/font-local.d.ts +10 -3
  182. package/dist/shims/font-local.js +41 -10
  183. package/dist/shims/head.d.ts +13 -2
  184. package/dist/shims/head.js +3 -3
  185. package/dist/shims/headers.d.ts +37 -43
  186. package/dist/shims/headers.js +183 -74
  187. package/dist/shims/image.d.ts +27 -37
  188. package/dist/shims/image.js +21 -14
  189. package/dist/shims/internal/cookie-serialize.d.ts +12 -9
  190. package/dist/shims/internal/cookie-serialize.js +10 -7
  191. package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
  192. package/dist/shims/internal/interpolate-as.d.ts +15 -1
  193. package/dist/shims/internal/interpolate-as.js +27 -2
  194. package/dist/shims/internal/utils.d.ts +3 -3
  195. package/dist/shims/legacy-image.d.ts +3 -37
  196. package/dist/shims/legacy-image.js +6 -16
  197. package/dist/shims/link.d.ts +15 -22
  198. package/dist/shims/link.js +34 -13
  199. package/dist/shims/metadata.d.ts +7 -17
  200. package/dist/shims/metadata.js +74 -24
  201. package/dist/shims/navigation-context-state.d.ts +1 -1
  202. package/dist/shims/navigation.d.ts +7 -3
  203. package/dist/shims/navigation.js +25 -14
  204. package/dist/shims/navigation.react-server.js +1 -1
  205. package/dist/shims/next-shims-augmentations.d.ts +1 -0
  206. package/dist/shims/next-shims-public.d.ts +1 -0
  207. package/dist/shims/public-shim-map.json.js +103 -0
  208. package/dist/shims/readonly-url-search-params.d.ts +3 -3
  209. package/dist/shims/readonly-url-search-params.js +3 -3
  210. package/dist/shims/request-context.d.ts +4 -1
  211. package/dist/shims/request-state-types.d.ts +1 -1
  212. package/dist/shims/router.d.ts +55 -21
  213. package/dist/shims/router.js +180 -44
  214. package/dist/shims/script.d.ts +6 -10
  215. package/dist/shims/script.js +7 -4
  216. package/dist/shims/server.d.ts +50 -26
  217. package/dist/shims/server.js +193 -55
  218. package/dist/shims/unified-request-context.d.ts +22 -3
  219. package/dist/shims/unified-request-context.js +84 -1
  220. package/dist/shims/url-safety.d.ts +1 -1
  221. package/dist/shims/url-safety.js +2 -2
  222. package/dist/typegen.d.ts +8 -2
  223. package/dist/typegen.js +76 -15
  224. package/dist/utils/cache-control-metadata.d.ts +2 -1
  225. package/dist/utils/cache-control-metadata.js +5 -1
  226. package/dist/utils/domain-locale.d.ts +2 -2
  227. package/dist/utils/external-url.d.ts +5 -0
  228. package/dist/utils/external-url.js +7 -0
  229. package/dist/utils/html-limited-bots.js +1 -1
  230. package/dist/utils/protocol-headers.d.ts +7 -1
  231. package/dist/utils/protocol-headers.js +7 -1
  232. package/dist/utils/regex-safety.d.ts +8 -0
  233. package/dist/utils/regex-safety.js +737 -0
  234. package/package.json +13 -2
@@ -2,6 +2,7 @@ import { splitPathSegments } from "../routing/utils.js";
2
2
  import { hasBasePath, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
3
3
  import { parseCookieHeader } from "../utils/parse-cookie.js";
4
4
  import { assertSafeNavigationUrl } from "./url-safety.js";
5
+ import { isExternalUrl } from "../utils/external-url.js";
5
6
  import { isUnknownRecord } from "../utils/record.js";
6
7
  import { AppRouterContext } from "./internal/app-router-context.js";
7
8
  import { RouterContext } from "./internal/router-context.js";
@@ -217,7 +218,8 @@ function getPagesRouterRuntimeComponents() {
217
218
  }
218
219
  function resolveUrl(url) {
219
220
  if (typeof url === "string") return url;
220
- const hasQuery = url.query !== void 0 && Object.keys(url.query).length > 0;
221
+ const query = url.query && typeof url.query === "object" ? url.query : void 0;
222
+ const hasQuery = query !== void 0 && Object.keys(query).length > 0;
221
223
  const hasSearch = typeof url.search === "string" && url.search.length > 0;
222
224
  const hasHash = typeof url.hash === "string" && url.hash.length > 0;
223
225
  const inheritsVisiblePath = url.pathname === void 0 && (hasQuery || hasSearch || hasHash);
@@ -227,7 +229,7 @@ function resolveUrl(url) {
227
229
  const hashIndex = search.indexOf("#");
228
230
  result += hashIndex === -1 ? search : `${search.slice(0, hashIndex)}%23${search.slice(hashIndex + 1)}`;
229
231
  } else if (hasQuery) {
230
- const params = urlQueryToSearchParams(url.query);
232
+ const params = urlQueryToSearchParams(query);
231
233
  result = appendSearchParamsToUrl(result, params);
232
234
  } else if (hasHash && typeof window !== "undefined") result += window.location.search;
233
235
  if (hasHash) result += url.hash.startsWith("#") ? url.hash : `#${url.hash}`;
@@ -245,6 +247,23 @@ function resolveUrl(url) {
245
247
  function resolveNavigationTarget(url, as, locale, replaceExistingLocale = false) {
246
248
  return applyNavigationLocale(as ?? resolveUrl(url), locale, replaceExistingLocale);
247
249
  }
250
+ /**
251
+ * Next.js's internal `_h` replacement receives browser-visible URLs, which may
252
+ * already contain basePath and a locale prefix. Convert those back to app
253
+ * paths before the normal history/data URL builders run; otherwise basePath is
254
+ * added twice and locale-domain routing can turn a same-document hydration
255
+ * update into an external navigation.
256
+ */
257
+ function normalizeHydrationNavigationUrl(url) {
258
+ try {
259
+ const parsed = new URL(url, window.location.href);
260
+ const origin = getWindowOrigin();
261
+ if (!origin || parsed.origin !== origin) return url;
262
+ return stripBasePath(parsed.pathname, __basePath) + parsed.search + parsed.hash;
263
+ } catch {
264
+ return url;
265
+ }
266
+ }
248
267
  var HrefInterpolationError = class extends Error {};
249
268
  function interpolateCurrentDynamicRoute(resolved) {
250
269
  if (typeof window === "undefined") return resolved;
@@ -376,10 +395,6 @@ function getPagesHtmlFetchUrl(browserUrl, locale) {
376
395
  const parsed = new URL(browserUrl, window.location.href);
377
396
  return normalizePathTrailingSlash(toBrowserNavigationHref(`${normalizePathTrailingSlash(`/${locale}`, __trailingSlash)}${parsed.search}${parsed.hash}`, window.location.href, __basePath), __trailingSlash);
378
397
  }
379
- /** Check if a URL is external (any URL scheme per RFC 3986, or protocol-relative) */
380
- function isExternalUrl(url) {
381
- return isAbsoluteOrProtocolRelativeUrl(url);
382
- }
383
398
  /** Resolve a hash URL to a basePath-stripped app URL for event payloads */
384
399
  function resolveHashUrl(url) {
385
400
  if (typeof window === "undefined") return url;
@@ -579,7 +594,7 @@ function getPagesNavigationContext() {
579
594
  return ctx;
580
595
  }
581
596
  if (!isPagesRouterDocumentActive()) return null;
582
- const resolvedPath = stripBasePath(window.location.pathname, __basePath);
597
+ const resolvedPath = removeNavigationLocalePrefix(stripBasePath(window.location.pathname, __basePath));
583
598
  const nextData = window.__NEXT_DATA__;
584
599
  const pattern = resolvePagesRoutePatternForPath(nextData?.page, resolvedPath);
585
600
  if (!pattern) return null;
@@ -626,6 +641,12 @@ function resolvePagesRoutePatternForPath(nextDataPage, resolvedPath) {
626
641
  _cachedPagesRoutePattern = resolved;
627
642
  return resolved;
628
643
  }
644
+ function getSerializedRouteQuery(nextData) {
645
+ const query = {};
646
+ for (const [key, value] of Object.entries(nextData?.query ?? {})) if (typeof value === "string") query[key] = value;
647
+ else if (Array.isArray(value)) query[key] = [...value];
648
+ return query;
649
+ }
629
650
  function extractRouteParamsFromPath(pattern, pathname) {
630
651
  return matchRoutePattern(splitPathSegments(pathname), routePatternParts(pattern));
631
652
  }
@@ -687,6 +708,11 @@ function getPathnameAndQuery() {
687
708
  const canonicalResolvedPath = removeNavigationLocalePrefix(resolvedPath);
688
709
  const pathname = window.__NEXT_DATA__?.page ?? canonicalResolvedPath;
689
710
  const nextData = window.__NEXT_DATA__;
711
+ if (!isPagesRouterReady() && !routerRuntimeState.routerDidNavigate && nextData) return {
712
+ pathname,
713
+ query: getSerializedRouteQuery(nextData),
714
+ asPath: getCurrentHistoryAsPath() ?? canonicalResolvedPath + window.location.search + window.location.hash
715
+ };
690
716
  const routeQuery = getRouteQueryFromNextData(nextData, resolvedPath);
691
717
  const searchQuery = {};
692
718
  const params = new URLSearchParams(window.location.search);
@@ -801,6 +827,7 @@ function cancelPreviousRenderCommit() {
801
827
  routerRuntimeState.cancelPendingRenderCommit = null;
802
828
  }
803
829
  function scheduleHardNavigationAndThrow(url, message) {
830
+ assertSafeNavigationUrl(url, HardNavigationScheduledError);
804
831
  if (typeof window === "undefined") throw new HardNavigationScheduledError(message);
805
832
  window.location.href = url;
806
833
  throw new HardNavigationScheduledError(message);
@@ -888,7 +915,7 @@ async function resolveClientConfigRedirect(href) {
888
915
  if (!redirects || redirects.length === 0) return null;
889
916
  const routeContext = getClientConfigRouteContext(href);
890
917
  if (!routeContext) return null;
891
- const { isExternalUrl, matchRedirect, preserveRedirectDestinationQuery } = await import("../config/config-matchers.js");
918
+ const { matchRedirect, preserveRedirectDestinationQuery } = await import("../config/config-matchers.js");
892
919
  const redirect = matchRedirect(routeContext.pathname, redirects, routeContext.context, routeContext.basePathState);
893
920
  if (!redirect) return null;
894
921
  return preserveRedirectDestinationQuery(__basePath && routeContext.basePathState.hadBasePath && !isExternalUrl(redirect.destination) && !hasBasePath(redirect.destination, __basePath) ? __basePath + redirect.destination : redirect.destination, routeContext.search);
@@ -896,7 +923,7 @@ async function resolveClientConfigRedirect(href) {
896
923
  async function applyClientConfigRewrite(href, rewrite) {
897
924
  const routeContext = getClientConfigRouteContext(href);
898
925
  if (!routeContext) return null;
899
- const { isExternalUrl, matchRewrite } = await import("../config/config-matchers.js");
926
+ const { matchRewrite } = await import("../config/config-matchers.js");
900
927
  const rewritten = matchRewrite(routeContext.pathname, [rewrite], routeContext.context, routeContext.basePathState);
901
928
  if (rewritten === null) return null;
902
929
  if (isExternalUrl(rewritten)) return { kind: "document" };
@@ -1111,13 +1138,13 @@ async function loadComponentOnlyProps(PageComponent, AppComponent, target, asPat
1111
1138
  const AppTree = (appProps) => createElement(AppComponent, {
1112
1139
  ...appProps,
1113
1140
  Component: PageComponent,
1114
- router: Router
1141
+ router: singletonRouter
1115
1142
  });
1116
1143
  return propsObject(await AppComponent.getInitialProps({
1117
1144
  Component: PageComponent,
1118
1145
  AppTree,
1119
1146
  ctx,
1120
- router: Router
1147
+ router: singletonRouter
1121
1148
  }));
1122
1149
  }
1123
1150
  if (typeof PageComponent.getInitialProps === "function") return { pageProps: propsObject(await PageComponent.getInitialProps(ctx)) };
@@ -1132,14 +1159,13 @@ async function renderPagesNavigationTarget(url, target, props, options, assertSt
1132
1159
  assertStillCurrent();
1133
1160
  const React = (await import("react")).default;
1134
1161
  assertStillCurrent();
1135
- const rawPageProps = props.pageProps;
1136
- const pageProps = isUnknownRecord(rawPageProps) ? rawPageProps : {};
1162
+ const pageProps = Object.assign({}, props.pageProps);
1163
+ props.pageProps = pageProps;
1137
1164
  let element;
1138
1165
  if (AppComponent) element = React.createElement(AppComponent, {
1139
1166
  ...props,
1140
1167
  Component: PageComponent,
1141
- pageProps: rawPageProps,
1142
- router: Router
1168
+ router: singletonRouter
1143
1169
  });
1144
1170
  else element = React.createElement(PageComponent, pageProps);
1145
1171
  const nextData = buildPagesNavigationNextData(target, props);
@@ -1194,7 +1220,7 @@ async function navigateClientData(url, initialTarget, controller, navId, assertS
1194
1220
  };
1195
1221
  const deploymentId = getDeploymentId();
1196
1222
  if (deploymentId) headers[NEXT_DEPLOYMENT_ID_HEADER] = deploymentId;
1197
- res = await (initialTarget.dataKind === "static" && Router.isPreview !== true ? fetchStaticPagesData : dedupedPagesDataFetch)(initialTarget.dataHref, {
1223
+ res = await (initialTarget.dataKind === "static" && singletonRouter.isPreview !== true ? fetchStaticPagesData : dedupedPagesDataFetch)(initialTarget.dataHref, {
1198
1224
  headers,
1199
1225
  signal: controller.signal
1200
1226
  });
@@ -1235,7 +1261,7 @@ async function navigateClientData(url, initialTarget, controller, navId, assertS
1235
1261
  const rawPageProps = props.pageProps;
1236
1262
  const pageProps = isUnknownRecord(rawPageProps) ? rawPageProps : {};
1237
1263
  if (initialTarget.dataKind === "server") evictPagesDataCache(initialTarget.dataHref);
1238
- if (props.__N_PREVIEW === true || Router.isPreview === true) evictPagesDataCache(initialTarget.dataHref);
1264
+ if (props.__N_PREVIEW === true || singletonRouter.isPreview === true) evictPagesDataCache(initialTarget.dataHref);
1239
1265
  const redirectDestination = pageProps.__N_REDIRECT;
1240
1266
  if (typeof redirectDestination === "string") {
1241
1267
  handleDataRedirect(redirectDestination, pageProps.__N_REDIRECT_BASE_PATH, options.mode);
@@ -1285,8 +1311,8 @@ async function navigateClientHtml(url, fetchUrl, controller, navId, assertStillC
1285
1311
  if (!nextDataJson) scheduleHardNavigationAndThrow(url, "Navigation failed: missing __NEXT_DATA__ in response");
1286
1312
  const nextData = parseVinextNextDataJson(nextDataJson);
1287
1313
  const props = nextData.props && typeof nextData.props === "object" ? nextData.props : {};
1288
- const rawPageProps = props.pageProps;
1289
- const pageProps = isUnknownRecord(rawPageProps) ? rawPageProps : {};
1314
+ const pageProps = Object.assign({}, props.pageProps);
1315
+ props.pageProps = pageProps;
1290
1316
  let pageModuleUrl = nextData.__vinext?.pageModuleUrl;
1291
1317
  if (!pageModuleUrl) {
1292
1318
  const moduleMatch = html.match(/import\("([^"]+)"\);\s*\n\s*const PageComponent/);
@@ -1328,8 +1354,7 @@ async function navigateClientHtml(url, fetchUrl, controller, navId, assertStillC
1328
1354
  if (AppComponent) element = React.createElement(AppComponent, {
1329
1355
  ...props,
1330
1356
  Component: PageComponent,
1331
- pageProps: rawPageProps,
1332
- router: Router
1357
+ router: singletonRouter
1333
1358
  });
1334
1359
  else element = React.createElement(PageComponent, pageProps);
1335
1360
  if (pendingRedirectHistoryUrl) {
@@ -1488,6 +1513,7 @@ function buildRouterValue(pathname, query, asPath, isReady, methods) {
1488
1513
  locales,
1489
1514
  defaultLocale,
1490
1515
  domainLocales,
1516
+ isLocaleDomain: typeof window !== "undefined" && domainLocales?.some((domain) => domain.domain === window.location.hostname) === true,
1491
1517
  isReady,
1492
1518
  isPreview: typeof window !== "undefined" ? nextData?.isPreview === true : _ssrState?.isPreview === true,
1493
1519
  isFallback: typeof window !== "undefined" ? nextData?.isFallback === true : _ssrState?.isFallback === true,
@@ -1577,11 +1603,12 @@ async function performNavigation(url, as, options, mode, onStateUpdate) {
1577
1603
  if (typeof window === "undefined") throwNoRouterInstance();
1578
1604
  assertSafeNavigationUrl(resolveUrl(url));
1579
1605
  if (as !== void 0) assertSafeNavigationUrl(String(as));
1606
+ const isHydrationQueryUpdate = options?._h === 1;
1580
1607
  const navigationLocale = resolveTransitionLocale(options?.locale);
1581
- const replaceInheritedLocale = as === void 0 && options?.locale !== void 0 && typeof url !== "string" && url.pathname === void 0 && (url.query !== void 0 && Object.keys(url.query).length > 0 || typeof url.search === "string" && url.search.length > 0 || typeof url.hash === "string" && url.hash.length > 0);
1582
- let resolved = resolveNavigationTarget(url, as, navigationLocale, replaceInheritedLocale);
1583
- let resolvedRoute = applyNavigationLocale(resolveUrl(url), navigationLocale, replaceInheritedLocale);
1584
- if (as === void 0 && (typeof url === "string" && options?._vinextInterpolateDynamicRoute === true || typeof url !== "string" && url.pathname === void 0 && (url.query !== void 0 && Object.keys(url.query).length > 0 || typeof url.search === "string" && url.search.length > 0))) {
1608
+ const replaceInheritedLocale = as === void 0 && options?.locale !== void 0 && typeof url !== "string" && url.pathname === void 0 && (url.query !== null && typeof url.query === "object" && Object.keys(url.query).length > 0 || typeof url.search === "string" && url.search.length > 0 || typeof url.hash === "string" && url.hash.length > 0);
1609
+ let resolved = isHydrationQueryUpdate ? normalizeHydrationNavigationUrl(as ?? resolveUrl(url)) : resolveNavigationTarget(url, as, navigationLocale, replaceInheritedLocale);
1610
+ let resolvedRoute = isHydrationQueryUpdate ? normalizeHydrationNavigationUrl(resolveUrl(url)) : applyNavigationLocale(resolveUrl(url), navigationLocale, replaceInheritedLocale);
1611
+ if (as === void 0 && (typeof url === "string" && options?._vinextInterpolateDynamicRoute === true || typeof url !== "string" && url.pathname === void 0 && (url.query !== null && typeof url.query === "object" && Object.keys(url.query).length > 0 || typeof url.search === "string" && url.search.length > 0))) {
1585
1612
  resolved = interpolateCurrentDynamicRoute(resolved);
1586
1613
  resolvedRoute = interpolateCurrentDynamicRoute(resolvedRoute);
1587
1614
  }
@@ -1602,7 +1629,7 @@ async function performNavigation(url, as, options, mode, onStateUpdate) {
1602
1629
  resolvedRoute = normalizePathTrailingSlash(resolvedRoute, __trailingSlash);
1603
1630
  let interpolatedRoute = resolvedRoute;
1604
1631
  if (resolvedRoute.includes("[")) {
1605
- const projection = interpolateDynamicRouteHref(resolvedRoute, resolved, typeof url === "string" ? void 0 : url.query);
1632
+ const projection = interpolateDynamicRouteHref(resolvedRoute, resolved, typeof url === "string" || !url.query || typeof url.query === "string" ? void 0 : url.query);
1606
1633
  if (projection?.href) {
1607
1634
  interpolatedRoute = projection.href;
1608
1635
  if (as === void 0 && stripHash(resolved).split("?", 1)[0] === projection.routePathname) {
@@ -1618,7 +1645,20 @@ async function performNavigation(url, as, options, mode, onStateUpdate) {
1618
1645
  const hashStr = extractHash(resolved);
1619
1646
  resolved = normalizePathTrailingSlash(`${projection.href.split(/[?#]/, 1)[0]}${searchStr ? `?${searchStr}` : ""}${hashStr}`, __trailingSlash);
1620
1647
  }
1621
- } else interpolatedRoute = resolved;
1648
+ } else {
1649
+ const missingParams = projection ? routePatternParts(projection.routePathname).filter((part) => part.startsWith(":") && !part.endsWith("*")).map((part) => part.slice(1, part.endsWith("+") ? -1 : void 0)).filter((paramName) => {
1650
+ const value = projection.query[paramName];
1651
+ return value === void 0 || value === "" || Array.isArray(value) && value.length === 0;
1652
+ }) : [];
1653
+ const hasExplicitHrefPathname = typeof url === "string" || url.pathname !== void 0;
1654
+ const isMiddlewareMatch = options?.shallow !== true && getPagesMiddlewareDataHref(resolved, __basePath) !== null;
1655
+ if (missingParams.length > 0 && hasExplicitHrefPathname && !isMiddlewareMatch) {
1656
+ const asPathname = stripHash(resolved).split("?", 1)[0];
1657
+ const routePathname = projection?.routePathname ?? stripHash(resolvedRoute).split("?", 1)[0];
1658
+ throw new HrefInterpolationError(asPathname === routePathname ? `The provided \`href\` (${resolvedRoute}) value is missing query values (${missingParams.join(", ")}) to be interpolated properly. Read more: https://nextjs.org/docs/messages/href-interpolation-failed` : `The provided \`as\` value (${asPathname}) is incompatible with the \`href\` value (${routePathname}). Read more: https://nextjs.org/docs/messages/incompatible-href-as`);
1659
+ }
1660
+ interpolatedRoute = resolved;
1661
+ }
1622
1662
  }
1623
1663
  const full = normalizePathTrailingSlash(toBrowserNavigationHref(resolved, window.location.href, __basePath), __trailingSlash);
1624
1664
  const fullRouteUrl = interpolatedRoute !== resolved ? normalizePathTrailingSlash(toBrowserNavigationHref(interpolatedRoute, window.location.href, __basePath), __trailingSlash) : full;
@@ -1742,7 +1782,7 @@ async function prefetchUrl(url, as) {
1742
1782
  function useRouter() {
1743
1783
  const router = useContext(RouterContext);
1744
1784
  if (router) return router;
1745
- if (typeof window !== "undefined" && window.__VINEXT_PAGE_LOADERS__ !== void 0) return Router;
1785
+ if (typeof window !== "undefined" && window.__VINEXT_PAGE_LOADERS__ !== void 0) return singletonRouter;
1746
1786
  throw new Error("NextRouter was not mounted. https://nextjs.org/docs/messages/next-router-not-mounted");
1747
1787
  }
1748
1788
  function PagesRouterProvider({ children }) {
@@ -1767,12 +1807,13 @@ function PagesRouterProvider({ children }) {
1767
1807
  };
1768
1808
  }, []);
1769
1809
  const router = useMemo(() => buildRouterValue(pathname, query, asPath, isReady, {
1770
- push: Router.push,
1771
- replace: Router.replace,
1772
- back: Router.back,
1773
- reload: Router.reload,
1774
- prefetch: Router.prefetch,
1775
- beforePopState: Router.beforePopState
1810
+ push: singletonRouter.push,
1811
+ replace: singletonRouter.replace,
1812
+ back: singletonRouter.back,
1813
+ forward: singletonRouter.forward,
1814
+ reload: singletonRouter.reload,
1815
+ prefetch: singletonRouter.prefetch,
1816
+ beforePopState: singletonRouter.beforePopState
1776
1817
  }), [
1777
1818
  pathname,
1778
1819
  query,
@@ -1782,23 +1823,23 @@ function PagesRouterProvider({ children }) {
1782
1823
  const appRouter = useMemo(() => ({
1783
1824
  bfcacheId: "0",
1784
1825
  back() {
1785
- Router.back();
1826
+ singletonRouter.back();
1786
1827
  },
1787
1828
  forward() {
1788
1829
  if (typeof window === "undefined") throwNoRouterInstance();
1789
1830
  window.history.forward();
1790
1831
  },
1791
1832
  refresh() {
1792
- Router.reload();
1833
+ singletonRouter.reload();
1793
1834
  },
1794
1835
  push(href, options) {
1795
- Router.push(href, void 0, { scroll: options?.scroll });
1836
+ singletonRouter.push(href, void 0, { scroll: options?.scroll });
1796
1837
  },
1797
1838
  replace(href, options) {
1798
- Router.replace(href, void 0, { scroll: options?.scroll });
1839
+ singletonRouter.replace(href, void 0, { scroll: options?.scroll });
1799
1840
  },
1800
1841
  prefetch(href) {
1801
- Router.prefetch(href);
1842
+ singletonRouter.prefetch(href);
1802
1843
  }
1803
1844
  }), []);
1804
1845
  const content = createElement(RouterContext.Provider, { value: router }, createElement(Fragment, null, children, createElement(PagesRouterHydrationMarker)));
@@ -1941,6 +1982,11 @@ function withRouter(ComposedComponent) {
1941
1982
  return WithRouterWrapper;
1942
1983
  }
1943
1984
  const RouterMethods = {
1985
+ router: null,
1986
+ readyCallbacks: [],
1987
+ ready(callback) {
1988
+ callback();
1989
+ },
1944
1990
  /** See `_components` comment above for the dual role this map plays. */
1945
1991
  components: getPagesRouterComponentsMap(),
1946
1992
  sdc: getPagesStaticDataCache(),
@@ -1960,6 +2006,10 @@ const RouterMethods = {
1960
2006
  if (typeof window === "undefined") throwNoRouterInstance();
1961
2007
  window.history.back();
1962
2008
  },
2009
+ forward: () => {
2010
+ if (typeof window === "undefined") throwNoRouterInstance();
2011
+ window.history.forward();
2012
+ },
1963
2013
  reload: () => {
1964
2014
  if (typeof window === "undefined") throwNoRouterInstance();
1965
2015
  window.location.reload();
@@ -1974,7 +2024,7 @@ const RouterMethods = {
1974
2024
  },
1975
2025
  events: routerEvents
1976
2026
  };
1977
- const Router = Object.defineProperties(RouterMethods, {
2027
+ const singletonRouter = Object.defineProperties(RouterMethods, {
1978
2028
  pathname: {
1979
2029
  enumerable: true,
1980
2030
  get() {
@@ -2034,6 +2084,14 @@ const Router = Object.defineProperties(RouterMethods, {
2034
2084
  return window.__NEXT_DATA__?.domainLocales;
2035
2085
  }
2036
2086
  },
2087
+ isLocaleDomain: {
2088
+ enumerable: true,
2089
+ get() {
2090
+ const domainLocales = typeof window === "undefined" ? _getSSRContext()?.domainLocales : window.__NEXT_DATA__?.domainLocales;
2091
+ if (!domainLocales || typeof window === "undefined") return false;
2092
+ return domainLocales.some((domain) => domain.domain === window.location.hostname);
2093
+ }
2094
+ },
2037
2095
  isReady: {
2038
2096
  enumerable: true,
2039
2097
  get() {
@@ -2055,7 +2113,7 @@ const Router = Object.defineProperties(RouterMethods, {
2055
2113
  }
2056
2114
  }
2057
2115
  });
2058
- routerRuntimeState.publicRouter = Router;
2116
+ routerRuntimeState.publicRouter = singletonRouter;
2059
2117
  const deprecatedRouterEvents = [
2060
2118
  "routeChangeStart",
2061
2119
  "beforeHistoryChange",
@@ -2069,7 +2127,7 @@ if (!routerRuntimeState.deprecatedEventBridgeInstalled) {
2069
2127
  for (const event of deprecatedRouterEvents) {
2070
2128
  const eventField = `on${event.charAt(0).toUpperCase()}${event.substring(1)}`;
2071
2129
  routerEvents.on(event, (...args) => {
2072
- const handler = (routerRuntimeState.publicRouter ?? Router)[eventField];
2130
+ const handler = (routerRuntimeState.publicRouter ?? singletonRouter)[eventField];
2073
2131
  if (typeof handler === "function") try {
2074
2132
  handler(...args);
2075
2133
  } catch (err) {
@@ -2081,9 +2139,87 @@ if (!routerRuntimeState.deprecatedEventBridgeInstalled) {
2081
2139
  }
2082
2140
  if (typeof window !== "undefined") {
2083
2141
  installPagesRouterRuntime();
2084
- installWindowNext({ router: Router });
2142
+ installWindowNext({ router: singletonRouter });
2085
2143
  }
2086
2144
  const _PAGES_NAVIGATION_ACCESSOR_KEY = Symbol.for("vinext.navigation.pagesNavigationContextAccessor");
2087
2145
  globalThis[_PAGES_NAVIGATION_ACCESSOR_KEY] = getPagesNavigationContext;
2146
+ /**
2147
+ * Constructible named export matching `next/router`'s Router class surface.
2148
+ * Vinext owns one browser history runtime, so instances delegate to that
2149
+ * shared runtime while preserving the class/static-events API used by apps.
2150
+ */
2151
+ var Router = class {
2152
+ static events = routerEvents;
2153
+ constructor(..._args) {}
2154
+ get route() {
2155
+ return singletonRouter.route;
2156
+ }
2157
+ get pathname() {
2158
+ return singletonRouter.pathname;
2159
+ }
2160
+ get query() {
2161
+ return singletonRouter.query;
2162
+ }
2163
+ get asPath() {
2164
+ return singletonRouter.asPath;
2165
+ }
2166
+ get basePath() {
2167
+ return singletonRouter.basePath;
2168
+ }
2169
+ get locale() {
2170
+ return singletonRouter.locale;
2171
+ }
2172
+ get locales() {
2173
+ return singletonRouter.locales;
2174
+ }
2175
+ get defaultLocale() {
2176
+ return singletonRouter.defaultLocale;
2177
+ }
2178
+ get domainLocales() {
2179
+ return singletonRouter.domainLocales;
2180
+ }
2181
+ get isLocaleDomain() {
2182
+ return singletonRouter.isLocaleDomain;
2183
+ }
2184
+ get isReady() {
2185
+ return singletonRouter.isReady;
2186
+ }
2187
+ get isPreview() {
2188
+ return singletonRouter.isPreview;
2189
+ }
2190
+ get isFallback() {
2191
+ return singletonRouter.isFallback;
2192
+ }
2193
+ get events() {
2194
+ return singletonRouter.events;
2195
+ }
2196
+ get components() {
2197
+ return singletonRouter.components;
2198
+ }
2199
+ get sdc() {
2200
+ return singletonRouter.sdc;
2201
+ }
2202
+ push(url, as, options) {
2203
+ return singletonRouter.push(url, as, options);
2204
+ }
2205
+ replace(url, as, options) {
2206
+ return singletonRouter.replace(url, as, options);
2207
+ }
2208
+ reload() {
2209
+ singletonRouter.reload();
2210
+ }
2211
+ back() {
2212
+ singletonRouter.back();
2213
+ }
2214
+ forward() {
2215
+ singletonRouter.forward();
2216
+ }
2217
+ prefetch(url, as) {
2218
+ return singletonRouter.prefetch(url, as);
2219
+ }
2220
+ beforePopState(cb) {
2221
+ singletonRouter.beforePopState(cb);
2222
+ }
2223
+ };
2088
2224
  //#endregion
2089
- export { initializePagesRouterReadyFromNextData as _initializePagesRouterReadyFromNextData, markPagesRouterReady as _markPagesRouterReady, _registerRouterStateAccessors, applyNavigationLocale, Router as default, getPagesNavigationContext, getPagesNavigationIsReadyFromSerializedState, isExternalUrl, isHashOnlyChange, setSSRContext, useRouter, withRouter, wrapWithRouterContext };
2225
+ export { Router, initializePagesRouterReadyFromNextData as _initializePagesRouterReadyFromNextData, markPagesRouterReady as _markPagesRouterReady, _registerRouterStateAccessors, applyNavigationLocale, singletonRouter as default, getPagesNavigationContext, getPagesNavigationIsReadyFromSerializedState, isExternalUrl, isHashOnlyChange, setSSRContext, useRouter, withRouter, wrapWithRouterContext };
@@ -1,21 +1,18 @@
1
1
  import React from "react";
2
2
 
3
3
  //#region src/shims/script.d.ts
4
- type ScriptProps = {
4
+ type ScriptProps = React.ScriptHTMLAttributes<HTMLScriptElement> & {
5
5
  /** Script source URL */src?: string; /** Loading strategy. Default: "afterInteractive" */
6
6
  strategy?: "beforeInteractive" | "afterInteractive" | "lazyOnload" | "worker"; /** Unique identifier for the script */
7
7
  id?: string; /** Called when the script has loaded */
8
- onLoad?: (e: Event) => void; /** Called when the script is ready (after load, and on every re-render if already loaded) */
8
+ onLoad?: (e: unknown) => void; /** Called when the script is ready (after load, and on every re-render if already loaded) */
9
9
  onReady?: () => void; /** Called on script load error */
10
- onError?: (e: Event) => void; /** Inline script content */
11
- children?: React.ReactNode; /** Dangerous inner HTML */
12
- dangerouslySetInnerHTML?: {
13
- __html: string;
14
- }; /** Script type attribute */
10
+ onError?: (e: unknown) => void; /** Inline script content */
11
+ children?: React.ReactNode; /** Script type attribute */
15
12
  type?: string; /** Async attribute */
16
13
  async?: boolean; /** Defer attribute */
17
14
  defer?: boolean; /** Crossorigin attribute */
18
- crossOrigin?: string; /** Nonce for CSP */
15
+ crossOrigin?: React.ScriptHTMLAttributes<HTMLScriptElement>["crossOrigin"]; /** Nonce for CSP */
19
16
  nonce?: string; /** Integrity hash */
20
17
  integrity?: string;
21
18
  /**
@@ -27,8 +24,7 @@ type ScriptProps = {
27
24
  * `.nextjs-ref/packages/next/src/client/script.tsx` (`insertStylesheets`
28
25
  * and the `appDir` block).
29
26
  */
30
- stylesheets?: string[]; /** Additional attributes */
31
- [key: string]: unknown;
27
+ stylesheets?: string[];
32
28
  };
33
29
  /**
34
30
  * Load a script imperatively (outside of React).
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { escapeInlineContent } from "./head.js";
3
2
  import { useScriptNonce } from "./script-nonce-context.js";
4
3
  import { hasAppNavigationRuntimeBootstrap } from "../client/navigation-runtime.js";
5
4
  import { useBeforeInteractiveRegister } from "./before-interactive-context.js";
5
+ import { escapeInlineContent } from "./head.js";
6
6
  import React, { useEffect, useRef } from "react";
7
7
  import * as ReactDOM from "react-dom";
8
8
  //#region src/shims/script.tsx
@@ -78,9 +78,12 @@ function buildBeforeInteractiveScriptProps(options) {
78
78
  if (options.src) scriptProps.src = options.src;
79
79
  if (options.id) scriptProps.id = options.id;
80
80
  if (options.resolvedNonce) scriptProps.nonce = options.resolvedNonce;
81
- if (options.dangerouslySetInnerHTML) scriptProps.dangerouslySetInnerHTML = { __html: escapeInlineContent(options.dangerouslySetInnerHTML.__html, "script") };
81
+ if (options.dangerouslySetInnerHTML) scriptProps.dangerouslySetInnerHTML = { __html: escapeInlineContent(stringifyInlineContent(options.dangerouslySetInnerHTML.__html), "script") };
82
82
  return scriptProps;
83
83
  }
84
+ function stringifyInlineContent(value) {
85
+ return String(value);
86
+ }
84
87
  /**
85
88
  * Extract the inline script content for a `beforeInteractive` Script element
86
89
  * with no `src`. Returns `null` when the element has neither a string-shaped
@@ -93,7 +96,7 @@ function buildBeforeInteractiveScriptProps(options) {
93
96
  * to the emit point so the rule is obvious at the boundary).
94
97
  */
95
98
  function extractBeforeInteractiveInlineContent(children, dangerouslySetInnerHTML) {
96
- if (dangerouslySetInnerHTML && typeof dangerouslySetInnerHTML.__html === "string" && dangerouslySetInnerHTML.__html.length > 0) return dangerouslySetInnerHTML.__html;
99
+ if (dangerouslySetInnerHTML && stringifyInlineContent(dangerouslySetInnerHTML.__html).length > 0) return stringifyInlineContent(dangerouslySetInnerHTML.__html);
97
100
  if (typeof children === "string" && children.length > 0) return children;
98
101
  if (Array.isArray(children) && children.every((c) => typeof c === "string")) {
99
102
  const joined = children.join("");
@@ -220,7 +223,7 @@ function loadClientScript(props, options) {
220
223
  onReady?.();
221
224
  };
222
225
  if (dangerouslySetInnerHTML?.__html) {
223
- el.innerHTML = dangerouslySetInnerHTML.__html;
226
+ el.innerHTML = stringifyInlineContent(dangerouslySetInnerHTML.__html);
224
227
  markLoaded();
225
228
  } else if (children && typeof children === "string") {
226
229
  el.textContent = children;