vinext 1.2.1 → 1.3.0

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 (212) hide show
  1. package/README.md +12 -9
  2. package/dist/build/client-build-config.d.ts +64 -3
  3. package/dist/build/client-build-config.js +131 -4
  4. package/dist/build/client-reference-groups.d.ts +163 -0
  5. package/dist/build/client-reference-groups.js +534 -0
  6. package/dist/build/module-dependency-cache.d.ts +31 -0
  7. package/dist/build/module-dependency-cache.js +51 -1
  8. package/dist/build/next-client-runtime-manifests.d.ts +10 -1
  9. package/dist/build/next-client-runtime-manifests.js +19 -4
  10. package/dist/build/nitro-public-files.d.ts +24 -0
  11. package/dist/build/nitro-public-files.js +60 -0
  12. package/dist/build/pages-client-assets-module.js +1 -1
  13. package/dist/build/prerender-paths.js +5 -2
  14. package/dist/build/server-actions-encryption-key.d.ts +23 -0
  15. package/dist/build/server-actions-encryption-key.js +101 -0
  16. package/dist/build/ssr-manifest.d.ts +3 -0
  17. package/dist/build/ssr-manifest.js +10 -1
  18. package/dist/client/client-rewrite-params.d.ts +9 -0
  19. package/dist/client/client-rewrite-params.js +20 -0
  20. package/dist/client/dev-error-overlay.js +2 -1
  21. package/dist/client/navigation-runtime.d.ts +25 -2
  22. package/dist/client/navigation-runtime.js +42 -11
  23. package/dist/client/vinext-next-data.d.ts +0 -1
  24. package/dist/config/config-matchers.d.ts +15 -40
  25. package/dist/config/config-matchers.js +183 -255
  26. package/dist/config/config-source.d.ts +34 -0
  27. package/dist/config/config-source.js +141 -0
  28. package/dist/config/header-params.d.ts +29 -0
  29. package/dist/config/header-params.js +106 -0
  30. package/dist/config/next-config.d.ts +7 -5
  31. package/dist/config/next-config.js +120 -7
  32. package/dist/entries/app-browser-entry.d.ts +14 -1
  33. package/dist/entries/app-browser-entry.js +26 -36
  34. package/dist/entries/app-rsc-entry.d.ts +2 -0
  35. package/dist/entries/app-rsc-entry.js +92 -57
  36. package/dist/entries/app-rsc-manifest.d.ts +10 -0
  37. package/dist/entries/app-rsc-manifest.js +20 -1
  38. package/dist/entries/app-ssr-entry.d.ts +4 -1
  39. package/dist/entries/app-ssr-entry.js +9 -2
  40. package/dist/entries/pages-client-entry.d.ts +1 -0
  41. package/dist/entries/pages-client-entry.js +6 -6
  42. package/dist/entries/pages-server-entry.js +17 -14
  43. package/dist/index.d.ts +11 -0
  44. package/dist/index.js +239 -83
  45. package/dist/init.js +17 -0
  46. package/dist/plugins/optimize-imports.d.ts +25 -2
  47. package/dist/plugins/optimize-imports.js +106 -20
  48. package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
  49. package/dist/plugins/rsc-client-reference-loaders.js +336 -18
  50. package/dist/plugins/use-cache-callable.d.ts +5 -0
  51. package/dist/plugins/use-cache-callable.js +30 -8
  52. package/dist/plugins/worker-image-imports.d.ts +1 -0
  53. package/dist/plugins/worker-image-imports.js +1 -1
  54. package/dist/routing/app-route-graph.d.ts +1 -1
  55. package/dist/routing/browser-route-manifest.d.ts +43 -0
  56. package/dist/routing/browser-route-manifest.js +195 -0
  57. package/dist/routing/hashed-route-patterns.d.ts +4 -0
  58. package/dist/routing/hashed-route-patterns.js +22 -0
  59. package/dist/routing/optimistic-route-trie.d.ts +27 -0
  60. package/dist/routing/optimistic-route-trie.js +102 -0
  61. package/dist/routing/route-validation.d.ts +6 -1
  62. package/dist/routing/route-validation.js +26 -10
  63. package/dist/server/app-action-forwarding.d.ts +8 -0
  64. package/dist/server/app-action-forwarding.js +15 -1
  65. package/dist/server/app-browser-entry.js +147 -60
  66. package/dist/server/app-browser-error.d.ts +3 -1
  67. package/dist/server/app-browser-error.js +7 -2
  68. package/dist/server/app-browser-interception-context.d.ts +2 -2
  69. package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
  70. package/dist/server/app-browser-mpa-navigation.js +6 -5
  71. package/dist/server/app-browser-navigation-controller.d.ts +17 -6
  72. package/dist/server/app-browser-navigation-controller.js +88 -26
  73. package/dist/server/app-browser-state.d.ts +2 -2
  74. package/dist/server/app-browser-visible-commit.d.ts +4 -4
  75. package/dist/server/app-client-reference-preloader.d.ts +23 -0
  76. package/dist/server/app-client-reference-preloader.js +30 -7
  77. package/dist/server/app-fallback-renderer.js +2 -1
  78. package/dist/server/app-middleware.d.ts +6 -0
  79. package/dist/server/app-middleware.js +8 -10
  80. package/dist/server/app-optimistic-routing.d.ts +8 -10
  81. package/dist/server/app-optimistic-routing.js +4 -95
  82. package/dist/server/app-page-boundary-render.js +8 -1
  83. package/dist/server/app-page-cache-render.js +1 -0
  84. package/dist/server/app-page-dispatch.js +2 -0
  85. package/dist/server/app-page-render.js +3 -1
  86. package/dist/server/app-page-rsc-render-status.d.ts +1 -0
  87. package/dist/server/app-page-rsc-render-status.js +1 -0
  88. package/dist/server/app-page-search-params-observation.d.ts +1 -4
  89. package/dist/server/app-page-search-params-observation.js +8 -10
  90. package/dist/server/app-page-stream.d.ts +7 -0
  91. package/dist/server/app-page-stream.js +1 -0
  92. package/dist/server/app-pages-bridge.d.ts +2 -1
  93. package/dist/server/app-pages-bridge.js +11 -7
  94. package/dist/server/app-prerender-static-params.js +3 -2
  95. package/dist/server/app-render-dependency.js +42 -2
  96. package/dist/server/app-request-stage-independent-entry.js +2 -2
  97. package/dist/server/app-response-stage-entry.js +3 -3
  98. package/dist/server/app-route-handler-dispatch.js +3 -1
  99. package/dist/server/app-route-handler-execution.d.ts +2 -0
  100. package/dist/server/app-route-handler-execution.js +9 -2
  101. package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
  102. package/dist/server/app-route-handler-middleware-context.js +3 -3
  103. package/dist/server/app-route-handler-response.d.ts +2 -1
  104. package/dist/server/app-route-handler-response.js +2 -2
  105. package/dist/server/app-route-handler-runtime.d.ts +2 -0
  106. package/dist/server/app-route-handler-runtime.js +20 -3
  107. package/dist/server/app-route-module-loader.js +7 -6
  108. package/dist/server/app-route-tree.d.ts +20 -0
  109. package/dist/server/app-route-tree.js +18 -0
  110. package/dist/server/app-router-entry.js +2 -2
  111. package/dist/server/app-rsc-combined-handler.js +8 -1
  112. package/dist/server/app-rsc-errors.d.ts +7 -0
  113. package/dist/server/app-rsc-errors.js +9 -2
  114. package/dist/server/app-rsc-handler.d.ts +4 -1
  115. package/dist/server/app-rsc-handler.js +146 -130
  116. package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
  117. package/dist/server/app-rsc-response-finalizer.js +4 -1
  118. package/dist/server/app-rsc-response-stage.js +3 -1
  119. package/dist/server/app-rsc-route-matching.d.ts +1 -0
  120. package/dist/server/app-rsc-route-matching.js +1 -1
  121. package/dist/server/app-server-action-execution.d.ts +23 -6
  122. package/dist/server/app-server-action-execution.js +50 -56
  123. package/dist/server/app-ssr-entry.d.ts +6 -0
  124. package/dist/server/app-ssr-entry.js +16 -7
  125. package/dist/server/app-ssr-stream.d.ts +7 -0
  126. package/dist/server/app-ssr-stream.js +13 -1
  127. package/dist/server/config-headers.js +12 -3
  128. package/dist/server/isolate-shared-promise.d.ts +10 -0
  129. package/dist/server/isolate-shared-promise.js +33 -0
  130. package/dist/server/isr-cache.js +3 -2
  131. package/dist/server/middleware-matcher-pattern.d.ts +0 -1
  132. package/dist/server/middleware-matcher-pattern.js +11 -140
  133. package/dist/server/middleware-matcher.js +5 -6
  134. package/dist/server/middleware-response-headers.d.ts +31 -0
  135. package/dist/server/middleware-response-headers.js +57 -1
  136. package/dist/server/middleware-runtime.js +26 -13
  137. package/dist/server/navigation-planner.d.ts +2 -2
  138. package/dist/server/nitro-public-files-plugin.d.ts +38 -0
  139. package/dist/server/nitro-public-files-plugin.js +106 -0
  140. package/dist/server/nitro-public-files.d.ts +21 -0
  141. package/dist/server/nitro-public-files.js +39 -0
  142. package/dist/server/pages-asset-tags.d.ts +5 -0
  143. package/dist/server/pages-asset-tags.js +9 -2
  144. package/dist/server/pages-client-assets.d.ts +4 -1
  145. package/dist/server/pages-i18n.d.ts +18 -0
  146. package/dist/server/pages-i18n.js +18 -2
  147. package/dist/server/pages-node-compat.d.ts +5 -3
  148. package/dist/server/pages-node-compat.js +35 -16
  149. package/dist/server/pages-request-pipeline.d.ts +6 -1
  150. package/dist/server/pages-request-pipeline.js +31 -35
  151. package/dist/server/pages-request-stage-entry.js +16 -6
  152. package/dist/server/pages-response-stage-entry.js +1 -1
  153. package/dist/server/pages-revalidate.js +1 -0
  154. package/dist/server/pages-router-entry.js +1 -1
  155. package/dist/server/prod-server.d.ts +2 -2
  156. package/dist/server/prod-server.js +71 -33
  157. package/dist/server/proxy-trust.d.ts +6 -0
  158. package/dist/server/proxy-trust.js +12 -6
  159. package/dist/server/request-pipeline.d.ts +5 -0
  160. package/dist/server/request-pipeline.js +12 -1
  161. package/dist/server/server-reference-loader.js +10 -1
  162. package/dist/server/static-file-cache.js +15 -3
  163. package/dist/server/worker-utils.js +1 -1
  164. package/dist/shims/cache-handler.js +3 -2
  165. package/dist/shims/cache-request-state.d.ts +40 -3
  166. package/dist/shims/cache-request-state.js +70 -5
  167. package/dist/shims/cache-runtime.js +47 -19
  168. package/dist/shims/cache.d.ts +2 -2
  169. package/dist/shims/cache.js +17 -8
  170. package/dist/shims/cdn-purge-routes.d.ts +24 -0
  171. package/dist/shims/cdn-purge-routes.js +77 -0
  172. package/dist/shims/dynamic.js +17 -4
  173. package/dist/shims/form.js +8 -3
  174. package/dist/shims/image-props.d.ts +93 -0
  175. package/dist/shims/image-props.js +323 -0
  176. package/dist/shims/image.d.ts +4 -18
  177. package/dist/shims/image.js +4 -319
  178. package/dist/shims/internal/headers-state.d.ts +7 -0
  179. package/dist/shims/internal/headers-state.js +14 -2
  180. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
  181. package/dist/shims/internal/hybrid-client-route-owner-direct.js +31 -14
  182. package/dist/shims/internal/hybrid-client-route-owner.js +8 -8
  183. package/dist/shims/link.js +5 -3
  184. package/dist/shims/navigation.d.ts +1 -1
  185. package/dist/shims/navigation.js +17 -5
  186. package/dist/shims/og.js +35 -10
  187. package/dist/shims/request-context.d.ts +13 -0
  188. package/dist/shims/router.js +19 -40
  189. package/dist/shims/server.d.ts +31 -4
  190. package/dist/shims/server.js +58 -10
  191. package/dist/shims/thenable-params.d.ts +6 -1
  192. package/dist/shims/thenable-params.js +11 -2
  193. package/dist/shims/unified-request-context.d.ts +5 -0
  194. package/dist/shims/unified-request-context.js +2 -0
  195. package/dist/utils/asset-prefix.d.ts +7 -0
  196. package/dist/utils/asset-prefix.js +10 -1
  197. package/dist/utils/client-build-manifest.js +12 -5
  198. package/dist/utils/client-runtime-metadata.d.ts +1 -0
  199. package/dist/utils/client-runtime-metadata.js +15 -2
  200. package/dist/utils/lazy-chunks.d.ts +4 -0
  201. package/dist/utils/manifest-paths.d.ts +14 -0
  202. package/dist/utils/manifest-paths.js +22 -1
  203. package/dist/utils/path-to-regexp.d.ts +21 -0
  204. package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
  205. package/dist/utils/plugin-react-version.d.ts +15 -0
  206. package/dist/utils/plugin-react-version.js +64 -0
  207. package/dist/utils/public-routes.d.ts +2 -0
  208. package/dist/utils/public-routes.js +18 -7
  209. package/package.json +1 -1
  210. package/dist/server/middleware-path-to-regexp.d.ts +0 -13
  211. package/dist/utils/regex-safety.d.ts +0 -17
  212. package/dist/utils/regex-safety.js +0 -789
@@ -1,6 +1,7 @@
1
1
  import { stripBasePath } from "../utils/base-path.js";
2
2
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
3
3
  import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders } from "./cache-control.js";
4
+ import { createArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
4
5
  import { AppElementsWire } from "./app-elements-wire.js";
5
6
  import "./app-elements.js";
6
7
  import DefaultGlobalError from "../shims/default-global-error.js";
@@ -96,14 +97,19 @@ function createAppPageBoundaryRscPayload(options) {
96
97
  const routeId = AppElementsWire.encodeRouteId(options.pathname, null);
97
98
  const layoutEntries = createAppPageBoundaryLayoutEntries(options.route, options.layoutModules);
98
99
  const sourcePageSegments = options.sourcePageSegments ?? options.route?.routeSegments;
100
+ const rootLayoutTreePath = layoutEntries[0]?.treePath ?? null;
99
101
  return {
100
102
  ...AppElementsWire.createMetadataEntries({
101
103
  interceptionContext: null,
102
104
  layoutIds: layoutEntries.map((entry) => entry.id),
103
- rootLayoutTreePath: layoutEntries[0]?.treePath ?? null,
105
+ rootLayoutTreePath,
104
106
  routeId,
105
107
  sourcePage: sourcePageSegments ? createAppPageSourcePage(sourcePageSegments) : null
106
108
  }),
109
+ [AppElementsWire.keys.artifactCompatibility]: createArtifactCompatibilityEnvelope({
110
+ deploymentVersion: process.env.__VINEXT_BUILD_ID ?? null,
111
+ rootBoundaryId: rootLayoutTreePath
112
+ }),
107
113
  [routeId]: options.element
108
114
  };
109
115
  }
@@ -157,6 +163,7 @@ async function renderAppPageBoundaryElementResponse(options) {
157
163
  isCacheCandidate: options.isCacheCandidate,
158
164
  isEdgeRuntime: options.isEdgeRuntime,
159
165
  middlewareHeaders: options.middlewareContext.headers,
166
+ preloadRoutePattern: options.route ? options.route.pattern : null,
160
167
  navigationContext: options.getNavigationContext() ?? {
161
168
  pathname,
162
169
  searchParams: requestUrl.searchParams,
@@ -43,6 +43,7 @@ async function renderAppPageCacheArtifactsImpl(options, renderSpan) {
43
43
  mirrorNextFlight: options.mirrorNextFlight,
44
44
  isStaticGeneration: true,
45
45
  isForceStatic: options.isForceStatic,
46
+ preloadRoutePattern: options.route.pattern,
46
47
  onSsrError: options.onSsrError && options.isCapturedRscError ? createAppPageSsrErrorHandler((error) => {
47
48
  recordAppPageRenderError(renderSpan, error);
48
49
  return options.onSsrError?.(error);
@@ -149,6 +149,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
149
149
  currentFetchRevalidate: options.currentFetchRevalidate ?? null,
150
150
  currentForceDynamicFetchDefault: options.dynamicConfig === "force-dynamic",
151
151
  executionContext: getRequestExecutionContext(),
152
+ rootParams: options.rootParams ?? null,
152
153
  unstableCacheRevalidation: "foreground"
153
154
  });
154
155
  const revalidation = runWithRequestContext(requestContext, () => runInWorkStoreScope(async () => {
@@ -388,6 +389,7 @@ async function dispatchAppPageInner(options) {
388
389
  draftModeSecret: options.draftModeSecret,
389
390
  dynamicConfig: revalidationDynamicConfig,
390
391
  params: revalidationTarget.navigationParams,
392
+ rootParams: options.rootParams,
391
393
  routePattern: revalidationTarget.route.pattern,
392
394
  routeSegments: revalidationTarget.route.routeSegments,
393
395
  setNavigationContext: options.setNavigationContext
@@ -497,7 +497,8 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
497
497
  isForceStatic: options.isForceStatic,
498
498
  loadSsrHandler: options.loadSsrHandler,
499
499
  navigationContext: options.getNavigationContext(),
500
- rootParams: options.rootParams
500
+ rootParams: options.rootParams,
501
+ routePattern: options.routePattern
501
502
  }) : void 0;
502
503
  let requestCacheLifeForPrerender = null;
503
504
  if (shouldWaitForAllReady) await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);
@@ -812,6 +813,7 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
812
813
  reactMaxHeadersLength: options.reactMaxHeadersLength,
813
814
  rootParams: options.rootParams,
814
815
  pprFallbackShellSignal: options.pprFallbackShellSignal,
816
+ preloadRoutePattern: options.routePattern,
815
817
  formState: options.formState ?? null,
816
818
  rscStream: rscForResponse,
817
819
  scriptNonce: options.scriptNonce,
@@ -31,6 +31,7 @@ type CreateAppPageRscRenderStatusResolverOptions = {
31
31
  loadSsrHandler: () => Promise<AppPageSsrHandler>;
32
32
  navigationContext: NavigationContext | null;
33
33
  rootParams?: RootParams;
34
+ routePattern: string;
34
35
  };
35
36
  /**
36
37
  * Resolve an RSC-only render's status once its Flight payload is complete.
@@ -28,6 +28,7 @@ async function resolveAppPageRscRenderStatus(options) {
28
28
  isForceStatic: options.isForceStatic,
29
29
  isStaticGeneration: true,
30
30
  onSsrError: () => void 0,
31
+ preloadRoutePattern: options.routePattern,
31
32
  rootParams: options.rootParams
32
33
  });
33
34
  } catch (error) {
@@ -1,15 +1,12 @@
1
1
  import { ThenableParams, ThenableParamsObserver } from "../shims/thenable-params.js";
2
2
  import { AppPageSearchParams } from "./app-page-head.js";
3
3
  //#region src/server/app-page-search-params-observation.d.ts
4
- type AppPageSearchParamsObservationOptions = {
5
- observeReactPromiseStatus?: boolean;
6
- };
7
4
  type ClientPageSsrSearchParamsOptions = {
8
5
  isForceStatic?: boolean;
9
6
  isPprFallbackShell?: boolean;
10
7
  };
11
8
  export declare function createAppPageSearchParamsObserver(): ThenableParamsObserver;
12
- export declare function makeObservedAppPageSearchParamsThenable(pageSearchParams: AppPageSearchParams, options?: AppPageSearchParamsObservationOptions): ThenableParams<AppPageSearchParams>;
9
+ export declare function makeObservedAppPageSearchParamsThenable(pageSearchParams: AppPageSearchParams): ThenableParams<AppPageSearchParams>;
13
10
  /**
14
11
  * The `searchParams` a client page receives during SSR (see
15
12
  * `shims/client-page-root.tsx`). Its RSC payload carries no query, so this is
@@ -9,17 +9,15 @@ function markAppPageSearchParamsAccess() {
9
9
  markRenderRequestApiUsage("searchParams");
10
10
  }
11
11
  function createAppPageSearchParamsObserver() {
12
- return { observeParamAccess() {
13
- markAppPageSearchParamsAccess();
14
- } };
12
+ return {
13
+ observeParamAccess() {
14
+ markAppPageSearchParamsAccess();
15
+ },
16
+ observeThenRead: throwIfStaticGenerationAccessError
17
+ };
15
18
  }
16
- function makeObservedAppPageSearchParamsThenable(pageSearchParams, options = {}) {
17
- const observer = createAppPageSearchParamsObserver();
18
- if (options.observeReactPromiseStatus === true) return makeThenableParams(pageSearchParams, {
19
- ...observer,
20
- observeReactPromiseStatus: true
21
- });
22
- return makeThenableParams(pageSearchParams, observer);
19
+ function makeObservedAppPageSearchParamsThenable(pageSearchParams) {
20
+ return makeThenableParams(pageSearchParams, createAppPageSearchParamsObserver());
23
21
  }
24
22
  /**
25
23
  * The `searchParams` a client page receives during SSR (see
@@ -71,6 +71,8 @@ export type AppPageSsrHandler = {
71
71
  };
72
72
  /** Abort signal for a build-time PPR fallback-shell static render. */
73
73
  pprFallbackShellSignal?: AbortSignal;
74
+ /** Route whose client references load before the render; null for none. */
75
+ preloadRoutePattern?: string | null;
74
76
  /** When true, wait for the full React tree before emitting bytes. */
75
77
  waitForAllReady?: boolean;
76
78
  /** Render is producing a static/prerendered HTML artifact. */
@@ -128,6 +130,11 @@ type RenderAppPageHtmlStreamOptions = {
128
130
  };
129
131
  /** Abort signal for a build-time PPR fallback-shell static render. */
130
132
  pprFallbackShellSignal?: AbortSignal;
133
+ /**
134
+ * Route whose client references load before the render, or null for a
135
+ * render without a route. Undefined loads every client reference.
136
+ */
137
+ preloadRoutePattern?: string | null;
131
138
  /** When true, wait for the full React tree before emitting bytes. */
132
139
  waitForAllReady?: boolean;
133
140
  /** Render is producing a static/prerendered HTML artifact. */
@@ -78,6 +78,7 @@ async function renderAppPageHtmlStream(options) {
78
78
  sideStream: options.sideStream,
79
79
  capturedRscDataRef: options.capturedRscDataRef,
80
80
  pprFallbackShellSignal: options.pprFallbackShellSignal,
81
+ preloadRoutePattern: options.preloadRoutePattern,
81
82
  waitForAllReady: options.waitForAllReady,
82
83
  isStaticGeneration: options.isStaticGeneration,
83
84
  isForceStatic: options.isForceStatic,
@@ -1,4 +1,5 @@
1
1
  import { AppMiddlewareContext } from "./app-middleware.js";
2
+ import { MiddlewareResponseMergeOptions } from "./middleware-response-headers.js";
2
3
  import { EdgeApiExecutionRuntime } from "./edge-api-runtime.js";
3
4
  //#region src/server/app-pages-bridge.d.ts
4
5
  export type PagesEntry = {
@@ -24,7 +25,7 @@ type AppRouteMatch = {
24
25
  type RenderPagesFallbackDependencies = {
25
26
  loadPagesEntry: () => Promise<PagesEntry> | PagesEntry;
26
27
  buildRequestHeaders: (requestHeaders: Headers, middlewareRequestHeaders: Headers) => Headers | null;
27
- applyRouteHandlerMiddlewareContext: (response: Response, middlewareContext: AppMiddlewareContext) => Response;
28
+ applyRouteHandlerMiddlewareContext: (response: Response, middlewareContext: AppMiddlewareContext, options?: MiddlewareResponseMergeOptions) => Response;
28
29
  /**
29
30
  * Returns the `__prerender_bypass` Set-Cookie header emitted by a
30
31
  * `draftMode().enable()`/`disable()` call inside middleware, if any. Reading
@@ -23,15 +23,18 @@ async function renderPagesFallback(options, dependencies) {
23
23
  if (isRscRequest && !allowRscDocumentFallback) return null;
24
24
  const pagesEntry = await loadPagesEntry();
25
25
  const pagesRequestHeaders = middlewareContext.requestHeaders ? buildRequestHeaders(request.headers, middlewareContext.requestHeaders) : null;
26
- let pagesRequest = request;
27
- if (pagesRequestHeaders) pagesRequest = cloneRequestWithHeaders(request, pagesRequestHeaders);
26
+ const matchRequest = pagesRequestHeaders ? new Request(request.url, {
27
+ headers: pagesRequestHeaders,
28
+ method: request.method
29
+ }) : request;
30
+ const claimPagesRequest = () => pagesRequestHeaders ? cloneRequestWithHeaders(request, pagesRequestHeaders) : request;
28
31
  const queryIndex = pathname.indexOf("?");
29
32
  const pagesPathname = queryIndex === -1 ? pathname : pathname.slice(0, queryIndex);
30
33
  const pagesUrl = pagesPathname + (queryIndex === -1 ? url.search || "" : pathname.slice(queryIndex));
31
34
  if (pagesPathname.startsWith("/api/") || pagesPathname === "/api") {
32
35
  if (typeof pagesEntry.handleApiRoute !== "function") return null;
33
36
  const hasApiMatcher = typeof pagesEntry.matchApiRoute === "function";
34
- const apiMatch = hasApiMatcher ? pagesEntry.matchApiRoute?.(pagesUrl, pagesRequest) ?? null : null;
37
+ const apiMatch = hasApiMatcher ? pagesEntry.matchApiRoute?.(pagesUrl, matchRequest) ?? null : null;
35
38
  if (hasApiMatcher && apiMatch === null) return null;
36
39
  if (apiMatch !== null && matchKind === "static" && apiMatch.route.isDynamic) return null;
37
40
  if (apiMatch !== null && matchKind === "dynamic" && !apiMatch.route.isDynamic) return null;
@@ -41,24 +44,25 @@ async function renderPagesFallback(options, dependencies) {
41
44
  if (apiMatch !== null) beginRouteCacheability("pages-api", apiMatch.route.pattern);
42
45
  const executionContext = getRequestExecutionContext();
43
46
  const apiArgs = [
44
- pagesRequest,
47
+ claimPagesRequest(),
45
48
  pagesUrl,
46
49
  executionContext ?? void 0,
47
- executionContext?.trustedRevalidateOrigin ?? new URL(pagesRequest.url).origin,
50
+ executionContext?.trustedRevalidateOrigin,
48
51
  executionContext?.hostRuntime ?? "node"
49
52
  ];
50
53
  const pagesApiResponse = await (initialResponseHeaders ? pagesEntry.handleApiRoute(...apiArgs, initialResponseHeaders) : pagesEntry.handleApiRoute(...apiArgs));
51
54
  const draftCookie = getDraftModeCookieHeader();
52
- return applyDraftModeCookie(applyRouteHandlerMiddlewareContext(pagesApiResponse, middlewareContext), draftCookie);
55
+ return applyDraftModeCookie(applyRouteHandlerMiddlewareContext(pagesApiResponse, middlewareContext, { appendResponseChallenges: false }), draftCookie);
53
56
  }
54
57
  if (typeof pagesEntry.renderPage !== "function") return null;
55
58
  const hasPageMatcher = typeof pagesEntry.matchPageRoute === "function";
56
- const pageMatch = hasPageMatcher ? pagesEntry.matchPageRoute?.(pagesUrl, pagesRequest) ?? null : null;
59
+ const pageMatch = hasPageMatcher ? pagesEntry.matchPageRoute?.(pagesUrl, matchRequest) ?? null : null;
57
60
  if (hasPageMatcher && pageMatch === null) return null;
58
61
  if (pageMatch !== null && matchKind === "static" && pageMatch.route.isDynamic) return null;
59
62
  if (pageMatch !== null && matchKind === "dynamic" && !pageMatch.route.isDynamic) return null;
60
63
  if (appRouteMatch !== null && (pageMatch === null || !pagesRouteHasPriorityOverAppRoute(pageMatch.route, appRouteMatch.route))) return null;
61
64
  if (pageMatch !== null) beginRouteCacheability("pages-page", pageMatch.route.pattern);
65
+ const pagesRequest = claimPagesRequest();
62
66
  const renderArgs = [
63
67
  pagesDataRequest ? cloneRequestWithUrl(pagesRequest, pagesDataRequest.url) : pagesRequest,
64
68
  pagesUrl,
@@ -1,4 +1,5 @@
1
1
  import { isUnknownRecord } from "../utils/record.js";
2
+ import { shareIsolatePromise } from "./isolate-shared-promise.js";
2
3
  import { pickRootParams, runWithRootParamsScope } from "../shims/root-params.js";
3
4
  //#region src/server/app-prerender-static-params.ts
4
5
  /**
@@ -42,7 +43,7 @@ function createAppPrerenderStaticParamsResolver(sources, rootParamNames) {
42
43
  let resolvePromise = null;
43
44
  const resolveFns = () => {
44
45
  if (resolvedFns) return Promise.resolve(resolvedFns);
45
- if (!resolvePromise) resolvePromise = (async () => {
46
+ if (!resolvePromise) resolvePromise = shareIsolatePromise((async () => {
46
47
  resolvedFns = (await Promise.all(usableSources.map(async (source) => {
47
48
  if (isGenerateStaticParamsFunction(source)) return source;
48
49
  const mod = await source.load();
@@ -50,7 +51,7 @@ function createAppPrerenderStaticParamsResolver(sources, rootParamNames) {
50
51
  return isGenerateStaticParamsFunction(fn) ? fn : null;
51
52
  }))).filter((fn) => fn !== null);
52
53
  return resolvedFns;
53
- })();
54
+ })());
54
55
  return resolvePromise;
55
56
  };
56
57
  return async (input) => {
@@ -1,5 +1,5 @@
1
1
  import { isPromiseLike } from "../utils/promise.js";
2
- import { createElement, use } from "react";
2
+ import { Fragment, createElement, isValidElement, use } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/server/app-render-dependency.tsx
5
5
  const REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference");
@@ -21,7 +21,47 @@ function invokeAppComponent(component, props) {
21
21
  if (candidate.$$typeof === REACT_LAZY && candidate._init) return invokeAppComponent(candidate._init(candidate._payload), props);
22
22
  if (candidate.$$typeof === REACT_FORWARD_REF && candidate.render) return candidate.render(props, void 0);
23
23
  if (isReactOwnedAppComponent(candidate)) return createElement(candidate, props);
24
- return candidate(props);
24
+ const result = candidate(props);
25
+ return isPromiseLike(result) ? result : invokeCssWrappedComponent(result, props);
26
+ }
27
+ /**
28
+ * Whether `elementProps` are what `createElement(type, props)` produces: the
29
+ * same values, plus any `type.defaultProps` for keys that are `undefined`.
30
+ * Defaulted values aren't read again, since a default can be a getter.
31
+ */
32
+ function isElementOfProps(elementProps, props, defaultProps) {
33
+ const keys = new Set(Object.keys(props));
34
+ const defaulted = /* @__PURE__ */ new Set();
35
+ for (const key in defaultProps) if (props[key] === void 0) {
36
+ keys.add(key);
37
+ defaulted.add(key);
38
+ }
39
+ return Object.keys(elementProps).length === keys.size && [...keys].every((key) => Object.hasOwn(elementProps, key) && (defaulted.has(key) || Object.is(elementProps[key], props[key])));
40
+ }
41
+ /**
42
+ * `@vitejs/plugin-rsc` wraps a server component export whose module imports
43
+ * CSS (`__vite_rsc_wrap_css__`). The wrapper returns
44
+ * `<><Css /><Component {...props} /></>`, so a component vinext invokes
45
+ * directly renders as an element with its props after all. React's dev build
46
+ * serializes an element's props as debug info and calls `then` on `params`
47
+ * and `searchParams`, which counts as reading them. Invoke the inner
48
+ * component from an element without props instead, as for an export without
49
+ * CSS.
50
+ */
51
+ function invokeCssWrappedComponent(result, props) {
52
+ if (!isValidElement(result) || result.type !== Fragment || result.key !== null) return result;
53
+ const children = result.props.children;
54
+ if (!Array.isArray(children) || children.length !== 2) return result;
55
+ const [css, inner] = children;
56
+ if (!isValidElement(inner) || typeof inner.type !== "function" || inner.key !== null) return result;
57
+ const component = inner.type;
58
+ if (!isElementOfProps(inner.props, props, component.defaultProps)) return result;
59
+ const componentProps = inner.props;
60
+ function CssWrappedComponent() {
61
+ return invokeAppComponent(component, componentProps);
62
+ }
63
+ CssWrappedComponent.displayName = component.displayName ?? component.name;
64
+ return createElement(Fragment, null, css, createElement(CssWrappedComponent));
25
65
  }
26
66
  const appElementRenderDependencies = /* @__PURE__ */ new WeakMap();
27
67
  function registerAppElementRenderDependencies(elements, dependenciesByElementId) {
@@ -26,7 +26,7 @@ const rejectResponseStage = () => Promise.resolve(new Response(null, { status: 4
26
26
  function handleRequestStage(request, env, ctx, dispatchResponseStage) {
27
27
  const originalRequest = request;
28
28
  const handleStage = async () => {
29
- await __ensureInstrumentation();
29
+ await __ensureInstrumentation(ctx);
30
30
  const url = new URL(request.url);
31
31
  return traceFrameworkRequest({
32
32
  callback: () => handleRequest(request, env, ctx, dispatchResponseStage, ctx?.assets).then((response) => applyCdnResponseIdentityHeaders(response, originalRequest)),
@@ -56,7 +56,7 @@ async function handleRequest(request, env, platformCtx, dispatchResponseStage, a
56
56
  if (validationResponse) return validationResponse;
57
57
  didValidateCdnRequest = true;
58
58
  if (readinessResponse.status !== 204) return readinessResponse;
59
- await __ensureHybridPagesApplication();
59
+ await __ensureHybridPagesApplication(ctx);
60
60
  }
61
61
  let probeMode = null;
62
62
  let probeRoute = null;
@@ -19,7 +19,7 @@ import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
19
19
  /** Cacheable App response stage. This is the only multi-stage App entry that imports user routes. */
20
20
  /** Invoke one transformed public cache function without rendering its owning route. */
21
21
  async function invokeCacheFunction(invocation, env, platformCtx, dispatchRequestStage) {
22
- await __ensureInstrumentation();
22
+ await __ensureInstrumentation(platformCtx);
23
23
  const [{ loadServerAction }, { invokeCacheFunction: invokeRegisteredCacheFunction }] = await Promise.all([import("@vitejs/plugin-rsc/core/rsc"), import("../shims/cache-callable-runtime.js")]);
24
24
  registerConfiguredCacheAdapters(env);
25
25
  ensureFetchPatch();
@@ -37,8 +37,8 @@ async function handleResponseStage(request, env, platformCtx, props, dispatchReq
37
37
  if (props.requestOrigin !== new URL(request.url).origin) return new Response("Invalid vinext App response stage", { status: 400 });
38
38
  const currentBuildId = process.env.__VINEXT_BUILD_ID ?? null;
39
39
  if (props.buildId !== currentBuildId) return new Response("Incompatible vinext App response stage", { status: 409 });
40
- await __ensureInstrumentation();
41
- if (props.kind === "app-full-request" && props.prerenderDiscovery) await __ensureHybridPagesApplication();
40
+ await __ensureInstrumentation(platformCtx);
41
+ if (props.kind === "app-full-request" && props.prerenderDiscovery) await __ensureHybridPagesApplication(platformCtx);
42
42
  registerConfiguredImageOptimizer(env);
43
43
  let ctx = createWorkerRevalidationContext(platformCtx, (internalRequest) => dispatchRequestStage(internalRequest), "node");
44
44
  if (props.kind === "app-full-request" && props.prerenderDiscovery) ctx = {
@@ -1,4 +1,4 @@
1
- import { closeAfterResponse, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
1
+ import { closeAfterResponse, createRequestContext, getRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
2
2
  import "../utils/protocol-headers.js";
3
3
  import { getRequestExecutionContext } from "../shims/request-context.js";
4
4
  import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
@@ -40,6 +40,7 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
40
40
  const requestContext = createRequestContext({
41
41
  headersContext,
42
42
  executionContext: getRequestExecutionContext(),
43
+ phase: "route-handler",
43
44
  unstableCacheRevalidation: "foreground"
44
45
  });
45
46
  const revalidation = runWithRequestContext(requestContext, () => runInWorkStoreScope(async () => {
@@ -203,6 +204,7 @@ async function dispatchAppRouteHandlerImpl(options) {
203
204
  return reportRequestError(error, request, context);
204
205
  },
205
206
  request: options.request,
207
+ requestSignal: getRequestContext().requestSignal ?? void 0,
206
208
  expireSeconds: options.expireSeconds,
207
209
  revalidateSeconds,
208
210
  revalidateReason,
@@ -56,6 +56,8 @@ type RunAppRouteHandlerOptions = {
56
56
  */
57
57
  params: AppRouteParams | null;
58
58
  request: Request;
59
+ /** Host signal for the client connection; only the foreground request has one. */
60
+ requestSignal?: AbortSignal;
59
61
  routePattern?: string;
60
62
  setHeadersAccessPhase?: (phase: HeadersAccessPhase) => HeadersAccessPhase;
61
63
  };
@@ -118,6 +118,7 @@ async function runAppRouteHandler(options) {
118
118
  options.markDynamicUsage();
119
119
  },
120
120
  requestMode: options.dynamicConfig === "force-static" || options.dynamicConfig === "error" ? options.dynamicConfig : "auto",
121
+ signal: options.requestSignal,
121
122
  staticGenerationErrorMessage(expression) {
122
123
  return getAppRouteStaticGenerationErrorMessage(options.routePattern, expression);
123
124
  }
@@ -210,10 +211,16 @@ async function executeAppRouteHandlerImpl(options) {
210
211
  revalidateSeconds: options.revalidateSeconds,
211
212
  requiresCompletedResponseAdmission: isRouteCacheabilityEvaluation()
212
213
  })) {
213
- const completed = await completeAppRouteHandlerResponse(response);
214
+ const completed = await completeAppRouteHandlerResponse(response).catch(async (error) => {
215
+ await _drainPendingRevalidations().catch(() => {});
216
+ throw error;
217
+ });
214
218
  response = completed.response;
215
219
  cleanupDeferredToBody = !completed.completed;
216
- if (completed.completed) markRouteCacheabilityResponseBodyComplete();
220
+ if (completed.completed) {
221
+ markRouteCacheabilityResponseBodyComplete();
222
+ await _drainPendingRevalidations();
223
+ }
217
224
  const dynamicUsedDuringCompletion = options.consumeDynamicUsage();
218
225
  dynamicUsedInHandler = handlerResult.didAccessDynamicRequest() || dynamicUsedDuringCompletion || dynamicUsedInHandler;
219
226
  }
@@ -1,8 +1,9 @@
1
+ import { MiddlewareResponseMergeOptions } from "./middleware-response-headers.js";
1
2
  //#region src/server/app-route-handler-middleware-context.d.ts
2
3
  export type RouteHandlerMiddlewareContext = {
3
4
  headers: Headers | null;
4
5
  status: number | null;
5
6
  };
6
7
  /** Apply request-stage middleware response metadata to a route-handler response. */
7
- export declare function applyRouteHandlerMiddlewareContext(response: Response, middlewareContext: RouteHandlerMiddlewareContext): Response;
8
+ export declare function applyRouteHandlerMiddlewareContext(response: Response, middlewareContext: RouteHandlerMiddlewareContext, options?: MiddlewareResponseMergeOptions): Response;
8
9
  //#endregion
@@ -1,10 +1,10 @@
1
- import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
1
+ import { mergeMiddlewareResponseHeadersOntoResponse } from "./middleware-response-headers.js";
2
2
  //#region src/server/app-route-handler-middleware-context.ts
3
3
  /** Apply request-stage middleware response metadata to a route-handler response. */
4
- function applyRouteHandlerMiddlewareContext(response, middlewareContext) {
4
+ function applyRouteHandlerMiddlewareContext(response, middlewareContext, options = {}) {
5
5
  if (!middlewareContext.headers && middlewareContext.status == null) return response;
6
6
  const responseHeaders = new Headers(response.headers);
7
- mergeMiddlewareResponseHeaders(responseHeaders, middlewareContext.headers);
7
+ mergeMiddlewareResponseHeadersOntoResponse(responseHeaders, middlewareContext.headers, options);
8
8
  return new Response(response.body, {
9
9
  status: middlewareContext.status ?? response.status,
10
10
  statusText: response.statusText,
@@ -1,3 +1,4 @@
1
+ import { MiddlewareResponseMergeOptions } from "./middleware-response-headers.js";
1
2
  import { CacheControlMetadata, CachedRouteValue } from "../shims/cache-handler.js";
2
3
  //#region src/server/app-route-handler-response.d.ts
3
4
  export type RouteHandlerMiddlewareContext = {
@@ -16,7 +17,7 @@ type FinalizeRouteHandlerResponseOptions = {
16
17
  draftCookie?: string | null;
17
18
  isHead: boolean;
18
19
  };
19
- export declare function applyRouteHandlerMiddlewareContext(response: Response, middlewareContext: RouteHandlerMiddlewareContext, options?: {
20
+ export declare function applyRouteHandlerMiddlewareContext(response: Response, middlewareContext: RouteHandlerMiddlewareContext, options?: MiddlewareResponseMergeOptions & {
20
21
  appendResponseLink?: boolean;
21
22
  }): Response;
22
23
  export declare function assertSupportedAppRouteHandlerResponse(response: Response): void;
@@ -5,7 +5,7 @@ import { markRouteCacheabilityExplicitResponsePolicy, recordRouteCacheability }
5
5
  import { applyCdnResponseHeaders } from "./cache-control.js";
6
6
  import { buildAppRouteMissIsrCacheControl, decideIsr } from "./isr-decision.js";
7
7
  import { setCacheStateHeaders } from "./cache-headers.js";
8
- import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
8
+ import { mergeMiddlewareResponseHeadersOntoResponse } from "./middleware-response-headers.js";
9
9
  import { markEdgeRouteHandlerLinkHeaders } from "./app-response-header-provenance.js";
10
10
  import { getSetCookieName } from "./cookie-utils.js";
11
11
  //#region src/server/app-route-handler-response.ts
@@ -22,7 +22,7 @@ function applyRouteHandlerMiddlewareContext(response, middlewareContext, options
22
22
  return response;
23
23
  }
24
24
  const responseHeaders = new Headers(response.headers);
25
- mergeMiddlewareResponseHeaders(responseHeaders, middlewareContext.headers);
25
+ mergeMiddlewareResponseHeadersOntoResponse(responseHeaders, middlewareContext.headers, options);
26
26
  if (responseLink && middlewareContext.headers?.get("link")) responseHeaders.append("link", responseLink);
27
27
  const result = new Response(response.body, {
28
28
  status: middlewareContext.status ?? response.status,
@@ -30,6 +30,8 @@ type TrackedAppRouteRequestOptions = {
30
30
  middlewareHeaders?: Headers | null;
31
31
  onDynamicAccess?: (access: AppRouteDynamicRequestAccess) => void;
32
32
  requestMode?: AppRouteRequestMode;
33
+ /** Host signal for the client connection (UnifiedRequestContext.requestSignal). */
34
+ signal?: AbortSignal;
33
35
  staticGenerationErrorMessage?: (expression?: string) => string;
34
36
  };
35
37
  type TrackedAppRouteRequest = {
@@ -72,7 +72,20 @@ function buildNextConfig(options) {
72
72
  skipTrailingSlashRedirect: options.skipTrailingSlashRedirect
73
73
  };
74
74
  }
75
- function createForceStaticNextRequest(input, nextConfig) {
75
+ /**
76
+ * Undici's Request follows its input's signal through a WeakRef, and so does
77
+ * every clone between the host signal and the handler's request. A handler
78
+ * that only listens on `request.signal` (e.g. to stop a stream) would miss the
79
+ * abort once GC collects any of them, so the request follows the host signal
80
+ * directly and stays reachable for as long as that signal is.
81
+ */
82
+ const requestsByHostSignal = /* @__PURE__ */ new WeakMap();
83
+ function retainWhileSignalLives(signal, request) {
84
+ const requests = requestsByHostSignal.get(signal);
85
+ if (requests) requests.push(request);
86
+ else requestsByHostSignal.set(signal, [request]);
87
+ }
88
+ function createForceStaticNextRequest(input, nextConfig, signal) {
76
89
  const read = (key) => {
77
90
  const descriptor = BUILT_IN_REQUEST_PROPERTY_MAP.get(key)?.descriptor;
78
91
  if (descriptor?.get) return descriptor.get.call(input);
@@ -89,7 +102,7 @@ function createForceStaticNextRequest(input, nextConfig) {
89
102
  redirect: read("redirect"),
90
103
  referrer: read("referrer"),
91
104
  referrerPolicy: read("referrerPolicy"),
92
- signal: read("signal"),
105
+ signal: signal ?? read("signal"),
93
106
  nextConfig: nextConfig ?? void 0
94
107
  });
95
108
  }
@@ -215,7 +228,11 @@ function createTrackedAppRouteRequest(request, options = {}) {
215
228
  const sourceCfDescriptor = Reflect.getOwnPropertyDescriptor(requestWithOverrides, "cf");
216
229
  const sourceCfAccessor = sourceCfDescriptor?.get;
217
230
  const sourceCfMetadata = sourceCfAccessor ? void 0 : Reflect.get(requestWithOverrides, "cf", requestWithOverrides);
218
- const nextRequest = requestMode === "force-static" ? createForceStaticNextRequest(requestWithOverrides, nextConfig) : requestWithOverrides instanceof NextRequest && sourceCfDescriptor?.configurable !== false ? requestWithOverrides : new NextRequest(requestWithOverrides, { nextConfig: nextConfig ?? void 0 });
231
+ const nextRequest = requestMode === "force-static" ? createForceStaticNextRequest(requestWithOverrides, nextConfig, options.signal) : requestWithOverrides instanceof NextRequest && sourceCfDescriptor?.configurable !== false && !options.signal ? requestWithOverrides : new NextRequest(requestWithOverrides, {
232
+ nextConfig: nextConfig ?? void 0,
233
+ signal: options.signal
234
+ });
235
+ if (options.signal) retainWhileSignalLives(options.signal, nextRequest);
219
236
  const rawCfMetadata = sourceCfAccessor ? void 0 : sourceCfMetadata === void 0 ? Reflect.get(nextRequest, "cf", nextRequest) : sourceCfMetadata;
220
237
  const hasCfMetadata = sourceCfAccessor !== void 0 || rawCfMetadata !== void 0;
221
238
  const originalCfDescriptor = sourceCfDescriptor ?? Reflect.getOwnPropertyDescriptor(nextRequest, "cf");
@@ -1,4 +1,5 @@
1
1
  import { runOutsideRequestScopes } from "../shims/internal/als-registry.js";
2
+ import { shareIsolatePromise } from "./isolate-shared-promise.js";
2
3
  //#region src/server/app-route-module-loader.ts
3
4
  /**
4
5
  * Lazy route-module hydration for the App Router RSC entry.
@@ -63,7 +64,7 @@ async function hydrateInterceptModule(intercept, loader, field, loadingField) {
63
64
  const cached = loadState?.[field];
64
65
  if (cached != null) intercept[field] = cached;
65
66
  if (!loader || intercept[field] != null) return;
66
- const loading = loadState?.[loadingField] ?? runOutsideRequestScopes(loader).then((module) => {
67
+ const loading = loadState?.[loadingField] ?? shareIsolatePromise(runOutsideRequestScopes(loader).then((module) => {
67
68
  intercept[field] = module;
68
69
  if (loadState) {
69
70
  loadState[field] = module;
@@ -73,7 +74,7 @@ async function hydrateInterceptModule(intercept, loader, field, loadingField) {
73
74
  }).catch((error) => {
74
75
  if (loadState) loadState[loadingField] = null;
75
76
  throw error;
76
- });
77
+ }));
77
78
  if (loadState) loadState[loadingField] = loading;
78
79
  intercept[field] = await loading;
79
80
  }
@@ -92,13 +93,13 @@ function loadAppInterceptLayouts(intercept) {
92
93
  pushArrayLoads(loads, intercept.interceptLayouts, intercept.__loadInterceptLayouts);
93
94
  pushArrayLoads(loads, intercept.interceptLoadings, intercept.__loadInterceptLoadings);
94
95
  if (loads.length === 0) return Promise.resolve(intercept.interceptLayouts ?? []);
95
- const loading = Promise.all(loads).then(() => {
96
+ const loading = shareIsolatePromise(Promise.all(loads).then(() => {
96
97
  if (loadState) loadState.interceptLayoutsLoading = null;
97
98
  return intercept.interceptLayouts ?? [];
98
99
  }).catch((error) => {
99
100
  if (loadState) loadState.interceptLayoutsLoading = null;
100
101
  throw error;
101
- });
102
+ }));
102
103
  if (loadState) loadState.interceptLayoutsLoading = loading;
103
104
  return loading;
104
105
  }
@@ -143,14 +144,14 @@ function ensureAppRouteModulesLoaded(route) {
143
144
  route.__loaded = true;
144
145
  return route;
145
146
  }
146
- const loading = Promise.all(loads).then(() => {
147
+ const loading = shareIsolatePromise(Promise.all(loads).then(() => {
147
148
  route.__loaded = true;
148
149
  route.__loading = null;
149
150
  return route;
150
151
  }).catch((error) => {
151
152
  route.__loading = null;
152
153
  throw error;
153
- });
154
+ }));
154
155
  route.__loading = loading;
155
156
  return loading;
156
157
  }
@@ -0,0 +1,20 @@
1
+ import { AppElements } from "./app-elements-wire.js";
2
+ import "./app-elements.js";
3
+ import { ReactNode } from "react";
4
+ //#region src/server/app-route-tree.d.ts
5
+ /**
6
+ * Builds the App Router route tree after a sibling that the browser uses to
7
+ * write navigation history. Insertion effects run in tree order, so that
8
+ * sibling's effect runs before React mutates the route tree's DOM, like
9
+ * Next.js' HistoryUpdater.
10
+ *
11
+ * The server and the browser must render this same shape: a second child
12
+ * changes the useId values of everything below it, so SSR passes null in the
13
+ * sibling's place to keep hydrated ids matching.
14
+ */
15
+ export declare function createAppRouteTree(options: {
16
+ elements: AppElements;
17
+ historyCommit: ReactNode;
18
+ routeId: string;
19
+ }): ReactNode;
20
+ //#endregion
@@ -0,0 +1,18 @@
1
+ import { ElementsContext, Slot } from "../shims/slot.js";
2
+ import { Fragment, createElement } from "react";
3
+ //#region src/server/app-route-tree.ts
4
+ /**
5
+ * Builds the App Router route tree after a sibling that the browser uses to
6
+ * write navigation history. Insertion effects run in tree order, so that
7
+ * sibling's effect runs before React mutates the route tree's DOM, like
8
+ * Next.js' HistoryUpdater.
9
+ *
10
+ * The server and the browser must render this same shape: a second child
11
+ * changes the useId values of everything below it, so SSR passes null in the
12
+ * sibling's place to keep hydrated ids matching.
13
+ */
14
+ function createAppRouteTree(options) {
15
+ return createElement(Fragment, null, options.historyCommit, createElement(ElementsContext.Provider, { value: options.elements }, createElement(Slot, { id: options.routeId })));
16
+ }
17
+ //#endregion
18
+ export { createAppRouteTree };