@rangojs/router 0.17.0 → 0.19.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/README.md +3 -2
- package/dist/types/browser/cookie-name.d.ts +6 -0
- package/dist/types/browser/event-controller.d.ts +3 -3
- package/dist/types/browser/history-state.d.ts +18 -0
- package/dist/types/browser/navigation-transaction.d.ts +20 -2
- package/dist/types/browser/partial-update.d.ts +16 -1
- package/dist/types/browser/prefetch/cache.d.ts +6 -6
- package/dist/types/browser/react/Link.d.ts +19 -9
- package/dist/types/browser/react/context.d.ts +2 -2
- package/dist/types/browser/react/location-state-shared.d.ts +95 -56
- package/dist/types/browser/react/location-state.d.ts +1 -1
- package/dist/types/browser/transition-when.d.ts +80 -0
- package/dist/types/browser/types.d.ts +104 -9
- package/dist/types/build/generate-manifest.d.ts +8 -0
- package/dist/types/cache/background-task.d.ts +24 -2
- package/dist/types/cache/cache-exec-scope.d.ts +31 -0
- package/dist/types/cache/cache-key-utils.d.ts +48 -2
- package/dist/types/cache/cache-policy.d.ts +18 -1
- package/dist/types/cache/cache-runtime.d.ts +7 -0
- package/dist/types/cache/cache-scope.d.ts +192 -26
- package/dist/types/cache/cache-tag.d.ts +116 -11
- package/dist/types/cache/cf/cf-base64.d.ts +6 -0
- package/dist/types/cache/cf/cf-cache-constants.d.ts +11 -0
- package/dist/types/cache/cf/cf-cache-store.d.ts +224 -72
- package/dist/types/cache/cf/cf-cache-types.d.ts +31 -4
- package/dist/types/cache/cf/cf-shell-frame.d.ts +95 -0
- package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +19 -0
- package/dist/types/cache/document-cache.d.ts +10 -0
- package/dist/types/cache/handle-snapshot.d.ts +41 -8
- package/dist/types/cache/index.d.ts +1 -0
- package/dist/types/cache/invalidation-order.d.ts +23 -0
- package/dist/types/cache/isolate-tag-memo.d.ts +149 -0
- package/dist/types/cache/request-tag-mask.d.ts +54 -0
- package/dist/types/cache/shell-memo.d.ts +178 -0
- package/dist/types/cache/shell-snapshot.d.ts +141 -105
- package/dist/types/cache/tag-invalidation.d.ts +54 -3
- package/dist/types/cache/types.d.ts +267 -96
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +123 -18
- package/dist/types/client-urls/navigation.d.ts +28 -2
- package/dist/types/client-urls/server-projection.d.ts +5 -2
- package/dist/types/client-urls/types.d.ts +5 -5
- package/dist/types/client.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.rsc.d.ts +1 -1
- package/dist/types/prerender/build-shell-capture.d.ts +11 -4
- package/dist/types/route-definition/helpers-types.d.ts +11 -11
- package/dist/types/route-name.d.ts +7 -0
- package/dist/types/router/error-handling.d.ts +1 -1
- package/dist/types/router/instrument.d.ts +8 -0
- package/dist/types/router/intercept-resolution.d.ts +2 -0
- package/dist/types/router/match-context.d.ts +5 -0
- package/dist/types/router/match-middleware/background-revalidation.d.ts +0 -4
- package/dist/types/router/middleware-types.d.ts +6 -1
- package/dist/types/router/router-options.d.ts +4 -1
- package/dist/types/router/segment-resolution/loader-cache.d.ts +58 -12
- package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -4
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +33 -48
- package/dist/types/router/segment-resolution/mask-nested.d.ts +73 -24
- package/dist/types/router/segment-resolution/view-transition-default.d.ts +7 -5
- package/dist/types/router/transition-when.d.ts +24 -10
- package/dist/types/rsc/attach-transition-when.d.ts +18 -0
- package/dist/types/rsc/full-payload.d.ts +21 -0
- package/dist/types/rsc/handler.d.ts +1 -1
- package/dist/types/rsc/response-cache-serve.d.ts +15 -12
- package/dist/types/rsc/shell-build-manifest.d.ts +12 -3
- package/dist/types/rsc/shell-capture-constants.d.ts +116 -12
- package/dist/types/rsc/shell-capture.d.ts +202 -74
- package/dist/types/rsc/shell-serve.d.ts +144 -50
- package/dist/types/rsc/types.d.ts +9 -0
- package/dist/types/segment-system.d.ts +7 -0
- package/dist/types/server/context.d.ts +155 -33
- package/dist/types/server/cookie-store.d.ts +33 -0
- package/dist/types/server/handle-store.d.ts +52 -1
- package/dist/types/server/request-context.d.ts +210 -63
- package/dist/types/server/request-headers.d.ts +44 -0
- package/dist/types/server.d.ts +1 -0
- package/dist/types/ssr/index.d.ts +9 -0
- package/dist/types/ssr/ssr-root.d.ts +9 -8
- package/dist/types/testing/e2e/index.d.ts +1 -1
- package/dist/types/testing/flight.entry.d.ts +7 -0
- package/dist/types/testing/index.d.ts +3 -2
- package/dist/types/testing/internal/action-id.d.ts +7 -0
- package/dist/types/testing/location-state-key.d.ts +24 -0
- package/dist/types/testing/render-route.d.ts +17 -1
- package/dist/types/testing/run-loader.d.ts +18 -3
- package/dist/types/testing/run-transition-when.d.ts +44 -69
- package/dist/types/testing/serve-shell-request.d.ts +133 -0
- package/dist/types/testing/shell-status.d.ts +44 -19
- package/dist/types/transition-when-ref.d.ts +79 -0
- package/dist/types/types/cache-types.d.ts +15 -3
- package/dist/types/types/handler-context.d.ts +14 -1
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/segments.d.ts +86 -71
- package/dist/types/urls/path-helper-types.d.ts +3 -4
- package/dist/types/urls/pattern-types.d.ts +21 -18
- package/dist/types/vite/plugins/transition-when-hoist.d.ts +45 -0
- package/dist/types/vite/router-discovery.d.ts +29 -2
- package/dist/vite/index.js +1005 -105
- package/package.json +1 -1
- package/skills/breadcrumbs/SKILL.md +17 -7
- package/skills/cache-guide/SKILL.md +175 -76
- package/skills/caching/SKILL.md +361 -33
- package/skills/catalog.json +1 -1
- package/skills/client-urls/SKILL.md +12 -7
- package/skills/cloudflare/SKILL.md +15 -0
- package/skills/comparison/references/framework-comparison.md +52 -37
- package/skills/defer-hydration/SKILL.md +50 -30
- package/skills/deployment-caching/SKILL.md +5 -2
- package/skills/document-cache/SKILL.md +32 -2
- package/skills/handler-use/SKILL.md +2 -0
- package/skills/hooks/SKILL.md +3 -1
- package/skills/hooks/handle-and-actions.md +3 -1
- package/skills/hooks/navigation.md +23 -2
- package/skills/hooks/state.md +101 -7
- package/skills/intercept/SKILL.md +29 -12
- package/skills/loader/SKILL.md +197 -44
- package/skills/middleware/SKILL.md +34 -9
- package/skills/migrate-nextjs/SKILL.md +68 -37
- package/skills/migrate-react-router/SKILL.md +2 -1
- package/skills/migrate-react-router/component-migration.md +3 -1
- package/skills/migrate-react-router/data-and-actions.md +3 -1
- package/skills/migrate-react-router/route-mapping.md +7 -4
- package/skills/observability/SKILL.md +65 -0
- package/skills/parallel/SKILL.md +13 -8
- package/skills/ppr/SKILL.md +715 -371
- package/skills/prerender/SKILL.md +30 -17
- package/skills/rango/SKILL.md +72 -34
- package/skills/route/SKILL.md +14 -7
- package/skills/router-setup/SKILL.md +4 -2
- package/skills/scripts/SKILL.md +8 -1
- package/skills/server-actions/SKILL.md +11 -0
- package/skills/shell-manifest/SKILL.md +21 -12
- package/skills/testing/SKILL.md +49 -43
- package/skills/testing/cache-prerender.md +15 -14
- package/skills/testing/client-components.md +45 -3
- package/skills/testing/loader.md +19 -1
- package/skills/testing/middleware.md +1 -0
- package/skills/testing/predicates.md +49 -49
- package/skills/testing/render-handler.md +1 -0
- package/skills/testing/serve-shell-request.md +202 -0
- package/skills/testing/server-actions.md +9 -3
- package/skills/theme/SKILL.md +56 -4
- package/skills/typesafety/env-and-bindings.md +18 -2
- package/skills/use-cache/SKILL.md +91 -23
- package/skills/vercel/SKILL.md +14 -2
- package/skills/view-transitions/SKILL.md +150 -29
- package/src/__augment-tests__/augmented.check.ts +23 -0
- package/src/browser/cookie-name.ts +23 -0
- package/src/browser/event-controller.ts +4 -4
- package/src/browser/history-state.ts +75 -1
- package/src/browser/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +77 -18
- package/src/browser/navigation-client.ts +4 -3
- package/src/browser/navigation-store.ts +43 -1
- package/src/browser/navigation-transaction.ts +31 -11
- package/src/browser/partial-update.ts +146 -35
- package/src/browser/prefetch/cache.ts +6 -6
- package/src/browser/prefetch/fetch.ts +2 -2
- package/src/browser/react/Link.tsx +38 -33
- package/src/browser/react/NavigationProvider.tsx +2 -2
- package/src/browser/react/context.ts +2 -2
- package/src/browser/react/location-state-shared.ts +241 -49
- package/src/browser/react/location-state.ts +5 -2
- package/src/browser/rsc-router.tsx +9 -0
- package/src/browser/server-action-bridge.ts +84 -15
- package/src/browser/transition-when.ts +205 -0
- package/src/browser/types.ts +124 -10
- package/src/build/generate-manifest.ts +77 -1
- package/src/cache/background-task.ts +55 -2
- package/src/cache/cache-exec-scope.ts +48 -1
- package/src/cache/cache-key-utils.ts +62 -2
- package/src/cache/cache-policy.ts +31 -4
- package/src/cache/cache-runtime.ts +209 -129
- package/src/cache/cache-scope.ts +573 -69
- package/src/cache/cache-tag.ts +475 -19
- package/src/cache/cf/cf-base64.ts +36 -4
- package/src/cache/cf/cf-cache-constants.ts +12 -0
- package/src/cache/cf/cf-cache-store.ts +1094 -376
- package/src/cache/cf/cf-cache-types.ts +32 -4
- package/src/cache/cf/cf-shell-frame.ts +258 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +55 -40
- package/src/cache/document-cache.ts +53 -7
- package/src/cache/handle-snapshot.ts +53 -9
- package/src/cache/index.ts +2 -0
- package/src/cache/invalidation-order.ts +84 -0
- package/src/cache/isolate-tag-memo.ts +308 -0
- package/src/cache/request-tag-mask.ts +147 -0
- package/src/cache/shell-memo.ts +341 -0
- package/src/cache/shell-snapshot.ts +249 -277
- package/src/cache/tag-invalidation.ts +109 -18
- package/src/cache/types.ts +274 -102
- package/src/cache/vercel/vercel-cache-store.ts +561 -74
- package/src/client-urls/client-root.tsx +8 -4
- package/src/client-urls/client-urls.ts +8 -6
- package/src/client-urls/navigation.ts +55 -4
- package/src/client-urls/server-projection.ts +31 -10
- package/src/client-urls/types.ts +12 -5
- package/src/client.tsx +2 -0
- package/src/host/cookie-handler.ts +2 -1
- package/src/index.rsc.ts +3 -0
- package/src/index.ts +3 -0
- package/src/loader-redirect.tsx +7 -3
- package/src/prerender/build-shell-capture.ts +173 -110
- package/src/route-definition/dsl-helpers.ts +6 -3
- package/src/route-definition/helpers-types.ts +11 -11
- package/src/route-name.ts +12 -0
- package/src/router/content-negotiation.ts +4 -1
- package/src/router/error-handling.ts +5 -2
- package/src/router/handler-context.ts +42 -5
- package/src/router/instrument.ts +54 -2
- package/src/router/intercept-resolution.ts +30 -8
- package/src/router/loader-resolution.ts +89 -33
- package/src/router/logging.ts +5 -3
- package/src/router/match-api.ts +89 -42
- package/src/router/match-context.ts +5 -0
- package/src/router/match-handlers.ts +14 -29
- package/src/router/match-middleware/background-revalidation.ts +3 -5
- package/src/router/match-middleware/cache-lookup.ts +52 -19
- package/src/router/match-middleware/cache-store.ts +36 -10
- package/src/router/match-result.ts +1 -0
- package/src/router/middleware-types.ts +6 -1
- package/src/router/middleware.ts +20 -4
- package/src/router/navigation-snapshot.ts +6 -5
- package/src/router/prerender-match.ts +10 -0
- package/src/router/request-classification.ts +7 -4
- package/src/router/router-options.ts +4 -1
- package/src/router/segment-resolution/fresh.ts +18 -13
- package/src/router/segment-resolution/helpers.ts +4 -2
- package/src/router/segment-resolution/loader-cache.ts +366 -70
- package/src/router/segment-resolution/loader-mask.ts +3 -4
- package/src/router/segment-resolution/loader-snapshot.ts +215 -126
- package/src/router/segment-resolution/mask-nested.ts +161 -42
- package/src/router/segment-resolution/revalidation.ts +27 -13
- package/src/router/segment-resolution/view-transition-default.ts +6 -21
- package/src/router/telemetry.ts +6 -3
- package/src/router/transition-when.ts +34 -52
- package/src/router.ts +2 -1
- package/src/rsc/attach-transition-when.ts +47 -0
- package/src/rsc/full-payload.ts +47 -3
- package/src/rsc/handler.ts +24 -10
- package/src/rsc/loader-fetch.ts +2 -1
- package/src/rsc/manifest-init.ts +4 -0
- package/src/rsc/origin-guard.ts +8 -5
- package/src/rsc/progressive-enhancement.ts +10 -32
- package/src/rsc/response-cache-serve.ts +69 -78
- package/src/rsc/response-route-handler.ts +2 -2
- package/src/rsc/rsc-rendering.ts +712 -338
- package/src/rsc/server-action.ts +8 -20
- package/src/rsc/shell-build-manifest.ts +49 -29
- package/src/rsc/shell-capture-constants.ts +182 -12
- package/src/rsc/shell-capture.ts +1126 -612
- package/src/rsc/shell-serve.ts +331 -85
- package/src/rsc/ssr-setup.ts +3 -2
- package/src/rsc/types.ts +9 -0
- package/src/segment-system.tsx +40 -7
- package/src/server/context.ts +328 -72
- package/src/server/cookie-store.ts +184 -133
- package/src/server/handle-store.ts +245 -27
- package/src/server/request-context.ts +364 -100
- package/src/server/request-headers.ts +134 -0
- package/src/server.ts +4 -0
- package/src/ssr/index.tsx +96 -37
- package/src/ssr/ssr-root.tsx +9 -8
- package/src/testing/dispatch.ts +4 -7
- package/src/testing/e2e/index.ts +1 -0
- package/src/testing/flight.entry.ts +14 -0
- package/src/testing/index.ts +5 -0
- package/src/testing/internal/action-id.ts +25 -0
- package/src/testing/internal/context.ts +1 -1
- package/src/testing/location-state-key.ts +45 -0
- package/src/testing/render-handler.ts +1 -1
- package/src/testing/render-route.tsx +109 -16
- package/src/testing/run-client-revalidate.ts +3 -19
- package/src/testing/run-loader.ts +67 -5
- package/src/testing/run-transition-when.ts +109 -172
- package/src/testing/serve-shell-request.ts +381 -0
- package/src/testing/shell-status.ts +73 -47
- package/src/theme/ThemeProvider.tsx +7 -6
- package/src/transition-when-ref.ts +220 -0
- package/src/types/cache-types.ts +15 -3
- package/src/types/handler-context.ts +14 -1
- package/src/types/index.ts +3 -0
- package/src/types/segments.ts +94 -91
- package/src/urls/path-helper-types.ts +3 -4
- package/src/urls/pattern-types.ts +21 -18
- package/src/vite/discovery/discover-routers.ts +3 -0
- package/src/vite/discovery/shell-prerender-phase.ts +9 -2
- package/src/vite/discovery/virtual-module-codegen.ts +16 -6
- package/src/vite/plugins/transition-when-hoist.ts +1064 -0
- package/src/vite/rango.ts +2 -0
- package/src/vite/router-discovery.ts +89 -9
- package/dist/types/rsc/transition-gate.d.ts +0 -23
- package/src/rsc/transition-gate.ts +0 -86
|
@@ -107,6 +107,7 @@ import type { GeneratorMiddleware } from "./cache-lookup.js";
|
|
|
107
107
|
import { debugLog, debugWarn, getOrCreateRequestId } from "../logging.js";
|
|
108
108
|
import { INTERNAL_RANGO_DEBUG } from "../../internal-debug.js";
|
|
109
109
|
import { getContext } from "../../server/context.js";
|
|
110
|
+
import { executionStart } from "../../cache/tag-invalidation.js";
|
|
110
111
|
import {
|
|
111
112
|
createRequestContext,
|
|
112
113
|
runWithRequestContext,
|
|
@@ -134,10 +135,6 @@ import {
|
|
|
134
135
|
* cache-scope.ts), so a swap sent live pushes into this render.
|
|
135
136
|
* setupLoaderAccess binds the store at setup, so it runs inside the
|
|
136
137
|
* derived context too.
|
|
137
|
-
* - _transitionWhen: fresh resolution appends transition({ when })
|
|
138
|
-
* predicates; the foreground's gateTransitions reads the array after the
|
|
139
|
-
* match, and a stale HIT (which replays the stored transition) must not
|
|
140
|
-
* evaluate this render's predicates.
|
|
141
138
|
* - _metricsStore: undefined, and the DSL store below has `metrics` unset
|
|
142
139
|
* (track() reads that one), so nothing lands on the foreground's perf
|
|
143
140
|
* timeline. ctx.Store.run closes over ctx.Store, so the derived store
|
|
@@ -156,6 +153,7 @@ export async function rerenderAndCacheRoute<TEnv>(
|
|
|
156
153
|
cacheScope: CacheScope,
|
|
157
154
|
routerCtx: RouterContext<TEnv>,
|
|
158
155
|
): Promise<number> {
|
|
156
|
+
const start = executionStart();
|
|
159
157
|
const handleStore = routerCtx.createHandleStore();
|
|
160
158
|
// Response writes land in a throwaway context nothing merges or drains. Its
|
|
161
159
|
// mutators are closures over its own stub, and they keep the same guards.
|
|
@@ -172,7 +170,6 @@ export async function rerenderAndCacheRoute<TEnv>(
|
|
|
172
170
|
}),
|
|
173
171
|
{
|
|
174
172
|
_handleStore: handleStore,
|
|
175
|
-
_transitionWhen: [],
|
|
176
173
|
_metricsStore: undefined,
|
|
177
174
|
_onResponseCallbacks: [],
|
|
178
175
|
header: sink.header,
|
|
@@ -253,6 +250,7 @@ export async function rerenderAndCacheRoute<TEnv>(
|
|
|
253
250
|
ctx.matched.params,
|
|
254
251
|
segments,
|
|
255
252
|
ctx.isIntercept,
|
|
253
|
+
start,
|
|
256
254
|
);
|
|
257
255
|
return segments.length;
|
|
258
256
|
});
|
|
@@ -92,12 +92,14 @@
|
|
|
92
92
|
* - Action context (if POST)
|
|
93
93
|
*/
|
|
94
94
|
import type { InternalHandlerContext, ResolvedSegment } from "../../types.js";
|
|
95
|
+
import type { OwnedPushDelivery } from "../../cache/handle-snapshot.js";
|
|
95
96
|
import type { EntryData } from "../../server/context.js";
|
|
96
97
|
import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
97
98
|
import { getRouterContext, type RouterContext } from "../router-context.js";
|
|
98
99
|
import { observeEvent } from "../instrument.js";
|
|
99
100
|
import { pushRevalidationTraceEntry, isTraceActive } from "../logging.js";
|
|
100
101
|
import { treeHasStreaming } from "./segment-resolution.js";
|
|
102
|
+
import { liveLaneLoaderIds } from "../segment-resolution/loader-cache.js";
|
|
101
103
|
import type { PrerenderStore, PrerenderEntry } from "../../prerender/store.js";
|
|
102
104
|
import {
|
|
103
105
|
_getRequestContext,
|
|
@@ -107,6 +109,7 @@ import {
|
|
|
107
109
|
createShellImplicitDocScope,
|
|
108
110
|
type CacheScope,
|
|
109
111
|
} from "../../cache/cache-scope.js";
|
|
112
|
+
import { ShellRecordUnavailableError } from "../../cache/shell-snapshot.js";
|
|
110
113
|
import { prerenderStoreShortCircuits } from "../navigation-snapshot.js";
|
|
111
114
|
import { paramsEqual } from "../params-util.js";
|
|
112
115
|
|
|
@@ -296,8 +299,7 @@ async function* yieldFromStore<TEnv>(
|
|
|
296
299
|
!paramsChanged &&
|
|
297
300
|
ctx.clientSegmentSet.has(segment.id)
|
|
298
301
|
) {
|
|
299
|
-
segment
|
|
300
|
-
segment.loading = undefined;
|
|
302
|
+
keepClientSegment(segment);
|
|
301
303
|
}
|
|
302
304
|
yield segment;
|
|
303
305
|
}
|
|
@@ -404,6 +406,21 @@ async function* tryPrerenderLookup<TEnv>(
|
|
|
404
406
|
return true;
|
|
405
407
|
}
|
|
406
408
|
|
|
409
|
+
/**
|
|
410
|
+
* Keep the client's copy of a stored (runtime cache, prerender, or shell
|
|
411
|
+
* replay) segment this navigation does not re-render. collectMatchResult
|
|
412
|
+
* (match-result.ts) omits a null-component segment the client holds, as the
|
|
413
|
+
* live partial path omits a segment whose revalidation said no
|
|
414
|
+
* (segment-resolution/revalidation.ts).
|
|
415
|
+
*
|
|
416
|
+
* A transition({ when }) is no exception: it is decided in the browser for
|
|
417
|
+
* kept segments too, so no segment is re-sent to carry a decision (#986).
|
|
418
|
+
*/
|
|
419
|
+
function keepClientSegment(segment: ResolvedSegment): void {
|
|
420
|
+
segment.component = null;
|
|
421
|
+
segment.loading = undefined;
|
|
422
|
+
}
|
|
423
|
+
|
|
407
424
|
/**
|
|
408
425
|
* Async generator middleware type
|
|
409
426
|
*/
|
|
@@ -508,6 +525,15 @@ export function withCacheLookup<TEnv>(
|
|
|
508
525
|
}
|
|
509
526
|
}
|
|
510
527
|
|
|
528
|
+
// A document HIT tail replays the handler layer through the implicit doc
|
|
529
|
+
// scope and never runs a handler: without that scope (a context that lost
|
|
530
|
+
// the marker before the scope resolved), fail like a lookup miss instead
|
|
531
|
+
// of falling through to the handlers below.
|
|
532
|
+
const tailMarker = pipelineReqCtx?._shellImplicitCache;
|
|
533
|
+
if (tailMarker?.docTail && !ctx.cacheScope?.isShellImplicitDocScope) {
|
|
534
|
+
throw new ShellRecordUnavailableError(tailMarker.fixedDocKey);
|
|
535
|
+
}
|
|
536
|
+
|
|
511
537
|
if (ctx.isAction || !ctx.cacheScope?.enabled) {
|
|
512
538
|
yield* source;
|
|
513
539
|
if (ms) {
|
|
@@ -521,14 +547,24 @@ export function withCacheLookup<TEnv>(
|
|
|
521
547
|
}
|
|
522
548
|
|
|
523
549
|
// A record's loader-owned handle values claim their loader, so its own
|
|
524
|
-
// cache() HIT does not replay them again (restoreHandles).
|
|
525
|
-
|
|
526
|
-
|
|
550
|
+
// cache() HIT does not replay them again (restoreHandles). A document
|
|
551
|
+
// HIT tail restores a bake-lane owner's values as the prelude's, unclaimed:
|
|
552
|
+
// they stand against any later push of that loader
|
|
553
|
+
// (HandleStore.pushRestored). An owner the route runs on the live lane is
|
|
554
|
+
// a hole, so its live run still replaces them, even inside a restored
|
|
555
|
+
// loader's body.
|
|
556
|
+
const ownedPushes: OwnedPushDelivery = {
|
|
557
|
+
claim: (ctx.handlerContext as InternalHandlerContext)._claimLoaderPushes,
|
|
558
|
+
};
|
|
559
|
+
if (tailMarker) {
|
|
560
|
+
ownedPushes.liveLane = liveLaneLoaderIds(ctx.entries);
|
|
561
|
+
ownedPushes.restore = tailMarker.docTail === true;
|
|
562
|
+
}
|
|
527
563
|
const explicitLookup = await ctx.cacheScope.lookupRouteDetailed(
|
|
528
564
|
ctx.pathname,
|
|
529
565
|
ctx.matched.params,
|
|
530
566
|
ctx.isIntercept,
|
|
531
|
-
|
|
567
|
+
ownedPushes,
|
|
532
568
|
);
|
|
533
569
|
let cacheResult =
|
|
534
570
|
explicitLookup.status === "hit" ? explicitLookup.result : null;
|
|
@@ -572,7 +608,7 @@ export function withCacheLookup<TEnv>(
|
|
|
572
608
|
ctx.pathname,
|
|
573
609
|
ctx.matched.params,
|
|
574
610
|
ctx.isIntercept,
|
|
575
|
-
|
|
611
|
+
ownedPushes,
|
|
576
612
|
);
|
|
577
613
|
} else if (explicitLookup.status === "bypass") {
|
|
578
614
|
// condition() refused at lookup time (the gate only pre-decides the
|
|
@@ -585,6 +621,13 @@ export function withCacheLookup<TEnv>(
|
|
|
585
621
|
}
|
|
586
622
|
|
|
587
623
|
if (!cacheResult) {
|
|
624
|
+
// A document shell HIT tail replays the handler layer from the entry's
|
|
625
|
+
// doc record and must never run a handler behind the committed prelude:
|
|
626
|
+
// a record that did not hit (it failed to decode, or the entry lost it)
|
|
627
|
+
// ends the tail here; serveShellHit degrades the response.
|
|
628
|
+
if (replayMarker?.docTail) {
|
|
629
|
+
throw new ShellRecordUnavailableError(replayMarker.fixedDocKey);
|
|
630
|
+
}
|
|
588
631
|
yield* source;
|
|
589
632
|
if (ms) {
|
|
590
633
|
ms.metrics.push({
|
|
@@ -658,7 +701,6 @@ export function withCacheLookup<TEnv>(
|
|
|
658
701
|
...liveMatchedIds,
|
|
659
702
|
...cacheResult.segments.map((s) => s.id),
|
|
660
703
|
];
|
|
661
|
-
const pprTransitionDecisions = pipelineReqCtx?._pprTransitionDecisions;
|
|
662
704
|
|
|
663
705
|
const canCheckSegmentRevalidation =
|
|
664
706
|
!ctx.isFullMatch &&
|
|
@@ -734,13 +776,7 @@ export function withCacheLookup<TEnv>(
|
|
|
734
776
|
reason: "cached-no-rules",
|
|
735
777
|
});
|
|
736
778
|
}
|
|
737
|
-
|
|
738
|
-
// segment otherwise needs no update. Keep its replayed component so the
|
|
739
|
-
// partial result retains the segment for gateTransitions().
|
|
740
|
-
if (!pprTransitionDecisions?.has(segment.id)) {
|
|
741
|
-
segment.component = null;
|
|
742
|
-
segment.loading = undefined;
|
|
743
|
-
}
|
|
779
|
+
keepClientSegment(segment);
|
|
744
780
|
yield segment;
|
|
745
781
|
continue;
|
|
746
782
|
}
|
|
@@ -772,10 +808,7 @@ export function withCacheLookup<TEnv>(
|
|
|
772
808
|
shouldRevalidate,
|
|
773
809
|
});
|
|
774
810
|
|
|
775
|
-
if (!shouldRevalidate
|
|
776
|
-
segment.component = null;
|
|
777
|
-
segment.loading = undefined;
|
|
778
|
-
}
|
|
811
|
+
if (!shouldRevalidate) keepClientSegment(segment);
|
|
779
812
|
|
|
780
813
|
yield segment;
|
|
781
814
|
}
|
|
@@ -107,6 +107,8 @@ import {
|
|
|
107
107
|
} from "../../server/request-context.js";
|
|
108
108
|
import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
109
109
|
import { createShellImplicitDocScope } from "../../cache/cache-scope.js";
|
|
110
|
+
import { recordSegmentTags } from "../../cache/cache-tag.js";
|
|
111
|
+
import { executionStart } from "../../cache/tag-invalidation.js";
|
|
110
112
|
import { getRouterContext } from "../router-context.js";
|
|
111
113
|
import { debugLog, debugWarn, getOrCreateRequestId } from "../logging.js";
|
|
112
114
|
import { INTERNAL_RANGO_DEBUG } from "../../internal-debug.js";
|
|
@@ -127,6 +129,9 @@ export function withCacheStore<TEnv>(
|
|
|
127
129
|
source: AsyncGenerator<ResolvedSegment>,
|
|
128
130
|
): AsyncGenerator<ResolvedSegment> {
|
|
129
131
|
const ms = ctx.metricsStore;
|
|
132
|
+
// Before the lookup and the handlers below it run: the record's write
|
|
133
|
+
// gate (#977, CacheScope.cacheRoute).
|
|
134
|
+
const renderStart = executionStart();
|
|
130
135
|
|
|
131
136
|
const allSegments: ResolvedSegment[] = [];
|
|
132
137
|
for await (const segment of source) {
|
|
@@ -262,6 +267,10 @@ export function withCacheStore<TEnv>(
|
|
|
262
267
|
ctx.matched.params,
|
|
263
268
|
allSegmentsToCache,
|
|
264
269
|
ctx.isIntercept,
|
|
270
|
+
// A capture's doc record lives only in the shell entry, which
|
|
271
|
+
// putShell gates by the capture start; skipping it here would
|
|
272
|
+
// read as a render that produced no record.
|
|
273
|
+
cacheScope.isShellImplicitDocScope ? undefined : renderStart,
|
|
265
274
|
);
|
|
266
275
|
if (INTERNAL_RANGO_DEBUG) {
|
|
267
276
|
const dur = performance.now() - start;
|
|
@@ -316,9 +325,10 @@ export function withCacheStore<TEnv>(
|
|
|
316
325
|
* store) on the no-eligible-snapshot path, so the lookup's own refusal is
|
|
317
326
|
* still surfaced while the fallback has nothing to serve.
|
|
318
327
|
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
328
|
+
* Registered through requestCtx.onResponse, which a capture fires only after
|
|
329
|
+
* the handler pushes settle (settleCaptureRecord), and wrapped in
|
|
330
|
+
* requestCtx.waitUntil — during a capture that is the tracked-write override,
|
|
331
|
+
* so settleWrites awaits the record before the capture reads it.
|
|
322
332
|
*/
|
|
323
333
|
function recordShellCaptureDocRecord<TEnv>(
|
|
324
334
|
ctx: MatchContext<TEnv>,
|
|
@@ -336,12 +346,28 @@ function recordShellCaptureDocRecord<TEnv>(
|
|
|
336
346
|
if (!scope.allowsCache("write")) return;
|
|
337
347
|
|
|
338
348
|
const docScope = createShellImplicitDocScope(marker);
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
),
|
|
349
|
+
// The route scope's cache({ tags }), and its enclosing scopes' (#974),
|
|
350
|
+
// describe these segments too: on its HIT they arrive with the replayed
|
|
351
|
+
// record (recordSegmentTags in lookupRouteDetailed); on a fresh render they
|
|
352
|
+
// are recorded here, so the doc record, and the shell taking its tags,
|
|
353
|
+
// carries them either way.
|
|
354
|
+
recordSegmentTags(
|
|
355
|
+
segments.map((s) => s.id),
|
|
356
|
+
scope.resolveTags(requestCtx),
|
|
357
|
+
requestCtx,
|
|
346
358
|
);
|
|
359
|
+
// Through onResponse, like the implicit scope's own write: the capture
|
|
360
|
+
// fires these callbacks (settleCaptureRecord) only after the handler
|
|
361
|
+
// pushes settled, so the record's handle encode never races them.
|
|
362
|
+
requestCtx.onResponse((response) => {
|
|
363
|
+
requestCtx.waitUntil(() =>
|
|
364
|
+
docScope.cacheRoute(
|
|
365
|
+
ctx.pathname,
|
|
366
|
+
ctx.matched.params,
|
|
367
|
+
segments,
|
|
368
|
+
ctx.isIntercept,
|
|
369
|
+
),
|
|
370
|
+
);
|
|
371
|
+
return response;
|
|
372
|
+
});
|
|
347
373
|
}
|
|
@@ -281,6 +281,7 @@ export function buildMatchResult<TEnv>(
|
|
|
281
281
|
routeName: ctx.routeKey,
|
|
282
282
|
slots: Object.keys(state.slots).length > 0 ? state.slots : undefined,
|
|
283
283
|
...(interceptTargets.length > 0 ? { interceptTargets } : {}),
|
|
284
|
+
...(ctx.interceptTargeted ? { interceptTargeted: true } : {}),
|
|
284
285
|
routeMiddleware:
|
|
285
286
|
ctx.routeMiddleware.length > 0 ? ctx.routeMiddleware : undefined,
|
|
286
287
|
};
|
|
@@ -68,7 +68,12 @@ export interface MiddlewareContext<
|
|
|
68
68
|
|
|
69
69
|
debugPerformance(): void;
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
/**
|
|
72
|
+
* The visitor's theme (cookie or default); undefined without theme config.
|
|
73
|
+
* Guarded like `cookies()`: a read inside a `"use cache"` function throws
|
|
74
|
+
* (#971).
|
|
75
|
+
*/
|
|
76
|
+
readonly theme?: Theme;
|
|
72
77
|
|
|
73
78
|
setTheme?: (theme: Theme) => void;
|
|
74
79
|
|
package/src/router/middleware.ts
CHANGED
|
@@ -31,6 +31,8 @@ import {
|
|
|
31
31
|
} from "../cache/taint.js";
|
|
32
32
|
import { getCacheExecScope } from "../cache/cache-exec-scope.js";
|
|
33
33
|
import { assertNonCacheableReadAllowed } from "../server/context.js";
|
|
34
|
+
import { readGuardedTheme } from "../server/cookie-store.js";
|
|
35
|
+
import type { Theme } from "../theme/types.js";
|
|
34
36
|
|
|
35
37
|
// Re-export types consumed through this module's path.
|
|
36
38
|
export type {
|
|
@@ -40,6 +42,22 @@ export type {
|
|
|
40
42
|
MiddlewareFn,
|
|
41
43
|
} from "./middleware-types.js";
|
|
42
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Middleware ctx.theme: the visitor's theme cookie, guarded like the handler
|
|
47
|
+
* ctx.theme and cookies() (#971, #946), so a read inside a "use cache"
|
|
48
|
+
* function the middleware calls throws. Non-enumerable like the handler and
|
|
49
|
+
* request-context getters: a spread of the ctx (inside a "use cache"
|
|
50
|
+
* function, say) does not read it. One shared descriptor, so every ctx keeps
|
|
51
|
+
* the same property shape.
|
|
52
|
+
*/
|
|
53
|
+
const MIDDLEWARE_THEME_DESCRIPTOR: PropertyDescriptor = {
|
|
54
|
+
get(): Theme | undefined {
|
|
55
|
+
return readGuardedTheme(_getRequestContext(), "ctx.theme");
|
|
56
|
+
},
|
|
57
|
+
enumerable: false,
|
|
58
|
+
configurable: true,
|
|
59
|
+
};
|
|
60
|
+
|
|
43
61
|
const MIDDLEWARE_METRIC_DEPTH = 1;
|
|
44
62
|
const POST_METRIC_MIN_DURATION_MS = 0.01;
|
|
45
63
|
|
|
@@ -320,10 +338,7 @@ export function createMiddlewareContext<TEnv>(
|
|
|
320
338
|
responseHolder.response.headers.set(name, value);
|
|
321
339
|
},
|
|
322
340
|
|
|
323
|
-
|
|
324
|
-
return _getRequestContext()?.theme;
|
|
325
|
-
},
|
|
326
|
-
|
|
341
|
+
// theme: MIDDLEWARE_THEME_DESCRIPTOR, defined after this literal.
|
|
327
342
|
get setTheme(): MiddlewareContext<TEnv>["setTheme"] {
|
|
328
343
|
return _getRequestContext()?.setTheme;
|
|
329
344
|
},
|
|
@@ -361,6 +376,7 @@ export function createMiddlewareContext<TEnv>(
|
|
|
361
376
|
}
|
|
362
377
|
},
|
|
363
378
|
};
|
|
379
|
+
Object.defineProperty(ctx, "theme", MIDDLEWARE_THEME_DESCRIPTOR);
|
|
364
380
|
(ctx as any)[NOCACHE_SYMBOL] = true;
|
|
365
381
|
return ctx;
|
|
366
382
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { requestHeaders } from "../server/request-headers.js";
|
|
1
2
|
import type { RouteMatchResult } from "./pattern-matching.js";
|
|
2
3
|
|
|
3
4
|
export interface NavigationSnapshot {
|
|
@@ -40,8 +41,8 @@ export interface ResolveNavigationDeps {
|
|
|
40
41
|
*/
|
|
41
42
|
export function getNavigationContextHeader(request: Request): string | null {
|
|
42
43
|
return (
|
|
43
|
-
request.
|
|
44
|
-
request.
|
|
44
|
+
requestHeaders(request).get("X-RSC-Router-Client-Path") ||
|
|
45
|
+
requestHeaders(request).get("Referer")
|
|
45
46
|
);
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -59,7 +60,7 @@ export function prerenderStoreShortCircuits(
|
|
|
59
60
|
pr: true | undefined,
|
|
60
61
|
request: Request,
|
|
61
62
|
): boolean {
|
|
62
|
-
return pr === true && !request.
|
|
63
|
+
return pr === true && !requestHeaders(request).get("X-RSC-HMR");
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
/**
|
|
@@ -71,7 +72,7 @@ export function prerenderStoreShortCircuits(
|
|
|
71
72
|
* request would report `prerender-store` for an artifact that cannot serve.
|
|
72
73
|
*/
|
|
73
74
|
export function getInterceptSourceHeader(request: Request): string | null {
|
|
74
|
-
return request.
|
|
75
|
+
return requestHeaders(request).get("X-RSC-Router-Intercept-Source");
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
export async function resolveNavigation(
|
|
@@ -85,7 +86,7 @@ export async function resolveNavigation(
|
|
|
85
86
|
const stale = url.searchParams.get("_rsc_stale") === "true";
|
|
86
87
|
const previousUrl = getNavigationContextHeader(request);
|
|
87
88
|
const interceptSourceUrl = getInterceptSourceHeader(request);
|
|
88
|
-
const isHmr = !!request.
|
|
89
|
+
const isHmr = !!requestHeaders(request).get("X-RSC-HMR");
|
|
89
90
|
|
|
90
91
|
if (!previousUrl) {
|
|
91
92
|
return null;
|
|
@@ -223,6 +223,8 @@ export async function matchForPrerender<TEnv = any>(
|
|
|
223
223
|
res: stubRes,
|
|
224
224
|
cookie: () => undefined,
|
|
225
225
|
cookies: () => ({}),
|
|
226
|
+
_readCookie: () => undefined,
|
|
227
|
+
_readCookies: () => ({}),
|
|
226
228
|
setCookie: () => {},
|
|
227
229
|
deleteCookie: () => {},
|
|
228
230
|
header: () => {},
|
|
@@ -230,6 +232,7 @@ export async function matchForPrerender<TEnv = any>(
|
|
|
230
232
|
_setStatus: () => {},
|
|
231
233
|
_rotateStateCookie: () => {},
|
|
232
234
|
_setKeepCacheDirective: () => {},
|
|
235
|
+
_setFreshReadsCookie: () => {},
|
|
233
236
|
use: (() => {
|
|
234
237
|
throw new Error("use() not available during pre-rendering");
|
|
235
238
|
}) as any,
|
|
@@ -239,6 +242,8 @@ export async function matchForPrerender<TEnv = any>(
|
|
|
239
242
|
waitUntil: () => {},
|
|
240
243
|
onResponse: () => {},
|
|
241
244
|
_onResponseCallbacks: [],
|
|
245
|
+
// No theme at build time: no request cookie.
|
|
246
|
+
_readTheme: () => undefined,
|
|
242
247
|
setLocationState() {},
|
|
243
248
|
_locationState: undefined,
|
|
244
249
|
_renderBarrier: Promise.resolve(),
|
|
@@ -523,6 +528,8 @@ export async function renderStaticSegment<TEnv = any>(
|
|
|
523
528
|
res: stubRes,
|
|
524
529
|
cookie: () => undefined,
|
|
525
530
|
cookies: () => ({}),
|
|
531
|
+
_readCookie: () => undefined,
|
|
532
|
+
_readCookies: () => ({}),
|
|
526
533
|
setCookie: () => {},
|
|
527
534
|
deleteCookie: () => {},
|
|
528
535
|
header: () => {},
|
|
@@ -530,6 +537,7 @@ export async function renderStaticSegment<TEnv = any>(
|
|
|
530
537
|
_setStatus: () => {},
|
|
531
538
|
_rotateStateCookie: () => {},
|
|
532
539
|
_setKeepCacheDirective: () => {},
|
|
540
|
+
_setFreshReadsCookie: () => {},
|
|
533
541
|
use: (() => {
|
|
534
542
|
throw new Error("use() not available during static pre-rendering");
|
|
535
543
|
}) as any,
|
|
@@ -539,6 +547,8 @@ export async function renderStaticSegment<TEnv = any>(
|
|
|
539
547
|
waitUntil: () => {},
|
|
540
548
|
onResponse: () => {},
|
|
541
549
|
_onResponseCallbacks: [],
|
|
550
|
+
// No theme at build time: no request cookie.
|
|
551
|
+
_readTheme: () => undefined,
|
|
542
552
|
setLocationState() {},
|
|
543
553
|
_locationState: undefined,
|
|
544
554
|
_renderBarrier: Promise.resolve(),
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* Builds on RouteSnapshot from route-snapshot.ts.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
+
import { requestHeaders } from "../server/request-headers.js";
|
|
18
19
|
import { RouteNotFoundError } from "../errors.js";
|
|
19
20
|
import type { EntryData } from "../server/context.js";
|
|
20
21
|
import type { CollectedMiddleware } from "./middleware-types.js";
|
|
@@ -149,10 +150,11 @@ export async function classifyRequest<TEnv = any>(
|
|
|
149
150
|
): Promise<RequestPlan<TEnv>> {
|
|
150
151
|
const pathname = url.pathname;
|
|
151
152
|
const isAction =
|
|
152
|
-
request.
|
|
153
|
+
requestHeaders(request).has("rsc-action") ||
|
|
154
|
+
url.searchParams.has("_rsc_action");
|
|
153
155
|
const isLoaderFetch = url.searchParams.has("_rsc_loader");
|
|
154
156
|
const isPartialReq = url.searchParams.has("_rsc_partial");
|
|
155
|
-
const contentType = request.
|
|
157
|
+
const contentType = requestHeaders(request).get("content-type") || "";
|
|
156
158
|
const isFormSubmission =
|
|
157
159
|
contentType.includes("multipart/form-data") ||
|
|
158
160
|
contentType.includes("application/x-www-form-urlencoded");
|
|
@@ -176,7 +178,7 @@ export async function classifyRequest<TEnv = any>(
|
|
|
176
178
|
) {
|
|
177
179
|
let reloadUrl = stripInternalParams(url).toString();
|
|
178
180
|
if (isAction) {
|
|
179
|
-
const referer = request.
|
|
181
|
+
const referer = requestHeaders(request).get("referer");
|
|
180
182
|
if (referer) {
|
|
181
183
|
try {
|
|
182
184
|
const refererUrl = new URL(referer);
|
|
@@ -248,7 +250,8 @@ export async function classifyRequest<TEnv = any>(
|
|
|
248
250
|
}
|
|
249
251
|
|
|
250
252
|
const actionId =
|
|
251
|
-
request.
|
|
253
|
+
requestHeaders(request).get("rsc-action") ||
|
|
254
|
+
url.searchParams.get("_rsc_action");
|
|
252
255
|
|
|
253
256
|
const hasVariants =
|
|
254
257
|
snapshot.matched.negotiateVariants &&
|
|
@@ -518,7 +518,10 @@ export interface RangoOptions<TEnv = any> {
|
|
|
518
518
|
*
|
|
519
519
|
* Controls how long prefetch responses are kept in the client-side
|
|
520
520
|
* in-memory cache and sets `Cache-Control: private, max-age=<ttl>`
|
|
521
|
-
* on
|
|
521
|
+
* on prefetch responses, so the browser's HTTP cache may reuse them
|
|
522
|
+
* (`private`: shared caches such as a CDN do not store them). A route an
|
|
523
|
+
* intercept targets gets no prefetch `Cache-Control`: whether its
|
|
524
|
+
* response is the modal or the full page depends on the source page.
|
|
522
525
|
*
|
|
523
526
|
* The cache is automatically invalidated on server actions regardless
|
|
524
527
|
* of TTL, so this is primarily a staleness safety net.
|
|
@@ -37,7 +37,7 @@ import { applyViewTransitionDefault } from "./view-transition-default.js";
|
|
|
37
37
|
import { _getRequestContext } from "../../server/request-context.js";
|
|
38
38
|
import { getRouterContext } from "../router-context.js";
|
|
39
39
|
import { observeStreamedHandler } from "./streamed-handler-telemetry.js";
|
|
40
|
-
import {
|
|
40
|
+
import { observeSegmentHandler } from "../instrument.js";
|
|
41
41
|
import {
|
|
42
42
|
track,
|
|
43
43
|
RangoContext,
|
|
@@ -173,9 +173,7 @@ export async function resolveLoaders<TEnv>(
|
|
|
173
173
|
// bakes at capture regardless of the entry's loading() lane
|
|
174
174
|
// (loader-cache.ts capture branch) and its HIT-tail seed
|
|
175
175
|
// overlay needs the same key.
|
|
176
|
-
bakeLane || loaderEntry.
|
|
177
|
-
? segmentId
|
|
178
|
-
: null,
|
|
176
|
+
bakeLane || loaderEntry.bake === true ? segmentId : null,
|
|
179
177
|
),
|
|
180
178
|
),
|
|
181
179
|
entry,
|
|
@@ -223,7 +221,7 @@ export async function resolveLoaders<TEnv>(
|
|
|
223
221
|
loaderEntry,
|
|
224
222
|
ctx,
|
|
225
223
|
ctx.pathname,
|
|
226
|
-
bakeLane || loaderEntry.
|
|
224
|
+
bakeLane || loaderEntry.bake === true ? segmentId : null,
|
|
227
225
|
),
|
|
228
226
|
),
|
|
229
227
|
entry,
|
|
@@ -326,7 +324,6 @@ export async function resolveSegment<TEnv>(
|
|
|
326
324
|
transition: applyViewTransitionDefault(
|
|
327
325
|
entry.transition,
|
|
328
326
|
deps.viewTransitionDefault,
|
|
329
|
-
entry.shortCode,
|
|
330
327
|
),
|
|
331
328
|
params,
|
|
332
329
|
belongsToRoute: false,
|
|
@@ -396,7 +393,7 @@ export async function resolveSegment<TEnv>(
|
|
|
396
393
|
const doneRouteHandler = track(`handler:${entry.id}`, 2);
|
|
397
394
|
if (entry.loading) {
|
|
398
395
|
const result = handleHandlerResult(
|
|
399
|
-
|
|
396
|
+
observeSegmentHandler(entry.shortCode, entry.id, handler, context),
|
|
400
397
|
);
|
|
401
398
|
if (result instanceof Promise) {
|
|
402
399
|
warnOnStreamedResponse(result, entry.id);
|
|
@@ -420,7 +417,12 @@ export async function resolveSegment<TEnv>(
|
|
|
420
417
|
}
|
|
421
418
|
} else {
|
|
422
419
|
component = handleHandlerResult(
|
|
423
|
-
await
|
|
420
|
+
await observeSegmentHandler(
|
|
421
|
+
entry.shortCode,
|
|
422
|
+
entry.id,
|
|
423
|
+
handler,
|
|
424
|
+
context,
|
|
425
|
+
),
|
|
424
426
|
);
|
|
425
427
|
doneRouteHandler();
|
|
426
428
|
}
|
|
@@ -471,7 +473,6 @@ export async function resolveSegment<TEnv>(
|
|
|
471
473
|
transition: applyViewTransitionDefault(
|
|
472
474
|
entry.transition,
|
|
473
475
|
deps.viewTransitionDefault,
|
|
474
|
-
entry.shortCode,
|
|
475
476
|
),
|
|
476
477
|
params,
|
|
477
478
|
belongsToRoute: true,
|
|
@@ -560,7 +561,6 @@ export async function resolveOrphanLayout<TEnv>(
|
|
|
560
561
|
transition: applyViewTransitionDefault(
|
|
561
562
|
orphan.transition,
|
|
562
563
|
deps.viewTransitionDefault,
|
|
563
|
-
orphan.shortCode,
|
|
564
564
|
),
|
|
565
565
|
...(orphan.mountPath ? { mountPath: orphan.mountPath } : {}),
|
|
566
566
|
});
|
|
@@ -670,7 +670,12 @@ export async function resolveParallelEntry<TEnv>(
|
|
|
670
670
|
if (hasLoadingFallback) {
|
|
671
671
|
const result =
|
|
672
672
|
typeof handler === "function"
|
|
673
|
-
?
|
|
673
|
+
? observeSegmentHandler(
|
|
674
|
+
`${parentShortCode}.${slot}`,
|
|
675
|
+
`${parallelEntry.id}.${slot}`,
|
|
676
|
+
handler,
|
|
677
|
+
context,
|
|
678
|
+
)
|
|
674
679
|
: handler;
|
|
675
680
|
if (result instanceof Promise) {
|
|
676
681
|
result.finally(doneParallelHandler).catch(() => {});
|
|
@@ -694,7 +699,8 @@ export async function resolveParallelEntry<TEnv>(
|
|
|
694
699
|
} else {
|
|
695
700
|
component =
|
|
696
701
|
typeof handler === "function"
|
|
697
|
-
? await
|
|
702
|
+
? await observeSegmentHandler(
|
|
703
|
+
`${parentShortCode}.${slot}`,
|
|
698
704
|
`${parallelEntry.id}.${slot}`,
|
|
699
705
|
handler,
|
|
700
706
|
context,
|
|
@@ -714,7 +720,6 @@ export async function resolveParallelEntry<TEnv>(
|
|
|
714
720
|
transition: applyViewTransitionDefault(
|
|
715
721
|
parallelEntry.transition,
|
|
716
722
|
deps.viewTransitionDefault,
|
|
717
|
-
`${parentShortCode}.${slot}`,
|
|
718
723
|
),
|
|
719
724
|
params,
|
|
720
725
|
slot,
|
|
@@ -29,7 +29,7 @@ import type {
|
|
|
29
29
|
import type { SegmentResolutionDeps } from "../types.js";
|
|
30
30
|
import { debugLog } from "../logging.js";
|
|
31
31
|
import { tryStaticLookup } from "./static-store.js";
|
|
32
|
-
import {
|
|
32
|
+
import { observeSegmentHandler } from "../instrument.js";
|
|
33
33
|
import type { TelemetrySink } from "../telemetry.js";
|
|
34
34
|
import { resolveSink, safeEmit, getRequestId } from "../telemetry.js";
|
|
35
35
|
|
|
@@ -175,7 +175,9 @@ export async function resolveLayoutComponent<TEnv>(
|
|
|
175
175
|
// by track("handler:<id>") at the call site). handleHandlerResult stays OUTSIDE
|
|
176
176
|
// the span so a handler that returns a Response (redirect control flow, which it
|
|
177
177
|
// rethrows) is not recorded as a span error — mirrors the route-handler sites.
|
|
178
|
-
return handleHandlerResult(
|
|
178
|
+
return handleHandlerResult(
|
|
179
|
+
await observeSegmentHandler(entry.shortCode, entry.id, handler, context),
|
|
180
|
+
);
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
// ---------------------------------------------------------------------------
|