vinext 0.1.2 → 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 (199) hide show
  1. package/dist/build/prerender.d.ts +9 -1
  2. package/dist/build/prerender.js +41 -12
  3. package/dist/build/run-prerender.d.ts +10 -2
  4. package/dist/build/run-prerender.js +15 -1
  5. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  6. package/dist/client/app-nav-failure-handler.js +44 -0
  7. package/dist/client/vinext-next-data.d.ts +18 -1
  8. package/dist/client/window-next.d.ts +2 -1
  9. package/dist/client/window-next.js +12 -1
  10. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  11. package/dist/config/config-matchers.js +73 -14
  12. package/dist/config/next-config.d.ts +46 -4
  13. package/dist/config/next-config.js +147 -48
  14. package/dist/deploy.d.ts +30 -11
  15. package/dist/deploy.js +180 -99
  16. package/dist/entries/app-browser-entry.d.ts +9 -3
  17. package/dist/entries/app-browser-entry.js +21 -3
  18. package/dist/entries/app-rsc-entry.d.ts +2 -0
  19. package/dist/entries/app-rsc-entry.js +64 -5
  20. package/dist/entries/app-rsc-manifest.js +2 -0
  21. package/dist/entries/app-ssr-entry.js +1 -1
  22. package/dist/entries/pages-client-entry.js +53 -8
  23. package/dist/entries/pages-server-entry.js +41 -5
  24. package/dist/index.js +200 -62
  25. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  26. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  27. package/dist/plugins/optimize-imports.d.ts +2 -1
  28. package/dist/plugins/optimize-imports.js +11 -9
  29. package/dist/plugins/postcss.js +7 -7
  30. package/dist/plugins/typeof-window.d.ts +14 -0
  31. package/dist/plugins/typeof-window.js +150 -0
  32. package/dist/routing/app-route-graph.d.ts +2 -1
  33. package/dist/routing/app-route-graph.js +44 -14
  34. package/dist/routing/file-matcher.d.ts +10 -1
  35. package/dist/routing/file-matcher.js +22 -1
  36. package/dist/routing/pages-router.js +3 -3
  37. package/dist/routing/utils.d.ts +35 -6
  38. package/dist/routing/utils.js +59 -7
  39. package/dist/server/api-handler.d.ts +6 -1
  40. package/dist/server/api-handler.js +21 -15
  41. package/dist/server/app-browser-action-result.d.ts +19 -6
  42. package/dist/server/app-browser-action-result.js +19 -10
  43. package/dist/server/app-browser-entry.js +167 -90
  44. package/dist/server/app-browser-error.d.ts +10 -6
  45. package/dist/server/app-browser-error.js +43 -8
  46. package/dist/server/app-browser-hydration.d.ts +2 -0
  47. package/dist/server/app-browser-hydration.js +1 -0
  48. package/dist/server/app-browser-navigation-controller.d.ts +4 -2
  49. package/dist/server/app-browser-navigation-controller.js +23 -2
  50. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  51. package/dist/server/app-browser-server-action-navigation.js +9 -0
  52. package/dist/server/app-browser-stream.js +86 -43
  53. package/dist/server/app-elements-wire.d.ts +6 -1
  54. package/dist/server/app-elements-wire.js +14 -4
  55. package/dist/server/app-elements.d.ts +2 -2
  56. package/dist/server/app-elements.js +2 -2
  57. package/dist/server/app-fallback-renderer.d.ts +1 -0
  58. package/dist/server/app-fallback-renderer.js +3 -1
  59. package/dist/server/app-optimistic-routing.js +2 -2
  60. package/dist/server/app-page-boundary-render.d.ts +1 -0
  61. package/dist/server/app-page-boundary-render.js +27 -14
  62. package/dist/server/app-page-cache-render.d.ts +53 -0
  63. package/dist/server/app-page-cache-render.js +91 -0
  64. package/dist/server/app-page-cache.d.ts +16 -2
  65. package/dist/server/app-page-cache.js +62 -1
  66. package/dist/server/app-page-dispatch.d.ts +26 -0
  67. package/dist/server/app-page-dispatch.js +149 -92
  68. package/dist/server/app-page-element-builder.d.ts +1 -0
  69. package/dist/server/app-page-element-builder.js +5 -2
  70. package/dist/server/app-page-execution.d.ts +6 -1
  71. package/dist/server/app-page-execution.js +21 -1
  72. package/dist/server/app-page-probe.d.ts +1 -0
  73. package/dist/server/app-page-probe.js +4 -0
  74. package/dist/server/app-page-render-observation.d.ts +3 -1
  75. package/dist/server/app-page-render-observation.js +17 -1
  76. package/dist/server/app-page-render.d.ts +12 -1
  77. package/dist/server/app-page-render.js +42 -4
  78. package/dist/server/app-page-request.d.ts +2 -0
  79. package/dist/server/app-page-request.js +2 -1
  80. package/dist/server/app-page-route-wiring.d.ts +3 -1
  81. package/dist/server/app-page-route-wiring.js +14 -5
  82. package/dist/server/app-page-stream.d.ts +15 -3
  83. package/dist/server/app-page-stream.js +11 -5
  84. package/dist/server/app-pages-bridge.d.ts +18 -0
  85. package/dist/server/app-pages-bridge.js +22 -5
  86. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  87. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  88. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  89. package/dist/server/app-ppr-fallback-shell.js +8 -1
  90. package/dist/server/app-route-handler-dispatch.js +9 -2
  91. package/dist/server/app-route-handler-policy.d.ts +1 -0
  92. package/dist/server/app-router-entry.js +5 -0
  93. package/dist/server/app-rsc-cache-busting.js +2 -0
  94. package/dist/server/app-rsc-handler.d.ts +25 -0
  95. package/dist/server/app-rsc-handler.js +154 -54
  96. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  97. package/dist/server/app-rsc-route-matching.js +2 -0
  98. package/dist/server/app-segment-config.d.ts +9 -1
  99. package/dist/server/app-segment-config.js +12 -3
  100. package/dist/server/app-server-action-execution.d.ts +1 -0
  101. package/dist/server/app-server-action-execution.js +42 -13
  102. package/dist/server/app-ssr-entry.d.ts +2 -0
  103. package/dist/server/app-ssr-entry.js +83 -10
  104. package/dist/server/cache-control.js +4 -0
  105. package/dist/server/dev-server.d.ts +2 -2
  106. package/dist/server/dev-server.js +244 -51
  107. package/dist/server/hybrid-route-priority.d.ts +22 -0
  108. package/dist/server/hybrid-route-priority.js +33 -0
  109. package/dist/server/image-optimization.d.ts +18 -9
  110. package/dist/server/image-optimization.js +37 -23
  111. package/dist/server/implicit-tags.d.ts +2 -1
  112. package/dist/server/implicit-tags.js +4 -1
  113. package/dist/server/navigation-planner.d.ts +133 -30
  114. package/dist/server/navigation-planner.js +114 -0
  115. package/dist/server/navigation-trace.d.ts +8 -1
  116. package/dist/server/navigation-trace.js +8 -1
  117. package/dist/server/pages-api-route.d.ts +6 -0
  118. package/dist/server/pages-api-route.js +13 -2
  119. package/dist/server/pages-asset-tags.d.ts +2 -1
  120. package/dist/server/pages-asset-tags.js +6 -2
  121. package/dist/server/pages-data-route.d.ts +8 -1
  122. package/dist/server/pages-data-route.js +11 -2
  123. package/dist/server/pages-get-initial-props.d.ts +54 -4
  124. package/dist/server/pages-get-initial-props.js +43 -1
  125. package/dist/server/pages-node-compat.js +2 -2
  126. package/dist/server/pages-page-data.d.ts +11 -2
  127. package/dist/server/pages-page-data.js +204 -33
  128. package/dist/server/pages-page-handler.d.ts +4 -2
  129. package/dist/server/pages-page-handler.js +59 -22
  130. package/dist/server/pages-page-response.d.ts +2 -1
  131. package/dist/server/pages-page-response.js +7 -4
  132. package/dist/server/pages-request-pipeline.d.ts +1 -0
  133. package/dist/server/pages-request-pipeline.js +73 -36
  134. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  135. package/dist/server/pregenerated-concrete-paths.js +2 -19
  136. package/dist/server/prerender-manifest.d.ts +33 -0
  137. package/dist/server/prerender-manifest.js +54 -0
  138. package/dist/server/prerender-route-params.d.ts +1 -2
  139. package/dist/server/prod-server.js +9 -3
  140. package/dist/server/request-pipeline.d.ts +3 -15
  141. package/dist/server/request-pipeline.js +58 -47
  142. package/dist/server/rsc-stream-hints.d.ts +5 -1
  143. package/dist/server/rsc-stream-hints.js +6 -1
  144. package/dist/server/seed-cache.js +10 -18
  145. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  146. package/dist/shims/app-router-scroll-state.js +14 -2
  147. package/dist/shims/app-router-scroll.d.ts +3 -0
  148. package/dist/shims/app-router-scroll.js +28 -18
  149. package/dist/shims/cache-runtime.js +3 -2
  150. package/dist/shims/cache.d.ts +1 -0
  151. package/dist/shims/cache.js +1 -1
  152. package/dist/shims/cdn-cache.d.ts +5 -5
  153. package/dist/shims/dynamic-preload-chunks.js +6 -4
  154. package/dist/shims/error-boundary.d.ts +2 -0
  155. package/dist/shims/error-boundary.js +7 -0
  156. package/dist/shims/error.js +3 -2
  157. package/dist/shims/error.react-server.d.ts +9 -0
  158. package/dist/shims/error.react-server.js +6 -0
  159. package/dist/shims/fetch-cache.d.ts +3 -1
  160. package/dist/shims/fetch-cache.js +45 -20
  161. package/dist/shims/hash-scroll.js +6 -1
  162. package/dist/shims/headers.js +29 -4
  163. package/dist/shims/internal/als-registry.js +28 -1
  164. package/dist/shims/internal/app-route-detection.js +8 -17
  165. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  166. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  167. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  168. package/dist/shims/internal/navigation-untracked.js +55 -0
  169. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  170. package/dist/shims/internal/pages-data-target.js +17 -8
  171. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  172. package/dist/shims/internal/pages-router-accessor.js +13 -0
  173. package/dist/shims/internal/router-context.d.ts +2 -1
  174. package/dist/shims/internal/router-context.js +3 -1
  175. package/dist/shims/link.js +12 -5
  176. package/dist/shims/navigation.d.ts +8 -2
  177. package/dist/shims/navigation.js +61 -31
  178. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  179. package/dist/shims/ppr-fallback-shell.js +28 -7
  180. package/dist/shims/router.d.ts +13 -2
  181. package/dist/shims/router.js +419 -128
  182. package/dist/shims/server.d.ts +16 -1
  183. package/dist/shims/server.js +44 -12
  184. package/dist/shims/unified-request-context.js +1 -0
  185. package/dist/utils/built-asset-url.d.ts +4 -0
  186. package/dist/utils/built-asset-url.js +11 -0
  187. package/dist/utils/commonjs-loader.d.ts +16 -0
  188. package/dist/utils/commonjs-loader.js +100 -0
  189. package/dist/utils/deployment-id.d.ts +8 -0
  190. package/dist/utils/deployment-id.js +22 -0
  191. package/dist/utils/html-limited-bots.d.ts +18 -1
  192. package/dist/utils/html-limited-bots.js +23 -1
  193. package/dist/utils/parse-cookie.d.ts +13 -0
  194. package/dist/utils/parse-cookie.js +52 -0
  195. package/dist/utils/path.d.ts +7 -1
  196. package/dist/utils/path.js +9 -1
  197. package/package.json +2 -2
  198. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  199. package/dist/shims/internal/parse-cookie-header.js +0 -30
@@ -1,10 +1,11 @@
1
1
  import { stripBasePath } from "../utils/base-path.js";
2
+ import { clearAppNavigationFailureTarget, getAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
2
3
  import { claimAppRouterScrollIntentForCommit, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
3
4
  import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
4
5
  import { shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
5
6
  import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, createPendingNavigationCommit } from "./app-browser-state.js";
6
7
  import { applyApprovedVisibleCommit, approveHmrVisibleCommit, approvePendingNavigationCommit, resolveAndClassifyNavigationCommit } from "./app-browser-visible-commit.js";
7
- import { startTransition, useLayoutEffect } from "react";
8
+ import { startTransition, useInsertionEffect, useLayoutEffect } from "react";
8
9
  import { flushSync } from "react-dom";
9
10
  //#region src/server/app-browser-navigation-controller.ts
10
11
  const HARD_NAVIGATION_LOOP_GUARD_KEY = "__vinext_hard_navigation_target__";
@@ -73,6 +74,7 @@ function createAppBrowserNavigationController(deps = {}) {
73
74
  let nextNavigationRenderId = 0;
74
75
  let activeNavigationId = 0;
75
76
  const pendingNavigationCommits = /* @__PURE__ */ new Map();
77
+ const pendingNavigationFailureTargets = /* @__PURE__ */ new Map();
76
78
  const pendingNavigationPrePaintEffects = /* @__PURE__ */ new Map();
77
79
  let setBrowserRouterState = null;
78
80
  let browserRouterStateRef = null;
@@ -191,6 +193,13 @@ function createAppBrowserNavigationController(deps = {}) {
191
193
  resolve();
192
194
  }
193
195
  }
196
+ function clearCommittedNavigationFailureTargets(renderId) {
197
+ for (const [pendingId, targetHref] of pendingNavigationFailureTargets) {
198
+ if (pendingId > renderId) continue;
199
+ pendingNavigationFailureTargets.delete(pendingId);
200
+ clearAppNavigationFailureTarget(targetHref);
201
+ }
202
+ }
194
203
  async function hmrReplaceTree(nextElements, navigationSnapshot) {
195
204
  if (!hasBrowserRouterState()) return;
196
205
  const pending = await createPendingNavigationCommit({
@@ -206,6 +215,9 @@ function createAppBrowserNavigationController(deps = {}) {
206
215
  dispatchSynchronousVisibleCommit(approveHmrVisibleCommit(pending));
207
216
  }
208
217
  function NavigationCommitSignal({ renderId, children }) {
218
+ useInsertionEffect(() => {
219
+ clearCommittedNavigationFailureTargets(renderId);
220
+ }, [renderId]);
209
221
  useLayoutEffect(() => {
210
222
  drainPrePaintEffects(renderId);
211
223
  const frame = requestAnimationFrame(() => {
@@ -298,6 +310,8 @@ function createAppBrowserNavigationController(deps = {}) {
298
310
  }
299
311
  async function renderNavigationPayload(options) {
300
312
  const renderId = allocateRenderId();
313
+ const failureTarget = getAppNavigationFailureTarget(options.targetHref);
314
+ if (failureTarget) pendingNavigationFailureTargets.set(renderId, failureTarget);
301
315
  let resolveCommitted;
302
316
  const committed = new Promise((resolve) => {
303
317
  resolveCommitted = resolve;
@@ -327,6 +341,8 @@ function createAppBrowserNavigationController(deps = {}) {
327
341
  });
328
342
  if (approval.decision.disposition === "no-commit") {
329
343
  settlePendingBrowserRouterState(options.pendingRouterState);
344
+ pendingNavigationFailureTargets.delete(renderId);
345
+ if (failureTarget) clearAppNavigationFailureTarget(failureTarget);
330
346
  pendingNavigationCommits.delete(renderId);
331
347
  resolveCommitted?.();
332
348
  consumeAppRouterScrollIntent(options.scrollIntent ?? null);
@@ -334,9 +350,12 @@ function createAppBrowserNavigationController(deps = {}) {
334
350
  }
335
351
  if (approval.decision.disposition === "hard-navigate") {
336
352
  settlePendingBrowserRouterState(options.pendingRouterState);
353
+ pendingNavigationFailureTargets.delete(renderId);
337
354
  pendingNavigationCommits.delete(renderId);
338
355
  consumeAppRouterScrollIntent(options.scrollIntent ?? null);
339
- return performHardNavigation(options.targetHref) ? "hard-navigate" : "no-commit";
356
+ if (performHardNavigation(options.targetHref)) return "hard-navigate";
357
+ if (failureTarget) clearAppNavigationFailureTarget(failureTarget);
358
+ return "no-commit";
340
359
  }
341
360
  const approvedCommit = approval.approvedCommit;
342
361
  if (approvedCommit === null) throw new Error("[vinext] Commit decision did not approve a visible commit");
@@ -354,6 +373,7 @@ function createAppBrowserNavigationController(deps = {}) {
354
373
  snapshotActivated = true;
355
374
  dispatchApprovedVisibleCommit(approvedCommit, options.pendingRouterState, options.visibleCommitMode ?? "transition");
356
375
  } catch (error) {
376
+ pendingNavigationFailureTargets.delete(renderId);
357
377
  pendingNavigationPrePaintEffects.delete(renderId);
358
378
  pendingNavigationCommits.delete(renderId);
359
379
  if (snapshotActivated) commitClientNavigationStateImpl(options.navId);
@@ -437,6 +457,7 @@ function createAppBrowserNavigationController(deps = {}) {
437
457
  commitSameUrlNavigatePayload,
438
458
  hmrReplaceTree,
439
459
  drainPrePaintEffects,
460
+ clearCommittedNavigationFailureTargets,
440
461
  NavigationCommitSignal
441
462
  };
442
463
  }
@@ -0,0 +1,6 @@
1
+ import { ServerActionResultDecision } from "./navigation-planner.js";
2
+
3
+ //#region src/server/app-browser-server-action-navigation.d.ts
4
+ declare function applyServerActionResultDecision(decision: ServerActionResultDecision, clearCaches: () => void, performHardNavigation: (url: string, historyMode?: "assign" | "replace") => void): boolean;
5
+ //#endregion
6
+ export { applyServerActionResultDecision };
@@ -0,0 +1,9 @@
1
+ //#region src/server/app-browser-server-action-navigation.ts
2
+ function applyServerActionResultDecision(decision, clearCaches, performHardNavigation) {
3
+ if (decision.kind !== "hardNavigate") return false;
4
+ if (decision.clearClientNavigationCaches) clearCaches();
5
+ performHardNavigation(decision.url, decision.historyMode);
6
+ return true;
7
+ }
8
+ //#endregion
9
+ export { applyServerActionResultDecision };
@@ -27,53 +27,96 @@ function getNavigationRuntimeRscBootstrap() {
27
27
  * immediately instead of polling with setTimeout.
28
28
  */
29
29
  function createProgressiveRscStream() {
30
- return new ReadableStream({ start(controller) {
31
- const vinext = getVinextBrowserGlobal();
32
- const runtimeRsc = getNavigationRuntimeRscBootstrap();
33
- const initialChunks = runtimeRsc?.rsc ?? vinext.__VINEXT_RSC_CHUNKS__ ?? [];
34
- for (const chunk of initialChunks) controller.enqueue(decodeRscEmbeddedChunk(chunk));
35
- if (runtimeRsc?.done || vinext.__VINEXT_RSC_DONE__) {
36
- controller.close();
37
- return;
38
- }
39
- let closed = false;
40
- let cancelDocumentCompletionCheck;
41
- const cancelPendingDocumentCompletionCheck = () => {
42
- const cancel = cancelDocumentCompletionCheck;
43
- cancelDocumentCompletionCheck = void 0;
44
- cancel?.();
45
- };
46
- const closeOnce = () => {
47
- if (!closed) {
48
- closed = true;
49
- cancelPendingDocumentCompletionCheck();
30
+ let cancelStream;
31
+ return new ReadableStream({
32
+ start(controller) {
33
+ const vinext = getVinextBrowserGlobal();
34
+ const runtimeRsc = getNavigationRuntimeRscBootstrap();
35
+ const initialChunks = runtimeRsc?.rsc ?? vinext.__VINEXT_RSC_CHUNKS__ ?? [];
36
+ for (const chunk of initialChunks) controller.enqueue(decodeRscEmbeddedChunk(chunk));
37
+ if (runtimeRsc?.done || vinext.__VINEXT_RSC_DONE__) {
50
38
  controller.close();
39
+ return;
51
40
  }
52
- };
53
- const errorOnce = () => {
54
- if (!closed) {
55
- closed = true;
56
- cancelPendingDocumentCompletionCheck();
57
- controller.error(createUnexpectedRscStreamCloseError());
41
+ let closed = false;
42
+ let cancelDocumentCompletionCheck;
43
+ const cancelPendingDocumentCompletionCheck = () => {
44
+ const cancel = cancelDocumentCompletionCheck;
45
+ cancelDocumentCompletionCheck = void 0;
46
+ cancel?.();
47
+ };
48
+ const closeOnce = () => {
49
+ if (!closed) {
50
+ closed = true;
51
+ cancelPendingDocumentCompletionCheck();
52
+ controller.close();
53
+ }
54
+ };
55
+ const scheduleCloseOnce = () => {
56
+ if (typeof queueMicrotask === "function") queueMicrotask(closeOnce);
57
+ else Promise.resolve().then(closeOnce);
58
+ };
59
+ const errorOnce = () => {
60
+ if (!closed) {
61
+ closed = true;
62
+ cancelPendingDocumentCompletionCheck();
63
+ controller.error(createUnexpectedRscStreamCloseError());
64
+ }
65
+ };
66
+ cancelStream = () => {
67
+ if (!closed) {
68
+ closed = true;
69
+ cancelPendingDocumentCompletionCheck();
70
+ }
71
+ };
72
+ const liveRuntimeRsc = getNavigationRuntime() === null ? null : ensureNavigationRuntimeRscBootstrap();
73
+ const arr = liveRuntimeRsc?.rsc ?? (vinext.__VINEXT_RSC_CHUNKS__ ??= []);
74
+ arr.push = function(...chunks) {
75
+ const length = Array.prototype.push.apply(this, chunks);
76
+ if (closed) return length;
77
+ for (const chunk of chunks) controller.enqueue(decodeRscEmbeddedChunk(chunk));
78
+ if (liveRuntimeRsc?.done || vinext.__VINEXT_RSC_DONE__) closeOnce();
79
+ return length;
80
+ };
81
+ if (liveRuntimeRsc) {
82
+ let done = Boolean(liveRuntimeRsc.done);
83
+ Object.defineProperty(liveRuntimeRsc, "done", {
84
+ configurable: true,
85
+ enumerable: true,
86
+ get() {
87
+ return done;
88
+ },
89
+ set(value) {
90
+ done = Boolean(value);
91
+ if (done) scheduleCloseOnce();
92
+ }
93
+ });
94
+ } else {
95
+ let done = Boolean(vinext.__VINEXT_RSC_DONE__);
96
+ Object.defineProperty(vinext, "__VINEXT_RSC_DONE__", {
97
+ configurable: true,
98
+ enumerable: true,
99
+ get() {
100
+ return done;
101
+ },
102
+ set(value) {
103
+ done = Boolean(value);
104
+ if (done) scheduleCloseOnce();
105
+ }
106
+ });
58
107
  }
59
- };
60
- const liveRuntimeRsc = getNavigationRuntime() === null ? null : ensureNavigationRuntimeRscBootstrap();
61
- const arr = liveRuntimeRsc?.rsc ?? (vinext.__VINEXT_RSC_CHUNKS__ ??= []);
62
- arr.push = function(...chunks) {
63
- const length = Array.prototype.push.apply(this, chunks);
64
- if (closed) return length;
65
- for (const chunk of chunks) controller.enqueue(decodeRscEmbeddedChunk(chunk));
66
- if (liveRuntimeRsc?.done || vinext.__VINEXT_RSC_DONE__) closeOnce();
67
- return length;
68
- };
69
- if (typeof document !== "undefined") if (document.readyState === "loading") {
70
- document.addEventListener("DOMContentLoaded", errorOnce);
71
- cancelDocumentCompletionCheck = () => document.removeEventListener("DOMContentLoaded", errorOnce);
72
- } else {
73
- const timeoutId = setTimeout(errorOnce);
74
- cancelDocumentCompletionCheck = () => clearTimeout(timeoutId);
108
+ if (typeof document !== "undefined") if (document.readyState === "loading") {
109
+ document.addEventListener("DOMContentLoaded", errorOnce);
110
+ cancelDocumentCompletionCheck = () => document.removeEventListener("DOMContentLoaded", errorOnce);
111
+ } else {
112
+ const timeoutId = setTimeout(errorOnce);
113
+ cancelDocumentCompletionCheck = () => clearTimeout(timeoutId);
114
+ }
115
+ },
116
+ cancel() {
117
+ cancelStream?.();
75
118
  }
76
- } });
119
+ });
77
120
  }
78
121
  //#endregion
79
122
  export { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal };
@@ -14,6 +14,7 @@ declare const APP_RENDER_OBSERVATION_KEY = "__renderObservation";
14
14
  declare const APP_ROUTE_KEY = "__route";
15
15
  declare const APP_ROOT_LAYOUT_KEY = "__rootLayout";
16
16
  declare const APP_SKIPPED_LAYOUT_IDS_KEY = "__skippedLayoutIds";
17
+ declare const APP_SOURCE_PAGE_KEY = "__sourcePage";
17
18
  declare const APP_SLOT_BINDINGS_KEY = "__slotBindings";
18
19
  /**
19
20
  * Static sibling segment names for the matched route, surfaced so the client
@@ -77,6 +78,7 @@ type AppElementsMetadata = {
77
78
  rootLayoutTreePath: string | null;
78
79
  skippedLayoutIds: readonly string[];
79
80
  slotBindings: readonly AppElementsSlotBinding[];
81
+ sourcePage: string | null;
80
82
  };
81
83
  type AppElementsWireElementKey = {
82
84
  kind: "layout";
@@ -104,6 +106,7 @@ type AppElementsWireMetadataInput = {
104
106
  routeId: string;
105
107
  rootLayoutTreePath: string | null;
106
108
  slotBindings?: readonly AppElementsSlotBinding[];
109
+ sourcePage?: string | null;
107
110
  };
108
111
  type AppElementsWireMetadataEntries = Readonly<{
109
112
  [APP_ROUTE_KEY]: string;
@@ -111,6 +114,7 @@ type AppElementsWireMetadataEntries = Readonly<{
111
114
  [APP_INTERCEPTION_CONTEXT_KEY]: string | null;
112
115
  [APP_LAYOUT_IDS_KEY]: readonly string[];
113
116
  [APP_ROOT_LAYOUT_KEY]: string | null;
117
+ [APP_SOURCE_PAGE_KEY]?: string;
114
118
  [APP_SLOT_BINDINGS_KEY]?: readonly AppElementsSlotBinding[];
115
119
  }>;
116
120
  /**
@@ -132,6 +136,7 @@ type AppElementsWireKeys = {
132
136
  readonly route: typeof APP_ROUTE_KEY;
133
137
  readonly skippedLayoutIds: typeof APP_SKIPPED_LAYOUT_IDS_KEY;
134
138
  readonly slotBindings: typeof APP_SLOT_BINDINGS_KEY;
139
+ readonly sourcePage: typeof APP_SOURCE_PAGE_KEY;
135
140
  };
136
141
  type AppElementsWireCodec = {
137
142
  readonly keys: AppElementsWireKeys;
@@ -184,4 +189,4 @@ declare function buildOutgoingAppPayload(input: {
184
189
  declare function readAppElementsMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
185
190
  declare const AppElementsWire: AppElementsWireCodec;
186
191
  //#endregion
187
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
192
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
@@ -16,6 +16,7 @@ const APP_RENDER_OBSERVATION_KEY = "__renderObservation";
16
16
  const APP_ROUTE_KEY = "__route";
17
17
  const APP_ROOT_LAYOUT_KEY = "__rootLayout";
18
18
  const APP_SKIPPED_LAYOUT_IDS_KEY = "__skippedLayoutIds";
19
+ const APP_SOURCE_PAGE_KEY = "__sourcePage";
19
20
  const APP_SLOT_BINDINGS_KEY = "__slotBindings";
20
21
  /**
21
22
  * Static sibling segment names for the matched route, surfaced so the client
@@ -175,7 +176,8 @@ function createAppElementsWireMetadataEntries(input) {
175
176
  [APP_ROUTE_KEY]: input.routeId,
176
177
  [APP_INTERCEPTION_CONTEXT_KEY]: input.interceptionContext,
177
178
  [APP_LAYOUT_IDS_KEY]: layoutIds,
178
- [APP_ROOT_LAYOUT_KEY]: input.rootLayoutTreePath
179
+ [APP_ROOT_LAYOUT_KEY]: input.rootLayoutTreePath,
180
+ ...input.sourcePage === null || input.sourcePage === void 0 ? {} : { [APP_SOURCE_PAGE_KEY]: input.sourcePage }
179
181
  };
180
182
  const entriesWithInterception = input.interception ? {
181
183
  ...entries,
@@ -330,6 +332,11 @@ function readArtifactCompatibilityMetadata(value) {
330
332
  if (value === void 0) return createArtifactCompatibilityEnvelope();
331
333
  return parseArtifactCompatibilityEnvelope(value) ?? createArtifactCompatibilityEnvelope();
332
334
  }
335
+ function readSourcePageMetadata(value) {
336
+ if (value === void 0 || value === null) return null;
337
+ if (typeof value !== "string" || !value.startsWith("/")) return null;
338
+ return value;
339
+ }
333
340
  function createMissingCacheEntryReuseProof() {
334
341
  return {
335
342
  kind: "runtime-cache-entry",
@@ -387,6 +394,7 @@ function readAppElementsMetadata(elements) {
387
394
  const interception = parseInterceptionMetadata(elements[APP_INTERCEPTION_KEY]);
388
395
  const artifactCompatibility = readArtifactCompatibilityMetadata(elements[APP_ARTIFACT_COMPATIBILITY_KEY]);
389
396
  const cacheEntryReuseProof = parseCacheEntryReuseProofMetadata(elements[APP_CACHE_ENTRY_REUSE_PROOF_KEY]);
397
+ const sourcePage = readSourcePageMetadata(elements[APP_SOURCE_PAGE_KEY]);
390
398
  return {
391
399
  artifactCompatibility,
392
400
  ...cacheEntryReuseProof ? { cacheEntryReuseProof } : {},
@@ -397,7 +405,8 @@ function readAppElementsMetadata(elements) {
397
405
  routeId,
398
406
  rootLayoutTreePath,
399
407
  skippedLayoutIds,
400
- slotBindings
408
+ slotBindings,
409
+ sourcePage
401
410
  };
402
411
  }
403
412
  const AppElementsWire = {
@@ -412,7 +421,8 @@ const AppElementsWire = {
412
421
  rootLayout: APP_ROOT_LAYOUT_KEY,
413
422
  route: APP_ROUTE_KEY,
414
423
  skippedLayoutIds: APP_SKIPPED_LAYOUT_IDS_KEY,
415
- slotBindings: APP_SLOT_BINDINGS_KEY
424
+ slotBindings: APP_SLOT_BINDINGS_KEY,
425
+ sourcePage: APP_SOURCE_PAGE_KEY
416
426
  },
417
427
  unmatchedSlotValue: APP_UNMATCHED_SLOT_WIRE_VALUE,
418
428
  createMetadataEntries: createAppElementsWireMetadataEntries,
@@ -430,4 +440,4 @@ const AppElementsWire = {
430
440
  withLayoutFlags
431
441
  };
432
442
  //#endregion
433
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
443
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
@@ -1,4 +1,4 @@
1
- import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
1
+ import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
2
2
 
3
3
  //#region src/server/app-elements.d.ts
4
4
  declare const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
@@ -6,4 +6,4 @@ declare function getMountedSlotIds(elements: AppElements): string[];
6
6
  declare function getMountedSlotIdsHeader(elements: AppElements): string | null;
7
7
  declare function resolveVisitedResponseInterceptionContext(requestInterceptionContext: string | null, payloadInterceptionContext: string | null): string | null;
8
8
  //#endregion
9
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, type LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
9
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, type LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
@@ -1,4 +1,4 @@
1
- import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
1
+ import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
2
2
  import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
3
3
  //#region src/server/app-elements.ts
4
4
  const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
@@ -15,4 +15,4 @@ function resolveVisitedResponseInterceptionContext(requestInterceptionContext, p
15
15
  return payloadInterceptionContext ?? requestInterceptionContext;
16
16
  }
17
17
  //#endregion
18
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
18
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
@@ -70,6 +70,7 @@ type AppFallbackRendererCallContext = {
70
70
  * render path. Defaults to `false` when no route is matched.
71
71
  */
72
72
  isEdgeRuntime?: boolean;
73
+ sourcePageSegments?: readonly string[] | null;
73
74
  };
74
75
  type AppFallbackRenderer<TModule extends AppPageModule = AppPageModule> = {
75
76
  renderErrorBoundary: (route: AppPageBoundaryRoute<TModule> | null, error: unknown, isRscRequest: boolean, request: Request, matchedParams: AppPageParams | undefined, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext, callContext?: AppFallbackRendererCallContext) => Promise<Response | null>;
@@ -88,6 +88,7 @@ function createAppFallbackRenderer(options) {
88
88
  route,
89
89
  renderToReadableStream: rscRenderer,
90
90
  scriptNonce,
91
+ sourcePageSegments: callContext?.sourcePageSegments,
91
92
  statusCode
92
93
  });
93
94
  },
@@ -122,7 +123,8 @@ function createAppFallbackRenderer(options) {
122
123
  route,
123
124
  renderToReadableStream: rscRenderer,
124
125
  sanitizeErrorForClient: sanitizer,
125
- scriptNonce
126
+ scriptNonce,
127
+ sourcePageSegments: callContext?.sourcePageSegments
126
128
  });
127
129
  }
128
130
  };
@@ -174,7 +174,7 @@ function createOptimisticRouteTemplate(options) {
174
174
  href: options.href,
175
175
  routeManifest: options.routeManifest
176
176
  });
177
- if (match === null || !match.route.isDynamic) return null;
177
+ if (match === null || !options.allowLoadingShell && !match.route.isDynamic) return null;
178
178
  if (options.interceptionContext !== null) return null;
179
179
  const metadata = AppElementsWire.readMetadata(options.elements);
180
180
  if (metadata.interception !== null || metadata.interceptionContext !== null) return null;
@@ -205,7 +205,7 @@ function resolveOptimisticNavigationPayload(options) {
205
205
  href: options.href,
206
206
  routeManifest: options.routeManifest
207
207
  });
208
- if (match === null || !match.route.isDynamic) return null;
208
+ if (match === null) return null;
209
209
  const template = options.templates.get(getOptimisticRouteTemplateKey({
210
210
  interceptionContext: options.interceptionContext,
211
211
  mountedSlotsHeader: options.mountedSlotsHeader,
@@ -50,6 +50,7 @@ type AppPageBoundaryRenderCommonOptions<TModule extends AppPageModule = AppPageM
50
50
  resolveChildSegments: (routeSegments: readonly string[], treePosition: number, params: AppPageParams) => string[];
51
51
  rootLayouts: readonly (TModule | null | undefined)[];
52
52
  scriptNonce?: string;
53
+ sourcePageSegments?: readonly string[] | null;
53
54
  };
54
55
  type RenderAppPageHttpAccessFallbackOptions<TModule extends AppPageModule = AppPageModule> = {
55
56
  boundaryComponent?: AppPageComponent | null;
@@ -1,14 +1,15 @@
1
+ import { NEVER_CACHE_CONTROL } from "./cache-control.js";
1
2
  import { AppElementsWire } from "./app-elements-wire.js";
2
3
  import "./app-elements.js";
4
+ import DefaultGlobalError from "../shims/default-global-error.js";
3
5
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
4
6
  import { ErrorBoundary, GlobalErrorBoundary } from "../shims/error-boundary.js";
5
7
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
6
8
  import { MetadataHead, ViewportHead } from "../shims/metadata.js";
7
9
  import { resolveAppPageSpecialError } from "./app-page-execution.js";
8
10
  import { resolveAppPageHead } from "./app-page-head.js";
9
- import { createAppPageLayoutEntries } from "./app-page-route-wiring.js";
11
+ import { createAppPageLayoutEntries, createAppPageSourcePage } from "./app-page-route-wiring.js";
10
12
  import { buildClientHookErrorMessage } from "../shims/client-hook-error.js";
11
- import DefaultGlobalError from "../shims/default-global-error.js";
12
13
  import { renderAppPageBoundaryResponse, resolveAppPageErrorBoundary, resolveAppPageHttpAccessBoundaryModule, wrapAppPageBoundaryElement } from "./app-page-boundary.js";
13
14
  import { createAppPageFontData, renderAppPageHtmlResponse } from "./app-page-stream.js";
14
15
  import { Fragment, createElement } from "react";
@@ -76,12 +77,14 @@ function resolveHttpAccessFallbackHeadLayoutTreePositions(route, layoutModules)
76
77
  function createAppPageBoundaryRscPayload(options) {
77
78
  const routeId = AppElementsWire.encodeRouteId(options.pathname, null);
78
79
  const layoutEntries = createAppPageBoundaryLayoutEntries(options.route, options.layoutModules);
80
+ const sourcePageSegments = options.sourcePageSegments ?? options.route?.routeSegments;
79
81
  return {
80
82
  ...AppElementsWire.createMetadataEntries({
81
83
  interceptionContext: null,
82
84
  layoutIds: layoutEntries.map((entry) => entry.id),
83
85
  rootLayoutTreePath: layoutEntries[0]?.treePath ?? null,
84
- routeId
86
+ routeId,
87
+ sourcePage: sourcePageSegments ? createAppPageSourcePage(sourcePageSegments) : null
85
88
  }),
86
89
  [routeId]: options.element
87
90
  };
@@ -122,7 +125,8 @@ async function renderAppPageBoundaryElementResponse(options) {
122
125
  element: options.element,
123
126
  layoutModules: options.layoutModules,
124
127
  pathname,
125
- route: options.route
128
+ route: options.route,
129
+ sourcePageSegments: options.sourcePageSegments
126
130
  }),
127
131
  isEdgeRuntime: options.isEdgeRuntime,
128
132
  isRscRequest: options.isRscRequest,
@@ -261,16 +265,25 @@ async function renderAppPageErrorBoundary(options) {
261
265
  skipLayoutWrapping: errorBoundary.isGlobalError
262
266
  });
263
267
  };
264
- const renderWith = (BoundaryComponent) => renderAppPageBoundaryElementResponse({
265
- ...options,
266
- element: buildElement(BoundaryComponent),
267
- initialDevServerError: rawError,
268
- layoutModules,
269
- navigationParams: matchedParams,
270
- route: options.route,
271
- routePattern: options.route?.pattern,
272
- status: 200
273
- });
268
+ const renderWith = async (BoundaryComponent) => {
269
+ const response = await renderAppPageBoundaryElementResponse({
270
+ ...options,
271
+ element: buildElement(BoundaryComponent),
272
+ initialDevServerError: rawError,
273
+ layoutModules,
274
+ navigationParams: matchedParams,
275
+ route: options.route,
276
+ routePattern: options.route?.pattern,
277
+ status: errorBoundary.isGlobalError ? 500 : 200
278
+ });
279
+ if (errorBoundary.isGlobalError) {
280
+ response.headers.set("Cache-Control", NEVER_CACHE_CONTROL);
281
+ response.headers.delete("CDN-Cache-Control");
282
+ response.headers.delete("Cloudflare-CDN-Cache-Control");
283
+ response.headers.delete("Cache-Tag");
284
+ }
285
+ return response;
286
+ };
274
287
  try {
275
288
  return await renderWith(errorBoundary.component);
276
289
  } catch (renderError) {
@@ -0,0 +1,53 @@
1
+ import { CacheControlMetadata } from "../shims/cache.js";
2
+ import { NavigationContext } from "../shims/navigation.js";
3
+ import { AppPageFontPreload } from "./app-page-execution.js";
4
+ import { RootParams } from "../shims/root-params.js";
5
+ import { AppPageSsrHandler } from "./app-page-stream.js";
6
+ import { createAppPageRenderObservation } from "./app-page-render-observation.js";
7
+ import { ReactNode } from "react";
8
+
9
+ //#region src/server/app-page-cache-render.d.ts
10
+ type AppPageRenderableElement = ReactNode | Record<string, ReactNode>;
11
+ type AppPageCacheRoute = {
12
+ pattern: string;
13
+ routeSegments: readonly string[];
14
+ };
15
+ type RenderAppPageCacheArtifactsOptions = {
16
+ basePath?: string;
17
+ captureRscData: boolean;
18
+ cleanPathname: string;
19
+ clientTraceMetadata?: readonly string[];
20
+ element: AppPageRenderableElement;
21
+ getFontLinks: () => string[];
22
+ getFontPreloads: () => AppPageFontPreload[];
23
+ getFontStyles: () => string[];
24
+ getNavigationContext: () => NavigationContext | null;
25
+ loadSsrHandler: () => Promise<AppPageSsrHandler>;
26
+ mountedSlotsHeader?: string | null;
27
+ navigationParams: Record<string, unknown>;
28
+ onError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
29
+ reactMaxHeadersLength?: number;
30
+ renderToReadableStream: (element: AppPageRenderableElement, options: {
31
+ onError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
32
+ }) => ReadableStream<Uint8Array>;
33
+ rootParams?: RootParams;
34
+ route: AppPageCacheRoute;
35
+ waitForAllReady?: boolean;
36
+ };
37
+ type RenderAppPageCacheArtifactsResult = {
38
+ cacheControl?: CacheControlMetadata;
39
+ html: string;
40
+ htmlRenderObservation: ReturnType<typeof createAppPageRenderObservation>;
41
+ rscData?: ArrayBuffer;
42
+ rscRenderObservation?: ReturnType<typeof createAppPageRenderObservation>;
43
+ tags: string[];
44
+ };
45
+ /**
46
+ * Render an App page element to HTML (and optionally its RSC payload) for cache
47
+ * storage. Combines the RSC stream, SSR handler, observation consumption, and
48
+ * cache-tag construction used by both normal ISR revalidation and PPR fallback
49
+ * shell regeneration.
50
+ */
51
+ declare function renderAppPageCacheArtifacts(options: RenderAppPageCacheArtifactsOptions): Promise<RenderAppPageCacheArtifactsResult>;
52
+ //#endregion
53
+ export { RenderAppPageCacheArtifactsOptions, RenderAppPageCacheArtifactsResult, renderAppPageCacheArtifacts };