@rangojs/router 0.27.0 → 0.29.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.
- package/dist/bin/rango.js +1 -1
- package/dist/types/__internal.d.ts +7 -1
- package/dist/types/browser/action-fence.d.ts +2 -1
- package/dist/types/browser/event-controller.d.ts +8 -2
- package/dist/types/browser/history-state.d.ts +3 -9
- package/dist/types/browser/navigation-store.d.ts +8 -6
- package/dist/types/browser/partial-update.d.ts +11 -0
- package/dist/types/browser/react/filter-segment-order.d.ts +2 -2
- package/dist/types/browser/react/use-action.d.ts +7 -2
- package/dist/types/browser/react/use-handle.d.ts +19 -16
- package/dist/types/browser/react/use-link-status.d.ts +5 -2
- package/dist/types/browser/segment-reconciler.d.ts +32 -4
- package/dist/types/browser/types.d.ts +24 -5
- package/dist/types/browser/wire-protocol.d.ts +26 -0
- package/dist/types/cache/cache-key-utils.d.ts +11 -5
- package/dist/types/cache/cache-scope.d.ts +34 -22
- package/dist/types/cache/cf/cf-cache-constants.d.ts +2 -2
- package/dist/types/cache/cf/cf-cache-store.d.ts +47 -65
- package/dist/types/cache/cf/cf-kv-utils.d.ts +1 -1
- package/dist/types/cache/handle-snapshot.d.ts +9 -4
- package/dist/types/cache/segment-codec.d.ts +14 -0
- package/dist/types/cache/shell-snapshot.d.ts +1 -1
- package/dist/types/cache/taint.d.ts +5 -3
- package/dist/types/cache/types.d.ts +7 -3
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +8 -6
- package/dist/types/prefetch-markers.d.ts +5 -14
- package/dist/types/prerender/store.d.ts +31 -0
- package/dist/types/prerender/warm-request.d.ts +3 -3
- package/dist/types/prerender.d.ts +2 -2
- package/dist/types/route-name.d.ts +5 -0
- package/dist/types/router/error-handling.d.ts +11 -5
- package/dist/types/router/instrument.d.ts +4 -3
- package/dist/types/router/intercept-resolution.d.ts +25 -9
- package/dist/types/router/match-context.d.ts +6 -11
- package/dist/types/router/match-handlers.d.ts +2 -6
- package/dist/types/router/match-middleware/background-revalidation.d.ts +13 -22
- package/dist/types/router/match-middleware/cache-lookup.d.ts +34 -86
- package/dist/types/router/match-middleware/segment-resolution.d.ts +8 -6
- package/dist/types/router/navigation-snapshot.d.ts +7 -0
- package/dist/types/router/prerender-match.d.ts +21 -6
- package/dist/types/router/preview-match.d.ts +2 -7
- package/dist/types/router/request-classification.d.ts +5 -0
- package/dist/types/router/router-context.d.ts +7 -46
- package/dist/types/router/router-interfaces.d.ts +8 -14
- package/dist/types/router/segment-resolution/helpers.d.ts +19 -3
- package/dist/types/router/segment-resolution/loader-cache.d.ts +3 -3
- package/dist/types/router/segment-resolution/loader-mask.d.ts +4 -4
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +20 -18
- package/dist/types/router/segment-resolution/resolution-pass.d.ts +95 -0
- package/dist/types/router/segment-resolution/revalidation.d.ts +82 -31
- package/dist/types/router/segment-resolution/streamed-handler-boundary.d.ts +2 -0
- package/dist/types/router/segment-resolution.d.ts +1 -2
- package/dist/types/router/segment-wrappers.d.ts +11 -48
- package/dist/types/router/telemetry.d.ts +2 -0
- package/dist/types/router/types.d.ts +11 -1
- package/dist/types/rsc/full-payload.d.ts +2 -2
- package/dist/types/rsc/handler-context.d.ts +6 -6
- package/dist/types/rsc/json-route-result.d.ts +5 -9
- package/dist/types/rsc/request-stages.d.ts +203 -0
- package/dist/types/rsc/response-cache-serve.d.ts +7 -12
- package/dist/types/rsc/response-route-handler.d.ts +2 -2
- package/dist/types/rsc/routine-plan.d.ts +1 -1
- package/dist/types/rsc/server-action.d.ts +2 -2
- package/dist/types/rsc/shell-capture-constants.d.ts +1 -1
- package/dist/types/rsc/shell-capture.d.ts +132 -15
- package/dist/types/rsc/shell-serve.d.ts +37 -12
- package/dist/types/server/context.d.ts +9 -8
- package/dist/types/server/handle-store.d.ts +16 -0
- package/dist/types/server/render-pass.d.ts +72 -0
- package/dist/types/server/request-context.d.ts +53 -104
- package/dist/types/server/rewrite-trail.d.ts +2 -2
- package/dist/types/testing/dispatch.d.ts +35 -18
- package/dist/types/testing/render-route.d.ts +43 -8
- package/dist/types/testing/serve-shell-request.d.ts +8 -1
- package/dist/types/types/cache-types.d.ts +6 -3
- package/dist/types/types/error-types.d.ts +30 -3
- package/dist/types/types/handler-context.d.ts +9 -1
- package/dist/types/types/segments.d.ts +1 -1
- package/dist/types/vite/discovery/build-discovery-phase.d.ts +40 -0
- package/dist/types/vite/discovery/build-env.d.ts +22 -0
- package/dist/types/vite/discovery/bundle-scan-phase.d.ts +12 -0
- package/dist/types/vite/discovery/dev-prerender-cache.d.ts +3 -2
- package/dist/types/vite/discovery/dev-server-phase.d.ts +26 -0
- package/dist/types/vite/discovery/discovery-errors.d.ts +1 -1
- package/dist/types/vite/discovery/state.d.ts +12 -0
- package/dist/types/vite/plugins/version-plugin.d.ts +1 -1
- package/dist/types/vite/plugins/virtual-entries.d.ts +1 -1
- package/dist/types/vite/router-discovery.d.ts +8 -47
- package/dist/types/vite/temp-rsc-server.d.ts +39 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +9 -0
- package/dist/types/wire-params.d.ts +39 -0
- package/dist/vite/index.js +3822 -3727
- package/package.json +1 -1
- package/skills/cache-guide/SKILL.md +8 -5
- package/skills/caching/SKILL.md +37 -18
- package/skills/client-urls/SKILL.md +4 -2
- package/skills/document-cache/SKILL.md +13 -1
- package/skills/handler-use/SKILL.md +1 -1
- package/skills/hooks/SKILL.md +1 -1
- package/skills/hooks/data.md +8 -1
- package/skills/hooks/handle-and-actions.md +33 -2
- package/skills/hooks/navigation.md +121 -15
- package/skills/hooks/state.md +6 -4
- package/skills/hooks/urls.md +16 -5
- package/skills/intercept/SKILL.md +23 -7
- package/skills/middleware/SKILL.md +18 -0
- package/skills/observability/SKILL.md +30 -0
- package/skills/ppr/SKILL.md +18 -3
- package/skills/prerender/SKILL.md +39 -15
- package/skills/rango/SKILL.md +5 -1
- package/skills/server-actions/SKILL.md +15 -1
- package/skills/testing/client-components.md +25 -18
- package/skills/testing/response-routes.md +6 -4
- package/skills/testing/serve-shell-request.md +7 -7
- package/skills/use-cache/SKILL.md +46 -8
- package/skills/view-transitions/SKILL.md +1 -1
- package/src/__internal.ts +7 -1
- package/src/browser/action-fence.ts +2 -1
- package/src/browser/connection-warmup.ts +3 -1
- package/src/browser/event-controller.ts +37 -13
- package/src/browser/history-state.ts +6 -12
- package/src/browser/navigation-bridge.ts +59 -26
- package/src/browser/navigation-client.ts +20 -25
- package/src/browser/navigation-store.ts +25 -27
- package/src/browser/navigation-transaction.ts +4 -1
- package/src/browser/network-error-handler.ts +4 -0
- package/src/browser/partial-update.ts +33 -6
- package/src/browser/prefetch/cache.ts +2 -1
- package/src/browser/prefetch/fetch.ts +8 -16
- package/src/browser/prefetch/queue.ts +4 -4
- package/src/browser/react/NavigationProvider.tsx +2 -1
- package/src/browser/react/filter-segment-order.ts +2 -2
- package/src/browser/react/use-action.ts +24 -48
- package/src/browser/react/use-handle.ts +22 -18
- package/src/browser/react/use-link-status.ts +48 -60
- package/src/browser/react/use-navigation.ts +92 -41
- package/src/browser/rsc-router.tsx +1 -0
- package/src/browser/segment-reconciler.ts +109 -53
- package/src/browser/server-action-bridge.ts +81 -61
- package/src/browser/types.ts +25 -5
- package/src/browser/wire-protocol.ts +43 -0
- package/src/cache/cache-key-utils.ts +11 -5
- package/src/cache/cache-runtime.ts +132 -75
- package/src/cache/cache-scope.ts +110 -64
- package/src/cache/cf/cf-cache-constants.ts +2 -2
- package/src/cache/cf/cf-cache-store.ts +486 -874
- package/src/cache/cf/cf-kv-utils.ts +1 -1
- package/src/cache/document-cache.ts +64 -46
- package/src/cache/handle-snapshot.ts +19 -7
- package/src/cache/read-through-swr.ts +20 -18
- package/src/cache/segment-codec.ts +55 -0
- package/src/cache/shell-snapshot.ts +2 -2
- package/src/cache/tag-invalidation.ts +6 -2
- package/src/cache/taint.ts +5 -3
- package/src/cache/types.ts +7 -3
- package/src/cache/vercel/vercel-cache-store.ts +243 -310
- package/src/handles/pushed-by.ts +1 -1
- package/src/prefetch-markers.ts +5 -16
- package/src/prerender/store.ts +76 -0
- package/src/prerender/warm-request.ts +8 -4
- package/src/prerender.ts +2 -2
- package/src/route-name.ts +8 -0
- package/src/router/error-handling.ts +22 -10
- package/src/router/instrument.ts +4 -3
- package/src/router/intercept-resolution.ts +82 -75
- package/src/router/loader-resolution.ts +5 -4
- package/src/router/match-api.ts +5 -5
- package/src/router/match-context.ts +23 -12
- package/src/router/match-handlers.ts +8 -20
- package/src/router/match-middleware/background-revalidation.ts +46 -57
- package/src/router/match-middleware/cache-lookup.ts +677 -726
- package/src/router/match-middleware/cache-store.ts +4 -8
- package/src/router/match-middleware/intercept-resolution.ts +3 -23
- package/src/router/match-middleware/segment-resolution.ts +34 -61
- package/src/router/middleware.ts +69 -11
- package/src/router/navigation-snapshot.ts +14 -4
- package/src/router/prerender-match.ts +100 -44
- package/src/router/preview-match.ts +6 -41
- package/src/router/request-classification.ts +13 -7
- package/src/router/route-snapshot.ts +2 -5
- package/src/router/router-context.ts +10 -95
- package/src/router/router-interfaces.ts +8 -14
- package/src/router/segment-resolution/helpers.ts +49 -13
- package/src/router/segment-resolution/loader-cache.ts +15 -9
- package/src/router/segment-resolution/loader-mask.ts +5 -5
- package/src/router/segment-resolution/prefetch-deferral.ts +30 -27
- package/src/router/segment-resolution/resolution-pass.ts +139 -0
- package/src/router/segment-resolution/revalidation.ts +939 -789
- package/src/router/segment-resolution/streamed-handler-boundary.ts +3 -0
- package/src/router/segment-resolution.ts +4 -13
- package/src/router/segment-wrappers.ts +51 -269
- package/src/router/telemetry.ts +5 -0
- package/src/router/types.ts +11 -1
- package/src/router.ts +19 -17
- package/src/rsc/full-payload.ts +6 -5
- package/src/rsc/handler-context.ts +8 -14
- package/src/rsc/handler.ts +126 -507
- package/src/rsc/json-route-result.ts +5 -9
- package/src/rsc/loader-fetch.ts +6 -5
- package/src/rsc/progressive-enhancement.ts +5 -0
- package/src/rsc/request-stages.ts +759 -0
- package/src/rsc/response-cache-serve.ts +10 -14
- package/src/rsc/response-route-handler.ts +13 -5
- package/src/rsc/rewrite-passes.ts +2 -1
- package/src/rsc/routine-plan.ts +1 -1
- package/src/rsc/rsc-rendering.ts +164 -349
- package/src/rsc/server-action.ts +87 -113
- package/src/rsc/shell-capture-constants.ts +1 -1
- package/src/rsc/shell-capture.ts +275 -227
- package/src/rsc/shell-serve.ts +121 -18
- package/src/rsc/ssr-setup.ts +5 -4
- package/src/segment-system.tsx +3 -3
- package/src/server/context.ts +22 -25
- package/src/server/handle-store.ts +55 -0
- package/src/server/render-pass.ts +291 -0
- package/src/server/request-context.ts +75 -115
- package/src/server/rewrite-trail.ts +6 -4
- package/src/ssr/index.tsx +1 -1
- package/src/testing/dispatch.ts +226 -710
- package/src/testing/e2e/page-helpers.ts +2 -2
- package/src/testing/render-route.tsx +199 -13
- package/src/testing/serve-shell-request.ts +36 -40
- package/src/types/cache-types.ts +6 -3
- package/src/types/error-types.ts +30 -3
- package/src/types/handler-context.ts +12 -1
- package/src/types/segments.ts +1 -1
- package/src/vite/discovery/build-discovery-phase.ts +204 -0
- package/src/vite/discovery/build-env.ts +148 -0
- package/src/vite/discovery/bundle-scan-phase.ts +128 -0
- package/src/vite/discovery/dev-prerender-cache.ts +8 -3
- package/src/vite/discovery/dev-server-phase.ts +1776 -0
- package/src/vite/discovery/discover-routers.ts +1 -1
- package/src/vite/discovery/discovery-errors.ts +1 -1
- package/src/vite/discovery/prerender-collection.ts +24 -39
- package/src/vite/discovery/state.ts +15 -0
- package/src/vite/plugins/version-plugin.ts +1 -1
- package/src/vite/plugins/virtual-entries.ts +1 -1
- package/src/vite/router-discovery.ts +29 -2428
- package/src/vite/temp-rsc-server.ts +223 -0
- package/src/vite/utils/prerender-utils.ts +47 -0
- package/src/wire-params.ts +40 -0
- package/dist/types/router/segment-resolution/fresh.d.ts +0 -72
- package/src/router/segment-resolution/fresh.ts +0 -945
package/src/prerender/store.ts
CHANGED
|
@@ -159,6 +159,82 @@ export function createPrerenderStore(): PrerenderStore | null {
|
|
|
159
159
|
};
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
/**
|
|
163
|
+
* The segments of a prerendered URL's intercept variant (`/i`): the main
|
|
164
|
+
* variant's without the intercepted route's own (`belongsToRoute`: its
|
|
165
|
+
* handler, layouts and slots), then the intercept's. A render under an
|
|
166
|
+
* intercept skips the route's entry (resolveAllSegments), so the variant
|
|
167
|
+
* holds what a cache() intercept record holds. The producer
|
|
168
|
+
* (matchForPrerender) encodes `interceptHandles` for exactly these segments.
|
|
169
|
+
*/
|
|
170
|
+
export function interceptVariantSegments(
|
|
171
|
+
segments: SerializedSegmentData[],
|
|
172
|
+
interceptSegments: SerializedSegmentData[],
|
|
173
|
+
): SerializedSegmentData[] {
|
|
174
|
+
return [
|
|
175
|
+
...segments.filter((s) => s.metadata.belongsToRoute !== true),
|
|
176
|
+
...interceptSegments,
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* The intercept variant as served under the intercept the match selected
|
|
182
|
+
* (findInterceptForRoute): its main segments and that intercept's slot,
|
|
183
|
+
* `slotId` in `intercept:<routeName>`. The build bakes every intercept that
|
|
184
|
+
* can target the route, since it cannot evaluate when(). Null when the
|
|
185
|
+
* variant does not hold that slot: the request renders live. The handles
|
|
186
|
+
* string is kept whole; decodeStoredEntry (cache-lookup.ts) replays only the
|
|
187
|
+
* served segments' pushes.
|
|
188
|
+
*/
|
|
189
|
+
export function selectInterceptVariant(
|
|
190
|
+
entry: PrerenderEntry,
|
|
191
|
+
slotId: string,
|
|
192
|
+
routeName: string,
|
|
193
|
+
): PrerenderEntry | null {
|
|
194
|
+
const namespace = `intercept:${routeName}`;
|
|
195
|
+
let found = false;
|
|
196
|
+
const segments = entry.segments.filter(({ metadata }) => {
|
|
197
|
+
if (!metadata.namespace?.startsWith("intercept:")) return true;
|
|
198
|
+
if (metadata.id !== slotId || metadata.namespace !== namespace) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
found = true;
|
|
202
|
+
return true;
|
|
203
|
+
});
|
|
204
|
+
return found ? { segments, handles: entry.handles } : null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* The manifest entries ([key, PrerenderEntry JSON]) one prerendered URL
|
|
209
|
+
* bakes, keyed as the production store's get() reads them. The intercept
|
|
210
|
+
* variant (`/i`) holds interceptVariantSegments with the handle string the
|
|
211
|
+
* producer encoded for it. Written by the build
|
|
212
|
+
* (vite/discovery/prerender-collection.ts) and serveShellRequest.
|
|
213
|
+
*/
|
|
214
|
+
export function prerenderManifestEntries(
|
|
215
|
+
result: PrerenderEntry & {
|
|
216
|
+
routeName: string;
|
|
217
|
+
interceptSegments?: SerializedSegmentData[];
|
|
218
|
+
interceptHandles?: string;
|
|
219
|
+
},
|
|
220
|
+
paramHash: string,
|
|
221
|
+
): Array<[key: string, value: string]> {
|
|
222
|
+
const { segments, handles, interceptSegments } = result;
|
|
223
|
+
const key = `${result.routeName}/${paramHash}`;
|
|
224
|
+
const entries: Array<[string, string]> = [
|
|
225
|
+
[key, JSON.stringify({ segments, handles })],
|
|
226
|
+
];
|
|
227
|
+
if (interceptSegments?.length) {
|
|
228
|
+
const intercept = interceptVariantSegments(segments, interceptSegments);
|
|
229
|
+
const interceptHandles = result.interceptHandles ?? "";
|
|
230
|
+
entries.push([
|
|
231
|
+
`${key}/i`,
|
|
232
|
+
JSON.stringify({ segments: intercept, handles: interceptHandles }),
|
|
233
|
+
]);
|
|
234
|
+
}
|
|
235
|
+
return entries;
|
|
236
|
+
}
|
|
237
|
+
|
|
162
238
|
/**
|
|
163
239
|
* Create a static segment store.
|
|
164
240
|
* Production only: backed by globalThis.__STATIC_MANIFEST injected at build time.
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { HandlerCacheConfig } from "../rsc/types.js";
|
|
11
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
ShellCaptureDebugEvent,
|
|
13
|
+
ShellCaptureState,
|
|
14
|
+
} from "../rsc/shell-capture.js";
|
|
12
15
|
import type { PrerenderWarmCaches } from "./on-demand.js";
|
|
13
16
|
|
|
14
17
|
/** What one warm request did: written by the layers, read by the trigger. */
|
|
@@ -36,7 +39,7 @@ export interface PrerenderWarmRecord extends PrerenderWarmCaches {
|
|
|
36
39
|
/** What the helpers read; a derived capture context inherits the record. */
|
|
37
40
|
export interface WarmContext {
|
|
38
41
|
_prerenderWarm?: PrerenderWarmRecord;
|
|
39
|
-
|
|
42
|
+
_shellCaptureState?: Pick<ShellCaptureState, "run">;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
/**
|
|
@@ -79,14 +82,15 @@ export function readWarmMark(
|
|
|
79
82
|
* "use cache" in-flight dedup lives outside the store, so a wrapper would
|
|
80
83
|
* miss both.
|
|
81
84
|
*
|
|
82
|
-
* False in the warm's own shell capture (`
|
|
85
|
+
* False in the warm's own shell capture (`_shellCaptureState`): it runs after
|
|
83
86
|
* the warm's writes settled and must replay them, or it would render every
|
|
84
87
|
* handler a second time and could bake another generation than the one just
|
|
85
88
|
* written.
|
|
86
89
|
*/
|
|
87
90
|
export function isWarmReplace(ctx: WarmContext | null | undefined): boolean {
|
|
88
91
|
return (
|
|
89
|
-
ctx?._prerenderWarm?.mode === "replace" &&
|
|
92
|
+
ctx?._prerenderWarm?.mode === "replace" &&
|
|
93
|
+
ctx._shellCaptureState?.run !== true
|
|
90
94
|
);
|
|
91
95
|
}
|
|
92
96
|
|
package/src/prerender.ts
CHANGED
|
@@ -490,8 +490,8 @@ export function isPrerenderPassthrough(
|
|
|
490
490
|
* A build handler signals passthrough by returning `ctx.passthrough()` (the
|
|
491
491
|
* PRERENDER_PASSTHROUGH sentinel), which lands on the segment's `component`.
|
|
492
492
|
* But when the route declares `loading()`, the handler result is deferred
|
|
493
|
-
* upstream (
|
|
494
|
-
* to the sentinel rather than the sentinel itself — a synchronous
|
|
493
|
+
* upstream (resolveEntryHandler), so `component` is a thenable
|
|
494
|
+
* resolving to the sentinel rather than the sentinel itself — a synchronous
|
|
495
495
|
* `isPrerenderPassthrough(component)` on the Promise returns false and the build
|
|
496
496
|
* bakes a corrupt artifact instead of deferring. Resolve thenables first.
|
|
497
497
|
*
|
package/src/route-name.ts
CHANGED
|
@@ -63,3 +63,11 @@ export function validateUserRouteName(name: string): void {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The route key's last name segment ("item" for "shop.item"). An intercept
|
|
69
|
+
* that targets it is selected when none targets the full key (match-api.ts).
|
|
70
|
+
*/
|
|
71
|
+
export function localRouteName(routeKey: string): string {
|
|
72
|
+
return routeKey.slice(routeKey.lastIndexOf(".") + 1);
|
|
73
|
+
}
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
import { createElement, type ReactNode } from "react";
|
|
9
9
|
import type { EntryData } from "../server/context.js";
|
|
10
10
|
import { runIdentityExempt } from "../cache/cache-exec-scope.js";
|
|
11
|
+
import {
|
|
12
|
+
_getRequestContext,
|
|
13
|
+
isBackgroundWork,
|
|
14
|
+
} from "../server/request-context.js";
|
|
11
15
|
import type {
|
|
12
16
|
ResolvedSegment,
|
|
13
17
|
ErrorInfo,
|
|
@@ -39,7 +43,7 @@ export interface InvokeOnErrorContext<TEnv = any> {
|
|
|
39
43
|
isPartial?: boolean;
|
|
40
44
|
handledByBoundary?: boolean;
|
|
41
45
|
metadata?: Record<string, unknown>;
|
|
42
|
-
/**
|
|
46
|
+
/** performance.now() at request entry; the request context's by default. */
|
|
43
47
|
requestStartTime?: number;
|
|
44
48
|
}
|
|
45
49
|
|
|
@@ -50,6 +54,12 @@ export interface InvokeOnErrorContext<TEnv = any> {
|
|
|
50
54
|
* This is a shared utility used by both the router and RSC handler to ensure
|
|
51
55
|
* consistent error callback behavior across the codebase.
|
|
52
56
|
*
|
|
57
|
+
* `background` is set inside runAsBackgroundWork (server/request-context.ts),
|
|
58
|
+
* and `duration` and `env` come from the request context on the ALS
|
|
59
|
+
* (`_handlerStart`, `env`) when the call site leaves them out, so no call
|
|
60
|
+
* site has to know. A Prerender pass's ctx.env throws without buildEnv, so
|
|
61
|
+
* the walk never reads it eagerly.
|
|
62
|
+
*
|
|
53
63
|
* @param onError - The onError callback to invoke (may be undefined)
|
|
54
64
|
* @param error - The error that occurred
|
|
55
65
|
* @param phase - The phase where the error occurred
|
|
@@ -66,9 +76,10 @@ export function invokeOnError<TEnv = any>(
|
|
|
66
76
|
if (!onError) return;
|
|
67
77
|
|
|
68
78
|
const errorObj = error instanceof Error ? error : new Error(String(error));
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
const reqCtx = _getRequestContext();
|
|
80
|
+
const background = isBackgroundWork() || undefined;
|
|
81
|
+
const start = context.requestStartTime ?? reqCtx?._handlerStart;
|
|
82
|
+
const duration = start !== undefined ? performance.now() - start : undefined;
|
|
72
83
|
|
|
73
84
|
const errorContext: OnErrorContext<TEnv> = {
|
|
74
85
|
error: errorObj,
|
|
@@ -84,10 +95,11 @@ export function invokeOnError<TEnv = any>(
|
|
|
84
95
|
loaderName: context.loaderName,
|
|
85
96
|
middlewareId: context.middlewareId,
|
|
86
97
|
actionId: context.actionId,
|
|
87
|
-
env: context.env,
|
|
98
|
+
env: context.env ?? (reqCtx?.env as TEnv | undefined),
|
|
88
99
|
duration,
|
|
89
100
|
isPartial: context.isPartial,
|
|
90
|
-
|
|
101
|
+
background,
|
|
102
|
+
handledByBoundary: background ? false : context.handledByBoundary,
|
|
91
103
|
stack: errorObj.stack,
|
|
92
104
|
metadata: context.metadata,
|
|
93
105
|
};
|
|
@@ -111,10 +123,10 @@ export function invokeOnError<TEnv = any>(
|
|
|
111
123
|
/**
|
|
112
124
|
* First non-undefined `pick(orphan)` over the routeless entries in
|
|
113
125
|
* `entry.layout` and, recursively, in theirs: depth-first in render order
|
|
114
|
-
* (resolveOrphanLayout in segment-resolution/
|
|
115
|
-
* entry nested in another renders (a layout() after a
|
|
116
|
-
* layout() in a routeless wrapper); a one-level scan
|
|
117
|
-
* intercepts it declares (#926).
|
|
126
|
+
* (resolveOrphanLayout in segment-resolution/revalidation.ts).
|
|
127
|
+
* Since #922 a routeless entry nested in another renders (a layout() after a
|
|
128
|
+
* bare cache() marker, a layout() in a routeless wrapper); a one-level scan
|
|
129
|
+
* missed the boundaries and intercepts it declares (#926).
|
|
118
130
|
*
|
|
119
131
|
* `skip` is the entry an upward walk came from. Only a bare cache() marker is
|
|
120
132
|
* both in its layout's layout[] and in the chain, and its subtree was already
|
package/src/router/instrument.ts
CHANGED
|
@@ -428,9 +428,10 @@ function observeInSegmentScope<C, R>(
|
|
|
428
428
|
* loop (request.start/end/error, cache.decision, ...).
|
|
429
429
|
* - segment-resolution/helpers.ts emits via a caller-provided report.telemetry
|
|
430
430
|
* sink rather than the ALS router context.
|
|
431
|
-
* - rsc/
|
|
432
|
-
* (request.origin-rejected), and
|
|
433
|
-
* handler.error) emit via
|
|
431
|
+
* - rsc/request-stages.ts timeoutResponse (request.timeout) and
|
|
432
|
+
* originRejectedResponse (request.origin-rejected), and rsc/handler.ts
|
|
433
|
+
* handleStore.onError (late-handle handler.error) emit via
|
|
434
|
+
* router.telemetry directly — they run outside the
|
|
434
435
|
* RouterContext ALS (only match()/matchPartial() enter it), so a
|
|
435
436
|
* getRouterContext() read there throws and the event would vanish.
|
|
436
437
|
*/
|
|
@@ -11,11 +11,7 @@ import type {
|
|
|
11
11
|
InterceptEntry,
|
|
12
12
|
InterceptSelectorContext,
|
|
13
13
|
} from "../server/context";
|
|
14
|
-
import type {
|
|
15
|
-
HandlerContext,
|
|
16
|
-
InternalHandlerContext,
|
|
17
|
-
ResolvedSegment,
|
|
18
|
-
} from "../types";
|
|
14
|
+
import type { InternalHandlerContext, ResolvedSegment } from "../types";
|
|
19
15
|
import {
|
|
20
16
|
handleHandlerResult,
|
|
21
17
|
warnOnStreamedResponse,
|
|
@@ -28,18 +24,15 @@ import {
|
|
|
28
24
|
deliverStartedLoaders,
|
|
29
25
|
resolveOwnerLoaders,
|
|
30
26
|
} from "./segment-resolution/revalidation.js";
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
NOTHING_HELD,
|
|
34
|
-
} from "./segment-resolution/prefetch-deferral.js";
|
|
35
|
-
import type { SegmentResolutionDeps } from "./types.js";
|
|
27
|
+
import { fillSends } from "./segment-resolution/prefetch-deferral.js";
|
|
28
|
+
import type { ResolutionPass } from "./segment-resolution/resolution-pass.js";
|
|
36
29
|
import { getRouterContext } from "./router-context.js";
|
|
37
|
-
import type { RevalidationContext } from "./router-context.js";
|
|
38
30
|
import { runInSegmentTagScope } from "../cache/cache-tag.js";
|
|
39
31
|
import {
|
|
40
32
|
RangoContext,
|
|
41
33
|
latchPprHeaderScopeForEntries,
|
|
42
34
|
} from "../server/context.js";
|
|
35
|
+
import { _getRequestContext } from "../server/request-context.js";
|
|
43
36
|
|
|
44
37
|
/**
|
|
45
38
|
* Header-guard latch for the intercept funnels (issue #713). ppr and
|
|
@@ -171,31 +164,40 @@ export function findInterceptForRoute(
|
|
|
171
164
|
/**
|
|
172
165
|
* An intercept handler's throw or notFound() renders the declaring entry's
|
|
173
166
|
* boundary as the slot component (catchSegmentError, as for route handlers on
|
|
174
|
-
* partial navigations: 500/404 status, onError "handler"
|
|
175
|
-
*
|
|
176
|
-
*
|
|
167
|
+
* partial navigations: 500/404 status, onError "handler" naming the slot).
|
|
168
|
+
* Responses rethrow. The background re-render (`background`) reports the
|
|
169
|
+
* error the same way and then rethrows it, so a failed re-render aborts its
|
|
170
|
+
* cache write instead of storing the fallback.
|
|
177
171
|
*/
|
|
178
172
|
function renderInterceptHandlerError<TEnv>(
|
|
173
|
+
pass: ResolutionPass<TEnv>,
|
|
179
174
|
error: unknown,
|
|
180
175
|
parentEntry: EntryData,
|
|
181
|
-
|
|
182
|
-
context: HandlerContext<any, TEnv>,
|
|
183
|
-
deps: SegmentResolutionDeps<TEnv>,
|
|
176
|
+
slotSegmentId: string,
|
|
184
177
|
background: boolean | undefined,
|
|
185
178
|
): ReactNode {
|
|
186
|
-
if (error instanceof Response
|
|
187
|
-
|
|
179
|
+
if (error instanceof Response) throw error;
|
|
180
|
+
// A background re-render's waitUntil task may run outside the router
|
|
181
|
+
// context, as the segment walk's report allows.
|
|
182
|
+
let telemetry;
|
|
183
|
+
try {
|
|
184
|
+
telemetry = getRouterContext()?.telemetry;
|
|
185
|
+
} catch {}
|
|
186
|
+
const { component } = catchSegmentError(
|
|
188
187
|
error,
|
|
189
188
|
parentEntry,
|
|
190
|
-
params,
|
|
191
|
-
deps,
|
|
189
|
+
pass.params,
|
|
190
|
+
pass.deps,
|
|
192
191
|
{
|
|
193
|
-
...buildLoaderErrorContext(context),
|
|
192
|
+
...buildLoaderErrorContext(pass.context),
|
|
194
193
|
isPartial: true,
|
|
195
|
-
telemetry
|
|
194
|
+
telemetry,
|
|
196
195
|
},
|
|
197
|
-
context.pathname,
|
|
198
|
-
|
|
196
|
+
pass.context.pathname,
|
|
197
|
+
{ id: slotSegmentId, type: "parallel" },
|
|
198
|
+
);
|
|
199
|
+
if (background) throw error;
|
|
200
|
+
return component;
|
|
199
201
|
}
|
|
200
202
|
|
|
201
203
|
/** The segment id of `intercept`'s slot on `parentEntry`. */
|
|
@@ -206,6 +208,33 @@ export function interceptSlotId(
|
|
|
206
208
|
return `${parentEntry.shortCode}.${intercept.slotName}`;
|
|
207
209
|
}
|
|
208
210
|
|
|
211
|
+
/**
|
|
212
|
+
* The intercept a match selected (findInterceptForRoute), as its cache()
|
|
213
|
+
* record names it (CacheScope): the slot id, then `~` and its position among
|
|
214
|
+
* the intercepts its entry declares for the same slot and target route. Two
|
|
215
|
+
* such intercepts share the slot id, and the position tells them apart; one
|
|
216
|
+
* for another slot or route does not renumber it. `~` is unreserved in a
|
|
217
|
+
* URL, so a store that maps the key onto one unencoded keeps the whole key.
|
|
218
|
+
* Undefined when the match selected none.
|
|
219
|
+
*/
|
|
220
|
+
export function interceptRecordKey(
|
|
221
|
+
selected: { intercept: InterceptEntry; entry: EntryData } | null,
|
|
222
|
+
): string | undefined {
|
|
223
|
+
if (!selected) return undefined;
|
|
224
|
+
const { intercept, entry } = selected;
|
|
225
|
+
let position = 0;
|
|
226
|
+
for (const other of entry.intercept) {
|
|
227
|
+
if (other === intercept) break;
|
|
228
|
+
if (
|
|
229
|
+
other.slotName === intercept.slotName &&
|
|
230
|
+
other.routeName === intercept.routeName
|
|
231
|
+
) {
|
|
232
|
+
position++;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return `${interceptSlotId(entry, intercept)}~${position}`;
|
|
236
|
+
}
|
|
237
|
+
|
|
209
238
|
/**
|
|
210
239
|
* Every segment id an intercept's slot owns, in order: the slot, then one
|
|
211
240
|
* loader segment per loader in declaration order, run or not. A request that
|
|
@@ -228,14 +257,13 @@ export function interceptSegmentIds(
|
|
|
228
257
|
* revalidated on its own, kept in a fill, deferred by a prefetch when flagged.
|
|
229
258
|
*/
|
|
230
259
|
function resolveInterceptLoaders<TEnv>(
|
|
260
|
+
pass: ResolutionPass<TEnv>,
|
|
231
261
|
interceptEntry: InterceptEntry,
|
|
232
262
|
parentEntry: EntryData,
|
|
233
|
-
context: HandlerContext<any, TEnv>,
|
|
234
263
|
belongsToRoute: boolean,
|
|
235
|
-
deps: SegmentResolutionDeps<TEnv>,
|
|
236
|
-
rc: RevalidationContext,
|
|
237
264
|
): Promise<{ segments: ResolvedSegment[] }> {
|
|
238
265
|
return resolveOwnerLoaders(
|
|
266
|
+
pass,
|
|
239
267
|
{
|
|
240
268
|
loaders: interceptEntry.loader,
|
|
241
269
|
namespace: `intercept:${interceptEntry.routeName}`,
|
|
@@ -244,17 +272,7 @@ function resolveInterceptLoaders<TEnv>(
|
|
|
244
272
|
bakeLane: false,
|
|
245
273
|
traceSource: "intercept-loader",
|
|
246
274
|
},
|
|
247
|
-
context,
|
|
248
275
|
belongsToRoute,
|
|
249
|
-
rc.clientSegmentIds,
|
|
250
|
-
rc.prevParams,
|
|
251
|
-
rc.request,
|
|
252
|
-
rc.prevUrl,
|
|
253
|
-
rc.nextUrl,
|
|
254
|
-
rc.routeKey,
|
|
255
|
-
deps,
|
|
256
|
-
rc.actionContext,
|
|
257
|
-
rc.stale,
|
|
258
276
|
);
|
|
259
277
|
}
|
|
260
278
|
|
|
@@ -271,45 +289,37 @@ async function settleLoaderSegments(
|
|
|
271
289
|
}
|
|
272
290
|
|
|
273
291
|
/**
|
|
274
|
-
* Resolve an intercept entry: its slot segment, then its loader segments.
|
|
292
|
+
* Resolve an intercept entry: its slot segment, then its loader segments. The
|
|
293
|
+
* background re-render resolves with a pass that holds nothing
|
|
294
|
+
* (heldNothingPassInput, resolution-pass.ts): every segment renders fresh, and
|
|
295
|
+
* its loaders are skipped (skipLoaders), each registered for the handler's
|
|
296
|
+
* read.
|
|
275
297
|
*/
|
|
276
298
|
export async function resolveInterceptEntry<TEnv>(
|
|
299
|
+
pass: ResolutionPass<TEnv>,
|
|
277
300
|
interceptEntry: InterceptEntry,
|
|
278
301
|
parentEntry: EntryData,
|
|
279
|
-
params: Record<string, string>,
|
|
280
|
-
context: HandlerContext<any, TEnv>,
|
|
281
302
|
belongsToRoute: boolean,
|
|
282
|
-
deps: SegmentResolutionDeps<TEnv>,
|
|
283
|
-
// The background re-render passes none: nothing held, rendered fresh.
|
|
284
|
-
revalidationContext: RevalidationContext = {
|
|
285
|
-
clientSegmentIds: NOTHING_HELD,
|
|
286
|
-
prevParams: {},
|
|
287
|
-
request: context.request,
|
|
288
|
-
prevUrl: context.url,
|
|
289
|
-
nextUrl: context.url,
|
|
290
|
-
routeKey: interceptEntry.routeName,
|
|
291
|
-
},
|
|
292
303
|
options?: {
|
|
293
304
|
/**
|
|
294
305
|
* Set ONLY by the post-response background re-render (stale background
|
|
295
306
|
* revalidation), whose sole purpose is to re-render the segment tree to
|
|
296
|
-
* populate the cache: a handler error
|
|
297
|
-
* error boundary, so a failure is never cached. Never
|
|
298
|
-
* foreground path.
|
|
307
|
+
* populate the cache: a handler error is reported, then rejects instead
|
|
308
|
+
* of rendering the error boundary, so a failure is never cached. Never
|
|
309
|
+
* set on the foreground path.
|
|
299
310
|
*/
|
|
300
311
|
background?: boolean;
|
|
301
312
|
},
|
|
302
313
|
): Promise<ResolvedSegment[]> {
|
|
303
314
|
latchPprHeaderScopeForInterceptTarget(interceptEntry);
|
|
304
315
|
|
|
316
|
+
const { context, params } = pass;
|
|
305
317
|
const slotSegmentId = interceptSlotId(parentEntry, interceptEntry);
|
|
306
318
|
const { segments: loaderSegments } = await resolveInterceptLoaders(
|
|
319
|
+
pass,
|
|
307
320
|
interceptEntry,
|
|
308
321
|
parentEntry,
|
|
309
|
-
context,
|
|
310
322
|
belongsToRoute,
|
|
311
|
-
deps,
|
|
312
|
-
revalidationContext,
|
|
313
323
|
);
|
|
314
324
|
// The slot's tag scope (#957, cache-tag.ts runInSegmentTagScope) and the
|
|
315
325
|
// owner of its handler's handle pushes (a handler's ctx.use(Handle) reads
|
|
@@ -337,10 +347,7 @@ export async function resolveInterceptEntry<TEnv>(
|
|
|
337
347
|
// A fill keeps a slot the client holds: neither its handler nor its layout
|
|
338
348
|
// runs, only the loaders the client lacks (match-result.ts leaves the null
|
|
339
349
|
// slot out of the response).
|
|
340
|
-
if (
|
|
341
|
-
fillSends(context, slotSegmentId, revalidationContext.clientSegmentIds) ===
|
|
342
|
-
false
|
|
343
|
-
) {
|
|
350
|
+
if (fillSends(context, slotSegmentId, pass.client) === false) {
|
|
344
351
|
return [slotSegment(null, undefined), ...loaderSegments];
|
|
345
352
|
}
|
|
346
353
|
|
|
@@ -355,11 +362,10 @@ export async function resolveInterceptEntry<TEnv>(
|
|
|
355
362
|
: handler;
|
|
356
363
|
} catch (error) {
|
|
357
364
|
handlerResult = renderInterceptHandlerError(
|
|
365
|
+
pass,
|
|
358
366
|
error,
|
|
359
367
|
parentEntry,
|
|
360
|
-
|
|
361
|
-
context,
|
|
362
|
-
deps,
|
|
368
|
+
slotSegmentId,
|
|
363
369
|
options?.background,
|
|
364
370
|
);
|
|
365
371
|
}
|
|
@@ -392,13 +398,14 @@ export async function resolveInterceptEntry<TEnv>(
|
|
|
392
398
|
// recovered into the declared boundary, except on the background
|
|
393
399
|
// re-render, which must reject so a failure is never cached.
|
|
394
400
|
const streamedComponent = (promise: Promise<unknown>): ReactNode =>
|
|
395
|
-
trackStreamedHandler(deps, promise, {
|
|
401
|
+
trackStreamedHandler(pass.deps, promise, {
|
|
396
402
|
boundaryEntry: parentEntry,
|
|
397
403
|
segmentId: slotSegmentId,
|
|
398
404
|
segmentType: "parallel",
|
|
399
405
|
context,
|
|
400
406
|
routeKey: interceptEntry.routeName,
|
|
401
407
|
params,
|
|
408
|
+
isPartial: true,
|
|
402
409
|
recover: !options?.background,
|
|
403
410
|
});
|
|
404
411
|
|
|
@@ -423,11 +430,10 @@ export async function resolveInterceptEntry<TEnv>(
|
|
|
423
430
|
component = await handlerResult;
|
|
424
431
|
} catch (error) {
|
|
425
432
|
component = renderInterceptHandlerError(
|
|
433
|
+
pass,
|
|
426
434
|
error,
|
|
427
435
|
parentEntry,
|
|
428
|
-
|
|
429
|
-
context,
|
|
430
|
-
deps,
|
|
436
|
+
slotSegmentId,
|
|
431
437
|
options?.background,
|
|
432
438
|
);
|
|
433
439
|
}
|
|
@@ -445,23 +451,24 @@ export async function resolveInterceptEntry<TEnv>(
|
|
|
445
451
|
* keeps its cached component and layout, its loaders are never cached.
|
|
446
452
|
*/
|
|
447
453
|
export async function resolveInterceptLoadersOnly<TEnv>(
|
|
454
|
+
pass: ResolutionPass<TEnv>,
|
|
448
455
|
interceptEntry: InterceptEntry,
|
|
449
456
|
parentEntry: EntryData,
|
|
450
|
-
context: HandlerContext<any, TEnv>,
|
|
451
457
|
belongsToRoute: boolean,
|
|
452
|
-
deps: SegmentResolutionDeps<TEnv>,
|
|
453
|
-
revalidationContext: RevalidationContext,
|
|
454
458
|
): Promise<ResolvedSegment[]> {
|
|
455
459
|
latchPprHeaderScopeForInterceptTarget(interceptEntry);
|
|
460
|
+
const handleStore = _getRequestContext()?._handleStore;
|
|
456
461
|
const { segments } = await resolveInterceptLoaders(
|
|
462
|
+
pass,
|
|
457
463
|
interceptEntry,
|
|
458
464
|
parentEntry,
|
|
459
|
-
context,
|
|
460
465
|
belongsToRoute,
|
|
461
|
-
|
|
462
|
-
|
|
466
|
+
);
|
|
467
|
+
// Where resolveInterceptEntry runs the handler.
|
|
468
|
+
handleStore?.releaseRecordedValues(
|
|
469
|
+
interceptSlotId(parentEntry, interceptEntry),
|
|
463
470
|
);
|
|
464
471
|
if (!interceptEntry.loading) await settleLoaderSegments(segments);
|
|
465
|
-
deliverStartedLoaders(context, segments);
|
|
472
|
+
deliverStartedLoaders(pass.context, segments);
|
|
466
473
|
return segments;
|
|
467
474
|
}
|
|
@@ -341,7 +341,8 @@ export function wrapLoaderWithErrorHandling<T>(
|
|
|
341
341
|
// Render fallback on server. The user ErrorBoundaryHandler may throw
|
|
342
342
|
// synchronously; if it does we must NOT let that rejection escape — the
|
|
343
343
|
// wrapped LoaderDataResult promise is contracted to never reject (see
|
|
344
|
-
//
|
|
344
|
+
// resolveOwnerLoaders `await Promise.all(...)` in
|
|
345
|
+
// segment-resolution/revalidation.ts), and a
|
|
345
346
|
// rejection here would collapse the whole entry and discard healthy
|
|
346
347
|
// sibling loader data. On a fallback-render throw, fall back to the
|
|
347
348
|
// no-boundary result (fallback: null) so the client throws the ORIGINAL
|
|
@@ -585,7 +586,7 @@ function createLoaderExecutor<TEnv>(
|
|
|
585
586
|
const variables = internal._variables;
|
|
586
587
|
|
|
587
588
|
// Capture whether this loader is being started from a DSL loader scope
|
|
588
|
-
// (runInsideLoaderScope in
|
|
589
|
+
// (runInsideLoaderScope in resolveOwnerLoaders). Handler-invoked loaders are NOT
|
|
589
590
|
// inside loader scope. This determines whether rendered() is allowed.
|
|
590
591
|
const isDslLoader = isInsideLoaderScope();
|
|
591
592
|
// The body resolves ctx.reverse(".name") in its DSL declaration's module
|
|
@@ -596,7 +597,7 @@ function createLoaderExecutor<TEnv>(
|
|
|
596
597
|
|
|
597
598
|
// Owning segment for ctx.handle() attribution, captured SYNCHRONOUSLY at
|
|
598
599
|
// kickoff: segment resolution sets _currentSegmentId while resolving the
|
|
599
|
-
// segment that declares this loader (
|
|
600
|
+
// segment that declares this loader (resolveOwnerLoaders), and the value moves on as
|
|
600
601
|
// resolution continues — by the time the async body pushes, it would be
|
|
601
602
|
// stale. Attributing to the owning route/layout segment gives handle
|
|
602
603
|
// pushes the same granularity handler pushes have (segmentOrder-correct
|
|
@@ -844,7 +845,7 @@ function createLoaderExecutor<TEnv>(
|
|
|
844
845
|
// Run the loader body inside loader scope so request-scoped reads
|
|
845
846
|
// (cookies()/headers() and non-cacheable ctx.get) are exempt from the
|
|
846
847
|
// cache-purity guards: loaders always run fresh, so their reads never leak
|
|
847
|
-
// into a cached segment. DSL loaders are already wrapped by
|
|
848
|
+
// into a cached segment. DSL loaders are already wrapped by resolveOwnerLoaders; this
|
|
848
849
|
// also covers handler-invoked loaders (ctx.use(Loader) from a handler),
|
|
849
850
|
// which otherwise execute in the caller's cache scope and would wrongly
|
|
850
851
|
// throw. rendered() gating uses the captured isDslLoader (above), so this
|
package/src/router/match-api.ts
CHANGED
|
@@ -184,8 +184,9 @@ export async function createMatchContextForFull<TEnv>(
|
|
|
184
184
|
// A shell capture credits a push under a live-lane loader's body to that
|
|
185
185
|
// loader (shell-capture.ts deriveShellCaptureContext). The lanes are set
|
|
186
186
|
// before any loader runs: a bake-lane loader can start a later one.
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
const captureState = reqCtx?._shellCaptureState;
|
|
188
|
+
if (captureState?.run) {
|
|
189
|
+
captureState.loaderLanes = routeLoaderLanes(snapshot.entries);
|
|
189
190
|
}
|
|
190
191
|
// A document never defers; the plan feeds the ctx.rendered() guards.
|
|
191
192
|
(handlerContext as InternalHandlerContext<any, TEnv>)._prefetchDeferral =
|
|
@@ -208,7 +209,6 @@ export async function createMatchContextForFull<TEnv>(
|
|
|
208
209
|
routeKey: matched.routeKey,
|
|
209
210
|
localRouteName: snapshot.localRouteName,
|
|
210
211
|
handlerContext,
|
|
211
|
-
loaderPromises,
|
|
212
212
|
routeMap: deps.getRouteMap(),
|
|
213
213
|
metricsStore,
|
|
214
214
|
Store,
|
|
@@ -492,7 +492,7 @@ export async function createMatchContextForPartial<TEnv>(
|
|
|
492
492
|
prefetch: kind === "prefetch",
|
|
493
493
|
method: request.method,
|
|
494
494
|
isAction,
|
|
495
|
-
isShellCapture: reqCtx?.
|
|
495
|
+
isShellCapture: reqCtx?._shellCaptureState?.run === true,
|
|
496
496
|
}),
|
|
497
497
|
matched,
|
|
498
498
|
cacheScope,
|
|
@@ -514,6 +514,7 @@ export async function createMatchContextForPartial<TEnv>(
|
|
|
514
514
|
clientSegmentIds: nav.clientSegmentIds,
|
|
515
515
|
clientSegmentSet,
|
|
516
516
|
stale: nav.stale,
|
|
517
|
+
heldBoundary: nav.heldBoundary,
|
|
517
518
|
prevUrl: nav.prevUrl,
|
|
518
519
|
prevParams: nav.prevParams,
|
|
519
520
|
prevMatch: nav.prevMatch,
|
|
@@ -523,7 +524,6 @@ export async function createMatchContextForPartial<TEnv>(
|
|
|
523
524
|
routeKey: matched.routeKey,
|
|
524
525
|
localRouteName: snapshot.localRouteName,
|
|
525
526
|
handlerContext,
|
|
526
|
-
loaderPromises,
|
|
527
527
|
routeMap: deps.getRouteMap(),
|
|
528
528
|
metricsStore,
|
|
529
529
|
Store,
|