@rangojs/router 0.27.0 → 0.28.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/event-controller.d.ts +2 -1
- package/dist/types/browser/history-state.d.ts +3 -9
- package/dist/types/browser/navigation-store.d.ts +8 -6
- package/dist/types/browser/react/filter-segment-order.d.ts +2 -2
- package/dist/types/browser/segment-reconciler.d.ts +6 -4
- package/dist/types/browser/types.d.ts +2 -1
- package/dist/types/browser/wire-protocol.d.ts +25 -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/tag-invalidation.d.ts +10 -0
- 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 +4 -4
- 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 +4 -11
- package/dist/types/router/match-handlers.d.ts +2 -6
- package/dist/types/router/match-middleware/background-revalidation.d.ts +10 -20
- 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/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/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 +93 -0
- package/dist/types/router/segment-resolution/revalidation.d.ts +82 -31
- 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 +10 -0
- 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 +24 -104
- package/dist/types/server/rewrite-trail.d.ts +2 -2
- package/dist/types/testing/dispatch.d.ts +35 -18
- package/dist/types/types/cache-types.d.ts +6 -3
- package/dist/types/types/error-types.d.ts +9 -1
- 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 +34 -0
- package/dist/vite/index.js +3809 -3710
- package/package.json +1 -1
- package/skills/cache-guide/SKILL.md +8 -5
- package/skills/caching/SKILL.md +37 -18
- package/skills/document-cache/SKILL.md +13 -1
- package/skills/handler-use/SKILL.md +1 -1
- package/skills/intercept/SKILL.md +17 -7
- package/skills/middleware/SKILL.md +18 -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 +8 -1
- package/skills/testing/response-routes.md +6 -4
- package/skills/use-cache/SKILL.md +46 -8
- package/src/__internal.ts +7 -1
- package/src/browser/connection-warmup.ts +3 -1
- package/src/browser/event-controller.ts +5 -3
- package/src/browser/history-state.ts +6 -12
- package/src/browser/navigation-bridge.ts +14 -13
- package/src/browser/navigation-client.ts +18 -25
- package/src/browser/navigation-store.ts +25 -27
- package/src/browser/navigation-transaction.ts +4 -1
- 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/rsc-router.tsx +1 -0
- package/src/browser/segment-reconciler.ts +66 -53
- package/src/browser/server-action-bridge.ts +50 -57
- package/src/browser/types.ts +2 -1
- package/src/browser/wire-protocol.ts +41 -0
- package/src/cache/cache-key-utils.ts +11 -5
- package/src/cache/cache-runtime.ts +110 -50
- 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 +34 -13
- package/src/cache/handle-snapshot.ts +19 -7
- package/src/cache/segment-codec.ts +55 -0
- package/src/cache/shell-snapshot.ts +2 -2
- package/src/cache/tag-invalidation.ts +21 -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 +4 -4
- package/src/router/instrument.ts +4 -3
- package/src/router/intercept-resolution.ts +77 -75
- package/src/router/loader-resolution.ts +5 -4
- package/src/router/match-api.ts +4 -5
- package/src/router/match-context.ts +20 -12
- package/src/router/match-handlers.ts +8 -20
- package/src/router/match-middleware/background-revalidation.ts +41 -53
- package/src/router/match-middleware/cache-lookup.ts +675 -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 +4 -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/loader-cache.ts +14 -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 +137 -0
- package/src/router/segment-resolution/revalidation.ts +897 -776
- 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 +10 -0
- package/src/router.ts +12 -13
- 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 +757 -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 +212 -169
- 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 +26 -115
- package/src/server/rewrite-trail.ts +6 -4
- package/src/ssr/index.tsx +1 -1
- package/src/testing/dispatch.ts +223 -710
- package/src/testing/e2e/page-helpers.ts +2 -2
- package/src/testing/serve-shell-request.ts +23 -36
- package/src/types/cache-types.ts +6 -3
- package/src/types/error-types.ts +9 -1
- 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 +35 -0
- package/dist/types/router/segment-resolution/fresh.d.ts +0 -72
- package/src/router/segment-resolution/fresh.ts +0 -945
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Capture does NOT flow through the HTTP middleware pipeline. The integrated PPR
|
|
5
5
|
* serve path (rsc-rendering.ts + shell-serve.ts) builds a ShellCaptureDescriptor
|
|
6
6
|
* from the route's `ppr` path option after the served response is built and calls
|
|
7
|
-
*
|
|
7
|
+
* planShellCapture with it (ShellCaptureInput). The capture then runs as a background task that re-derives
|
|
8
8
|
* the page via `ctx.router.match()` under its OWN derived request context — fresh
|
|
9
|
-
* handle store, `
|
|
9
|
+
* handle store, `_shellCaptureState.run` so live-lane loaders mask (loader-mask.ts)
|
|
10
10
|
* and postpone at their loading() or inline <Suspense> boundary. The match is
|
|
11
11
|
* MIXED-CHAIN: cache()'d segments replay from ring 3, uncached segments execute
|
|
12
12
|
* their handlers. The record-first step (settleCaptureRecord) waits for the
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { type MatchResult } from "../types.js";
|
|
22
22
|
import { type ShellCaptureRefusal } from "./shell-capture-constants.js";
|
|
23
|
-
import { type RequestContext
|
|
23
|
+
import { type RequestContext } from "../server/request-context.js";
|
|
24
24
|
import { type HandleStore } from "../server/handle-store.js";
|
|
25
25
|
import type { SegmentCacheStore } from "../cache/types.js";
|
|
26
26
|
import type { HandlerContext } from "./handler-context.js";
|
|
@@ -128,7 +128,7 @@ export interface ShellCaptureDebugEvent {
|
|
|
128
128
|
* - skip-stored: a capture for the key stored after the scheduling request
|
|
129
129
|
* read the store and missed (ShellCaptureDescriptor.storedSeqAtRead), so
|
|
130
130
|
* the shell that request missed exists now
|
|
131
|
-
* - skip-in-flight:
|
|
131
|
+
* - skip-in-flight: planShellCapture found a capture already running for
|
|
132
132
|
* the key (stampede guard) and scheduled nothing
|
|
133
133
|
* - skip-backoff: the key is inside its refused-capture backoff window and
|
|
134
134
|
* the capture was not attempted
|
|
@@ -268,7 +268,7 @@ export declare function gateFlightForCapture(source: ReadableStream<Uint8Array>)
|
|
|
268
268
|
* The background shell-capture descriptor: everything the capture task needs to
|
|
269
269
|
* store the shell. Built by the integrated PPR serve path (rsc-rendering.ts) from
|
|
270
270
|
* the route's `ppr` path option (`PartialPrerenderProps`) and the app-level cache
|
|
271
|
-
* store, and passed to
|
|
271
|
+
* store, and passed to planShellCapture in its input — it is NOT threaded through
|
|
272
272
|
* the request context. `tags` carries the route's OPERATIONAL `ppr.tags`; the
|
|
273
273
|
* capture UNIONS them with the shell's own auto-collected (non-loader) request
|
|
274
274
|
* tags from its derived render (the collected set stays authoritative). That
|
|
@@ -336,7 +336,7 @@ export interface ShellCaptureDescriptor {
|
|
|
336
336
|
/**
|
|
337
337
|
* Set for a shell keyed by the visitor's URL (`rewrite(...).shell("visitor")`,
|
|
338
338
|
* visitorShellKey): the capture renders the visitor's location
|
|
339
|
-
* (`
|
|
339
|
+
* (`ShellCaptureState.forVisitor`) and stores it as
|
|
340
340
|
* ShellCacheEntry.pathname.
|
|
341
341
|
*/
|
|
342
342
|
pathname?: string;
|
|
@@ -351,7 +351,7 @@ export interface ShellCaptureDescriptor {
|
|
|
351
351
|
/**
|
|
352
352
|
* A `router.prerender()` warm's capture (rsc-rendering.ts shellServePlan):
|
|
353
353
|
* one explicit call that must store, so the guards that shed a herd of
|
|
354
|
-
* visitors do not apply to it.
|
|
354
|
+
* visitors do not apply to it. planShellCapture skips the in-flight
|
|
355
355
|
* dedup and the refused-capture backoff, and attemptCapture waits longer on
|
|
356
356
|
* the write barrier. Every correctness guard, the inert-store skip and the
|
|
357
357
|
* queue limits still decide.
|
|
@@ -360,6 +360,21 @@ export interface ShellCaptureDescriptor {
|
|
|
360
360
|
}
|
|
361
361
|
/** The latest stored capture's sequence number for `key` in this isolate, or 0. */
|
|
362
362
|
export declare function lastStoredCaptureSeq(key: string): number;
|
|
363
|
+
/** One shell capture: the request it re-renders and what it stores. */
|
|
364
|
+
export interface ShellCaptureInput {
|
|
365
|
+
ctx: HandlerContext<any>;
|
|
366
|
+
request: Request;
|
|
367
|
+
env: any;
|
|
368
|
+
url: URL;
|
|
369
|
+
reqCtx: RequestContext<any>;
|
|
370
|
+
/**
|
|
371
|
+
* The SSR module for the capture's own request and URL, called once the
|
|
372
|
+
* capture leaves the queue. A document passes the module it already
|
|
373
|
+
* resolved, returned as is, so the capture awaits only a pending one.
|
|
374
|
+
*/
|
|
375
|
+
ssr: (request: Request, url: URL) => SSRModule | null | Promise<SSRModule | null>;
|
|
376
|
+
descriptor: ShellCaptureDescriptor;
|
|
377
|
+
}
|
|
363
378
|
/**
|
|
364
379
|
* Schedule the background shell capture for a served document. Stampede-guarded:
|
|
365
380
|
* one capture per key per isolate. Runs via runBackground (waitUntil on workerd,
|
|
@@ -367,15 +382,13 @@ export declare function lastStoredCaptureSeq(key: string): number;
|
|
|
367
382
|
* error is routed through reportCacheError — capture is best-effort; a failure just
|
|
368
383
|
* means the next request recaptures.
|
|
369
384
|
*
|
|
370
|
-
* Eligibility (nonce/partial/status/strategy) is decided by the caller.
|
|
371
|
-
* module loader may be passed for cold partial requests; it runs only after the
|
|
372
|
-
* capture enters the guarded background queue, never on response latency.
|
|
385
|
+
* Eligibility (nonce/partial/status/strategy) is decided by the caller.
|
|
373
386
|
*/
|
|
374
|
-
export declare function
|
|
387
|
+
export declare function planShellCapture(input: ShellCaptureInput): void;
|
|
375
388
|
/**
|
|
376
389
|
* The ttl/swr a shell is stored with: the route's ppr policy, capped by the
|
|
377
390
|
* route cache() records the capture replayed or wrote
|
|
378
|
-
* (
|
|
391
|
+
* (ShellCaptureState.routeRecordWindow). A HIT replays the capture's handler
|
|
379
392
|
* output, while a client navigation reads the route's cache() tier first, so
|
|
380
393
|
* a shell that outlived its record would show a document request other
|
|
381
394
|
* handler output than a navigation of the same URL. Freshness and total
|
|
@@ -456,9 +469,9 @@ type CaptureAttemptStats = Pick<ShellCaptureDebugEvent, "barrierWaitMs" | "write
|
|
|
456
469
|
* several HTTP requests before a capture stuck. We retry ONLY on `no-shell`
|
|
457
470
|
* that did not run out of ppr.captureTimeout (CaptureAttemptStats.noShellCause),
|
|
458
471
|
* and on `expired`; a genuine render error is NOT retried — it propagates to
|
|
459
|
-
*
|
|
472
|
+
* planShellCapture's reportCacheError. See docs/design/ppr-shell-resume.md.
|
|
460
473
|
*
|
|
461
|
-
* `request` and `url` are the capture's own identity (
|
|
474
|
+
* `request` and `url` are the capture's own identity (planShellCapture
|
|
462
475
|
* strips a navigation-only capture's transport parameters). `retryDelayMs` is
|
|
463
476
|
* a parameter (defaulting to the module const) so unit tests can drive the
|
|
464
477
|
* retry without a real 400ms wall-clock wait.
|
|
@@ -511,9 +524,113 @@ export type CaptureRecordOutcome = {
|
|
|
511
524
|
* a HIT restores, and its handle encode has its own 5s timeout that must
|
|
512
525
|
* never be the one that fires); then the capture's onResponse callbacks fire
|
|
513
526
|
* with a synthetic 200 (the implicit doc scope's cacheRoute, an explicit
|
|
514
|
-
* scope's own write), and the deferred writes settle.
|
|
527
|
+
* scope's own write), and the deferred writes settle. A match holding an
|
|
528
|
+
* error or notFound boundary throws before the callbacks fire.
|
|
515
529
|
*/
|
|
516
530
|
export declare function settleCaptureRecord(match: MatchResult, derivation: CaptureContextDerivation, capture: Pick<ShellCaptureDescriptor, "key">, deadline: number): Promise<CaptureRecordOutcome>;
|
|
531
|
+
/**
|
|
532
|
+
* @internal The freshness window of a route cache() record, as ms
|
|
533
|
+
* timestamps: fresh until `freshUntil` (its `expiresAt`), stale until
|
|
534
|
+
* `staleUntil` (plus its scope's swr). `ttl`, `swr` and `written` describe
|
|
535
|
+
* the record that sets `staleUntil`: its cache() config, and whether this
|
|
536
|
+
* capture wrote it (cacheRoute) rather than read it.
|
|
537
|
+
*/
|
|
538
|
+
export interface RouteRecordWindow {
|
|
539
|
+
freshUntil: number;
|
|
540
|
+
staleUntil: number;
|
|
541
|
+
ttl: number;
|
|
542
|
+
swr: number;
|
|
543
|
+
written: boolean;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* @internal What a shell capture's render records about itself, on its
|
|
547
|
+
* derived request context as `_shellCaptureState`.
|
|
548
|
+
* RENDER_PASS_FIELDS["shell-capture"] (server/render-pass.ts) creates it with
|
|
549
|
+
* every field present, so it keeps one shape while the capture writes it. A
|
|
550
|
+
* background re-render the capture starts has none: it writes a route
|
|
551
|
+
* record, under cache() rules (RENDER_PASS_FIELDS["background-revalidation"]).
|
|
552
|
+
*/
|
|
553
|
+
export interface ShellCaptureState {
|
|
554
|
+
/**
|
|
555
|
+
* @internal PPR shell-capture ACTIVE marker. True ONLY inside the background
|
|
556
|
+
* capture task's derived request context (built by shell-capture.ts). This is
|
|
557
|
+
* the switch every capture-specific behavior reads: loader masking
|
|
558
|
+
* (loader-mask.ts isShellCaptureActive / resolveOwnerLoaders) and the
|
|
559
|
+
* identity-read capture guard (server/context.ts guardIdentityRead). The
|
|
560
|
+
* foreground render never sets it, so the
|
|
561
|
+
* served response is byte-identical to axis 1. The capture descriptor itself
|
|
562
|
+
* (key/ttl/swr/tags/store) is NOT threaded through the request context — the
|
|
563
|
+
* integrated PPR serve path (rsc/shell-serve.ts + rsc-rendering.ts) builds it
|
|
564
|
+
* locally and passes it to planShellCapture in its input.
|
|
565
|
+
*/
|
|
566
|
+
readonly run: true;
|
|
567
|
+
/**
|
|
568
|
+
* @internal Set beside `run` when the shell is keyed by the
|
|
569
|
+
* visitor's URL (`rewrite(...).shell("visitor")`): the capture renders the
|
|
570
|
+
* visitor's location and `ctx.rewrittenFrom`; the theme stays the default.
|
|
571
|
+
*/
|
|
572
|
+
forVisitor: boolean | undefined;
|
|
573
|
+
/**
|
|
574
|
+
* @internal Bake-lane loader containers collected DURING a shell capture:
|
|
575
|
+
* segment-key -> the loader's (pre-wrap) result promise. Populated by
|
|
576
|
+
* resolveLoaderData for bake-lane loaders (lane rule: see its JSDoc in
|
|
577
|
+
* loader-cache.ts). Drained by captureAndStoreShell after the shell
|
|
578
|
+
* quiesces: settled containers are promise-elided, Flight-serialized, and
|
|
579
|
+
* pinned into the snapshot's loader family; a REJECTED container refuses
|
|
580
|
+
* the capture (error UI must never bake into the shared shell).
|
|
581
|
+
*/
|
|
582
|
+
loaderRecords: Map<string, Promise<unknown>>;
|
|
583
|
+
/**
|
|
584
|
+
* @internal Set when a loader pushed a
|
|
585
|
+
* value the record cannot keep (masked nested promises, a pushed promise
|
|
586
|
+
* that settled to one, a live-lane loader's push, or a push outside a
|
|
587
|
+
* loader body): the loader records then carry `runs: 1`, so a HIT still
|
|
588
|
+
* runs their bodies for those pushes.
|
|
589
|
+
*/
|
|
590
|
+
unrecordedLoaderPush: true | undefined;
|
|
591
|
+
/**
|
|
592
|
+
* @internal The lane of each loader the capture's matched route registers
|
|
593
|
+
* (loader-cache.ts routeLoaderLanes), set by createMatchContextForFull
|
|
594
|
+
* before any loader runs. The capture's push funnel credits a push made
|
|
595
|
+
* under a live-lane loader's body, at any depth, to that loader
|
|
596
|
+
* (shell-capture.ts deriveShellCaptureContext).
|
|
597
|
+
*/
|
|
598
|
+
loaderLanes: ReadonlyMap<string, "live" | "bake"> | undefined;
|
|
599
|
+
/**
|
|
600
|
+
* @internal Set by the capture guard (server/context.ts
|
|
601
|
+
* guardIdentityRead) when it throws DURING a capture render: the read
|
|
602
|
+
* ("cookies()", "headers()", `ctx.get() for a non-cacheable variable`,
|
|
603
|
+
* "ctx.theme") and the fix the
|
|
604
|
+
* refusal warning gives for it. Load-bearing for the
|
|
605
|
+
* bake lane: a guard throw inside an executing loader is swallowed by
|
|
606
|
+
* wrapLoaderPromise into per-loader error UI, which would otherwise bake
|
|
607
|
+
* silently into the shared shell — the capture checks this flag after the
|
|
608
|
+
* render and refuses instead. Deterministic, so the capture does not retry.
|
|
609
|
+
*/
|
|
610
|
+
guardTripped: {
|
|
611
|
+
surface: string;
|
|
612
|
+
fix: string;
|
|
613
|
+
} | undefined;
|
|
614
|
+
/**
|
|
615
|
+
* @internal The loader $$id whose BODY was executing when the capture guard
|
|
616
|
+
* tripped (read off the loader-body ALS scope at trip time), or undefined
|
|
617
|
+
* when the read came from handler/render code. Only used to make the
|
|
618
|
+
* once-per-key refusal warning name the real source — the old text
|
|
619
|
+
* hardcoded "a bake-lane loader", which misattributed handler-land reads
|
|
620
|
+
* and sent users debugging the wrong lane (issue #672, secondary).
|
|
621
|
+
*/
|
|
622
|
+
guardTrippedLoaderId: string | undefined;
|
|
623
|
+
/**
|
|
624
|
+
* @internal The freshness window of the route cache() records this
|
|
625
|
+
* capture read or wrote (cache-scope.ts noteRouteRecordWindow), as ms
|
|
626
|
+
* timestamps: `freshUntil` is the record's `expiresAt`, `staleUntil` adds
|
|
627
|
+
* its scope's swr. The narrowest record wins. A shell capture caps its
|
|
628
|
+
* entry's ttl and ttl+swr to it (shell-capture.ts capShellWindow), so a
|
|
629
|
+
* shell is never fresher, or served longer, than the route cache() entry
|
|
630
|
+
* it replayed or wrote.
|
|
631
|
+
*/
|
|
632
|
+
routeRecordWindow: RouteRecordWindow | undefined;
|
|
633
|
+
}
|
|
517
634
|
/**
|
|
518
635
|
* The derived capture context and its fresh (mask-funneled) handle store,
|
|
519
636
|
* shared by BOTH shell producers: the runtime background capture
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { type EntryData } from "../server/context.js";
|
|
19
19
|
import type { DocumentShellCacheEntry, ShellCacheEntry, ShellDocumentRead, ShellEntryHead, ShellReadStats, ShellSnapshotFailure, ShellSnapshotRecord, SegmentCacheStore } from "../cache/types.js";
|
|
20
|
+
import type { MetricsStore } from "../server/context.js";
|
|
20
21
|
export { PPR_REPLAY_STATUS_HEADER, SHELL_STATUS_HEADER, buildShellKey, navigationShellKey, partitionShellKey, shellSearchSeed, } from "./shell-capture-constants.js";
|
|
21
22
|
/**
|
|
22
23
|
* Default shell ttl (seconds) for `ppr: true` and for a PartialPrerenderProps
|
|
@@ -76,18 +77,13 @@ export declare function normalizeCaptureTimeout(value: unknown): number | undefi
|
|
|
76
77
|
*/
|
|
77
78
|
export declare function resolvePprConfig(entry: EntryData | undefined | null): ResolvedPprConfig | null;
|
|
78
79
|
/**
|
|
79
|
-
* The forced-MISS
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* the
|
|
84
|
-
*
|
|
85
|
-
|
|
86
|
-
export declare const SHELL_MISS_PARAM: string;
|
|
87
|
-
/**
|
|
88
|
-
* The request without the forced-MISS marker, or undefined when it carries
|
|
89
|
-
* none. The handler calls it before anything reads the request: left in, the
|
|
90
|
-
* marker reached `ctx.request.url`, `originalUrl`, middleware, and the SSR
|
|
80
|
+
* The request without the forced-MISS marker (`WIRE.shellMiss`), or
|
|
81
|
+
* undefined when it carries none. A document HIT that cannot finish its tail
|
|
82
|
+
* reloads the page with the marker (shellReloadScript); the serve gate
|
|
83
|
+
* renders a request carrying it on axis 1, with no shell read and no
|
|
84
|
+
* capture, so the reload can never be a HIT that degrades again. The handler
|
|
85
|
+
* calls this on entry, before anything reads the request, and keeps only the
|
|
86
|
+
* flag (RequestContext._shellForcedMiss): left in, the marker reached `ctx.request.url`, `originalUrl`, middleware, and the SSR
|
|
91
87
|
* search seed (so `useSearchParams` rendered it), and a `"use cache"` key
|
|
92
88
|
* built from the request URL was never read again. GET and HEAD only: the
|
|
93
89
|
* reload is a navigation, and a request with a body cannot be re-created
|
|
@@ -165,6 +161,35 @@ export interface ShellDocument {
|
|
|
165
161
|
*/
|
|
166
162
|
export declare function openShellDocument(entry: ShellCacheEntry): ShellDocument | null;
|
|
167
163
|
export declare function openShellDocument(entry: ShellEntryHead, read: Pick<ShellDocumentRead, "prelude" | "snapshot" | "snapshotFailure" | "stats">): ShellDocument | null;
|
|
164
|
+
/**
|
|
165
|
+
* A document serve's store read: a getShell entry, or a prelude-first read
|
|
166
|
+
* (readShellDocument) whose entry is the head and whose snapshot arrives on
|
|
167
|
+
* its own promise.
|
|
168
|
+
*/
|
|
169
|
+
export type ShellRead = {
|
|
170
|
+
entry: ShellCacheEntry;
|
|
171
|
+
shouldRevalidate?: boolean;
|
|
172
|
+
read?: undefined;
|
|
173
|
+
} | {
|
|
174
|
+
entry: ShellEntryHead;
|
|
175
|
+
shouldRevalidate?: boolean;
|
|
176
|
+
read: ShellDocumentRead;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* The document serve's shell read from `source`, the app cache store, that
|
|
180
|
+
* degrades to null on failure (axis 1 MISS, never a 500) and records the raw
|
|
181
|
+
* `ppr:shell-read` outcome (pre-validity-gates, so a version-mismatch
|
|
182
|
+
* lifecycle miss stays distinguishable from a store miss). A store with a
|
|
183
|
+
* prelude-first read (readShellDocument) resolves before the snapshot is
|
|
184
|
+
* read, so the HIT commits without waiting for it. A build shell is read by
|
|
185
|
+
* shell-build-manifest.ts lookupBuildShell, which imports this module.
|
|
186
|
+
*/
|
|
187
|
+
export declare function readShell(source: SegmentCacheStore & {
|
|
188
|
+
getShell: NonNullable<SegmentCacheStore["getShell"]>;
|
|
189
|
+
}, key: string, opts: {
|
|
190
|
+
tagHints?: readonly string[];
|
|
191
|
+
metrics?: MetricsStore;
|
|
192
|
+
}): Promise<ShellRead | null>;
|
|
168
193
|
/**
|
|
169
194
|
* Prelude enqueue granularity. A streaming compressor in front of the worker
|
|
170
195
|
* emits its first byte only after compressing the whole write it was handed:
|
|
@@ -121,7 +121,7 @@ export type LoaderEntry = {
|
|
|
121
121
|
* thrown notFound()/redirect() deterministically precede first flush.
|
|
122
122
|
* Resolved at DSL-evaluation time from ctx.isSSR — entries are cached
|
|
123
123
|
* per-isSSR (router/manifest.ts cache key), so the flag is already
|
|
124
|
-
* request-mode-correct when
|
|
124
|
+
* request-mode-correct when resolveOwnerLoaders reads it and never
|
|
125
125
|
* appears on navigation-lane entries. Set by documentModeLoader, which
|
|
126
126
|
* getDocumentModeEntry also applies to a lazy include's captured ancestors.
|
|
127
127
|
*/
|
|
@@ -566,7 +566,7 @@ export interface IdentityReadWording {
|
|
|
566
566
|
* only observed; it is never rendered. A cached body, loader body or
|
|
567
567
|
* funnel they start is guarded again.
|
|
568
568
|
* 1. A PPR shell capture (`ctx` is the capture's derived context,
|
|
569
|
-
* `
|
|
569
|
+
* `_shellCaptureState`) trips first: the capture context is flagged (so a
|
|
570
570
|
* caught throw still refuses the capture) and the read throws. The shell is
|
|
571
571
|
* shared per host+URL, and every HIT replays what the capture read. There
|
|
572
572
|
* is no loader-body exemption here: a bake-lane loader and a loader a
|
|
@@ -737,12 +737,13 @@ export declare function latchPprHeaderScopeForEntries(entries: EntryData[], rout
|
|
|
737
737
|
* ONLY the ppr (shell) axis is dropped — dynamic() does NOT opt off the CACHE
|
|
738
738
|
* axis. Two cases:
|
|
739
739
|
* - Pure ppr funnel (no cache() boundary): clear the latch → writes re-permit.
|
|
740
|
-
* - ppr route nested under a cache() boundary:
|
|
741
|
-
* funnel top (first-wins), which MASKS the positional
|
|
742
|
-
* handler still runs inside the cache scope
|
|
743
|
-
* HIT skips that handler, so the write is
|
|
744
|
-
* "cache" instead of clearing, so the
|
|
745
|
-
* wording). This is why the check keys
|
|
740
|
+
* - ppr route nested under a cache() boundary: resolveAllSegments
|
|
741
|
+
* latches "ppr" at the funnel top (first-wins), which MASKS the positional
|
|
742
|
+
* cache() latch, but the handler still runs inside the cache scope
|
|
743
|
+
* (`insideCacheScope`). A cache() HIT skips that handler, so the write is
|
|
744
|
+
* still non-deterministic — UNMASK to "cache" instead of clearing, so the
|
|
745
|
+
* guard keeps throwing (accurate cache() wording). This is why the check keys
|
|
746
|
+
* off `insideCacheScope`, not just kind.
|
|
746
747
|
*
|
|
747
748
|
* A subsequent cache() entered AFTER dynamic() on a pure-ppr funnel re-latches
|
|
748
749
|
* "cache" via latchCachedHeaderScope's `!store.cachedHeaderScope` guard (the
|
|
@@ -169,6 +169,22 @@ export interface HandleStore {
|
|
|
169
169
|
* array, in order. Without placeholders it is a plain replay.
|
|
170
170
|
*/
|
|
171
171
|
replacePlaceholders(loaderIds: readonly string[], deliver: () => void): void;
|
|
172
|
+
/**
|
|
173
|
+
* A cache() or Prerender() HIT restored its stored values into
|
|
174
|
+
* `segmentIds` (cache-lookup.ts serveStoredSegments). The MISS ran each
|
|
175
|
+
* segment's handler after it started the segment's loaders, so a push into
|
|
176
|
+
* a restored array goes in front of the stored values until
|
|
177
|
+
* releaseRecordedValues: a loader's push lands where the same loader timing
|
|
178
|
+
* puts it on the MISS.
|
|
179
|
+
*/
|
|
180
|
+
holdRecordedValues(segmentIds: readonly string[]): void;
|
|
181
|
+
/**
|
|
182
|
+
* The HIT's loader walk reached the place where the MISS ran
|
|
183
|
+
* `segmentId`'s handler (revalidation.ts resolveLoadersOnly,
|
|
184
|
+
* intercept-resolution.ts resolveInterceptLoadersOnly): later pushes
|
|
185
|
+
* follow the record's values.
|
|
186
|
+
*/
|
|
187
|
+
releaseRecordedValues(segmentId: string): void;
|
|
172
188
|
/**
|
|
173
189
|
* Get all collected handle data after all handlers have settled.
|
|
174
190
|
* Waits for `settled` (handler lane), then returns the data at that point.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derived render passes over a request past its middleware (PPR shell
|
|
3
|
+
* capture, PPR HIT tail, background re-render, document cache re-run), each
|
|
4
|
+
* `Object.create(base)`.
|
|
5
|
+
* A field missing from a RENDER_PASS_FIELDS row reads the foreground
|
|
6
|
+
* request's value (#684). derived-context-shape.rsc-test.tsx pins each row's
|
|
7
|
+
* own keys.
|
|
8
|
+
*/
|
|
9
|
+
import type { RecordingShellStore } from "../cache/shell-snapshot.js";
|
|
10
|
+
import type { HandleStore } from "./handle-store.js";
|
|
11
|
+
import { type RequestContext } from "./request-context.js";
|
|
12
|
+
type ShellImplicitCache = NonNullable<RequestContext["_shellImplicitCache"]>;
|
|
13
|
+
/** _handleStore, readonly on RequestContext, is written by the rows. */
|
|
14
|
+
type PassUnderConstruction = RequestContext<any> & {
|
|
15
|
+
_handleStore: HandleStore;
|
|
16
|
+
};
|
|
17
|
+
/** What each purpose's caller builds for its row. */
|
|
18
|
+
export interface RenderPassInit {
|
|
19
|
+
"shell-capture": {
|
|
20
|
+
handleStore: HandleStore;
|
|
21
|
+
/** A navigation-only capture renders this URL instead of the request's. */
|
|
22
|
+
identity: {
|
|
23
|
+
request: Request;
|
|
24
|
+
url: URL;
|
|
25
|
+
} | undefined;
|
|
26
|
+
/** Only with a cache store on the request. */
|
|
27
|
+
recording: {
|
|
28
|
+
store: RecordingShellStore;
|
|
29
|
+
implicitCache: ShellImplicitCache;
|
|
30
|
+
} | undefined;
|
|
31
|
+
};
|
|
32
|
+
"ppr-tail": {
|
|
33
|
+
/** The request's store, shared: the tail's handles are this response's. */
|
|
34
|
+
handleStore: HandleStore;
|
|
35
|
+
loaderSeed: RequestContext["_shellLoaderSeed"];
|
|
36
|
+
implicitCache: ShellImplicitCache;
|
|
37
|
+
};
|
|
38
|
+
"background-revalidation": {
|
|
39
|
+
handleStore: HandleStore;
|
|
40
|
+
/** Throwaway: the pass's response writes land here and are dropped. */
|
|
41
|
+
sink: RequestContext<any>;
|
|
42
|
+
};
|
|
43
|
+
"document-revalidation": {
|
|
44
|
+
/** The request's: the stale HIT pushed nothing into it. */
|
|
45
|
+
handleStore: HandleStore;
|
|
46
|
+
/**
|
|
47
|
+
* Holds the re-run's response writes, which make the response the
|
|
48
|
+
* document cache stores; starts from the request's response stub.
|
|
49
|
+
*/
|
|
50
|
+
sink: RequestContext<any>;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export type RenderPurpose = keyof RenderPassInit;
|
|
54
|
+
interface PassFieldPolicy<I> {
|
|
55
|
+
/** "own": wireRenderBarrier(pass, init.handleStore) before `own` runs. */
|
|
56
|
+
readonly renderBarrier: "own" | "inherited";
|
|
57
|
+
/**
|
|
58
|
+
* Named stores, not one Object.assign: on Node 24 an Object.assign that
|
|
59
|
+
* takes the object to 20 own properties leaves it in V8 dictionary mode
|
|
60
|
+
* (#1109).
|
|
61
|
+
*/
|
|
62
|
+
readonly own: (pass: PassUnderConstruction, init: I, base: RequestContext<any>) => void;
|
|
63
|
+
}
|
|
64
|
+
export declare const RENDER_PASS_FIELDS: {
|
|
65
|
+
readonly [P in RenderPurpose]: PassFieldPolicy<RenderPassInit[P]>;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* `Object.create(base)` with RENDER_PASS_FIELDS[purpose]'s own fields. The only
|
|
69
|
+
* place a request context is derived (tools/check-internals.mjs).
|
|
70
|
+
*/
|
|
71
|
+
export declare function deriveRenderPass<P extends RenderPurpose, TEnv>(base: RequestContext<TEnv>, purpose: P, init: RenderPassInit[P]): RequestContext<TEnv>;
|
|
72
|
+
export {};
|
|
@@ -29,6 +29,7 @@ import type { RenderMode, RenderPhase } from "../router/timeout.js";
|
|
|
29
29
|
import type { LocationStateEntry } from "../browser/react/location-state-shared.js";
|
|
30
30
|
import type { RoutineTrace } from "../rsc/routine-plan.js";
|
|
31
31
|
import type { ActionContinuation } from "../rsc/server-action.js";
|
|
32
|
+
import type { ShellCaptureState } from "../rsc/shell-capture.js";
|
|
32
33
|
import type { FormActionOutcome } from "../rsc/progressive-enhancement.js";
|
|
33
34
|
import { type ExecutionStart } from "../cache/invalidation-order.js";
|
|
34
35
|
export interface RenderForegroundCursor {
|
|
@@ -182,8 +183,8 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
182
183
|
method: string;
|
|
183
184
|
/**
|
|
184
185
|
* @internal Handle store for tracking handle data across segments.
|
|
185
|
-
* Readonly: a
|
|
186
|
-
* (
|
|
186
|
+
* Readonly: a render that needs its own store derives a render pass
|
|
187
|
+
* (deriveRenderPass, server/render-pass.ts) instead of swapping this field,
|
|
187
188
|
* which the foreground still reads while it produces the page.
|
|
188
189
|
*/
|
|
189
190
|
readonly _handleStore: HandleStore;
|
|
@@ -233,52 +234,13 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
233
234
|
*/
|
|
234
235
|
_searchParamsFilter?: import("../cache/search-params-filter.js").SearchParamsFilter;
|
|
235
236
|
/**
|
|
236
|
-
* @internal PPR shell
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
* (key/ttl/swr/tags/store) is NOT threaded through the request context — the
|
|
244
|
-
* integrated PPR serve path (rsc/shell-serve.ts + rsc-rendering.ts) builds it
|
|
245
|
-
* locally and passes it to scheduleShellCapture directly.
|
|
246
|
-
*/
|
|
247
|
-
_shellCaptureRun?: boolean;
|
|
248
|
-
/**
|
|
249
|
-
* @internal Set beside `_shellCaptureRun` when the shell is keyed by the
|
|
250
|
-
* visitor's URL (`rewrite(...).shell("visitor")`): the capture renders the
|
|
251
|
-
* visitor's location and `ctx.rewrittenFrom`; the theme stays the default.
|
|
252
|
-
*/
|
|
253
|
-
_shellCaptureForVisitor?: boolean;
|
|
254
|
-
/**
|
|
255
|
-
* @internal Bake-lane loader containers collected DURING a shell capture:
|
|
256
|
-
* segment-key -> the loader's (pre-wrap) result promise. Populated by
|
|
257
|
-
* resolveLoaderData for bake-lane loaders (lane rule: see its JSDoc in
|
|
258
|
-
* loader-cache.ts). Drained by captureAndStoreShell after the shell
|
|
259
|
-
* quiesces: settled containers are promise-elided, Flight-serialized, and
|
|
260
|
-
* pinned into the snapshot's loader family; a REJECTED container refuses
|
|
261
|
-
* the capture (error UI must never bake into the shared shell). Own
|
|
262
|
-
* property of the capture's derived context only.
|
|
263
|
-
*/
|
|
264
|
-
_shellCaptureLoaderRecords?: Map<string, Promise<unknown>>;
|
|
265
|
-
/**
|
|
266
|
-
* @internal Set on a capture's derived context when a loader pushed a
|
|
267
|
-
* value the record cannot keep (masked nested promises, a pushed promise
|
|
268
|
-
* that settled to one, a live-lane loader's push, or a push outside a
|
|
269
|
-
* loader body): the loader records then carry `runs: 1`, so a HIT still
|
|
270
|
-
* runs their bodies for those pushes.
|
|
271
|
-
*/
|
|
272
|
-
_shellCaptureUnrecordedLoaderPush?: true;
|
|
273
|
-
/**
|
|
274
|
-
* @internal The lane of each loader the capture's matched route registers
|
|
275
|
-
* (loader-cache.ts routeLoaderLanes), set by createMatchContextForFull
|
|
276
|
-
* before any loader runs. The capture's push funnel credits a push made
|
|
277
|
-
* under a live-lane loader's body, at any depth, to that loader
|
|
278
|
-
* (shell-capture.ts deriveShellCaptureContext). Own property of the
|
|
279
|
-
* capture's derived context only.
|
|
280
|
-
*/
|
|
281
|
-
_shellCaptureLoaderLanes?: ReadonlyMap<string, "live" | "bake">;
|
|
237
|
+
* @internal A PPR shell capture's own state (rsc/shell-capture.ts
|
|
238
|
+
* ShellCaptureState): created by RENDER_PASS_FIELDS["shell-capture"]
|
|
239
|
+
* (server/render-pass.ts) on the capture's derived context. The foreground
|
|
240
|
+
* render and every background re-render never have one, so
|
|
241
|
+
* `_shellCaptureState?.run` is the capture switch.
|
|
242
|
+
*/
|
|
243
|
+
_shellCaptureState?: ShellCaptureState;
|
|
282
244
|
/**
|
|
283
245
|
* @internal Record keys resolved for this request (CacheScope
|
|
284
246
|
* resolveKeyFrom): by the scope's `key()` (one result) or its store's
|
|
@@ -295,9 +257,9 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
295
257
|
_shellKey?: string;
|
|
296
258
|
/**
|
|
297
259
|
* @internal The request carried the forced-MISS reload marker
|
|
298
|
-
* (
|
|
299
|
-
*
|
|
300
|
-
* cache miss.
|
|
260
|
+
* (`WIRE.shellMiss`). The handler strips the marker from the request on
|
|
261
|
+
* entry (shell-serve.ts withoutShellMissMarker) and sets this; the shell
|
|
262
|
+
* gate renders the request like a cache miss.
|
|
301
263
|
*/
|
|
302
264
|
_shellForcedMiss?: true;
|
|
303
265
|
/**
|
|
@@ -314,16 +276,6 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
314
276
|
* runtime has no AsyncLocalStorage.snapshot.
|
|
315
277
|
*/
|
|
316
278
|
_runAtRequestEntry?: <T>(fn: () => T) => T;
|
|
317
|
-
/**
|
|
318
|
-
* @internal The freshness window of the route cache() records this
|
|
319
|
-
* request read or wrote (cache-scope.ts noteRouteRecordWindow), as ms
|
|
320
|
-
* timestamps: `freshUntil` is the record's `expiresAt`, `staleUntil` adds
|
|
321
|
-
* its scope's swr. The narrowest record wins. A shell capture caps its
|
|
322
|
-
* entry's ttl and ttl+swr to it (shell-capture.ts capShellWindow), so a
|
|
323
|
-
* shell is never fresher, or served longer, than the route cache() entry
|
|
324
|
-
* it replayed or wrote.
|
|
325
|
-
*/
|
|
326
|
-
_routeRecordWindow?: RouteRecordWindow;
|
|
327
279
|
/**
|
|
328
280
|
* @internal Loader-family snapshot seed for a shell HIT's tail render:
|
|
329
281
|
* loader id -> the capture's elided container (already Flight-deserialized
|
|
@@ -445,30 +397,6 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
445
397
|
* it as an own property for exactly that reason.
|
|
446
398
|
*/
|
|
447
399
|
_shellFragmentPayload?: boolean;
|
|
448
|
-
/**
|
|
449
|
-
* @internal Set by the capture guard (server/context.ts
|
|
450
|
-
* guardIdentityRead) when it throws DURING a capture render: the read
|
|
451
|
-
* ("cookies()", "headers()", `ctx.get() for a non-cacheable variable`,
|
|
452
|
-
* "ctx.theme") and the fix the
|
|
453
|
-
* refusal warning gives for it. Load-bearing for the
|
|
454
|
-
* bake lane: a guard throw inside an executing loader is swallowed by
|
|
455
|
-
* wrapLoaderPromise into per-loader error UI, which would otherwise bake
|
|
456
|
-
* silently into the shared shell — the capture checks this flag after the
|
|
457
|
-
* render and refuses instead. Deterministic, so the capture does not retry.
|
|
458
|
-
*/
|
|
459
|
-
_shellCaptureGuardTripped?: {
|
|
460
|
-
surface: string;
|
|
461
|
-
fix: string;
|
|
462
|
-
};
|
|
463
|
-
/**
|
|
464
|
-
* @internal The loader $$id whose BODY was executing when the capture guard
|
|
465
|
-
* tripped (read off the loader-body ALS scope at trip time), or undefined
|
|
466
|
-
* when the read came from handler/render code. Only used to make the
|
|
467
|
-
* once-per-key refusal warning name the real source — the old text
|
|
468
|
-
* hardcoded "a bake-lane loader", which misattributed handler-land reads
|
|
469
|
-
* and sent users debugging the wrong lane (issue #672, secondary).
|
|
470
|
-
*/
|
|
471
|
-
_shellCaptureGuardTrippedLoaderId?: string;
|
|
472
400
|
/**
|
|
473
401
|
* @internal Handler-owned registry of explicit per-scope stores from
|
|
474
402
|
* cache({ store }). Created once per createRSCHandler() and threaded into
|
|
@@ -732,8 +660,8 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
732
660
|
* (loader(Def, { ssr: false })): segment resolution awaits these
|
|
733
661
|
* before returning, so the render barrier cannot resolve until they settle.
|
|
734
662
|
* rendered() checks this set to fail fast — a flagged loader awaiting the
|
|
735
|
-
* barrier is a guaranteed cycle, not a race. Registered by
|
|
736
|
-
*
|
|
663
|
+
* barrier is a guaranteed cycle, not a race. Registered by resolveOwnerLoaders
|
|
664
|
+
* before loader kickoff; only ever populated on document renders
|
|
737
665
|
* (the flag is stamped per-isSSR at DSL evaluation).
|
|
738
666
|
*/
|
|
739
667
|
_awaitBeforeFlushLoaderIds?: Set<string>;
|
|
@@ -811,6 +739,12 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
811
739
|
* keeping phases that began before the opt-in at their true (non-negative) offset.
|
|
812
740
|
*/
|
|
813
741
|
_handlerStart?: number;
|
|
742
|
+
/**
|
|
743
|
+
* @internal Handler-level Server-Timing entries (rsc/handler.ts): the
|
|
744
|
+
* bootstrap timings, then the core handler's classify. A stale document
|
|
745
|
+
* cache entry's re-run has its own (render-pass.ts).
|
|
746
|
+
*/
|
|
747
|
+
_handlerTiming?: string[];
|
|
814
748
|
/** @internal Resolved platform phase-span tracing for this request (Cloudflare or OTel) */
|
|
815
749
|
_tracing?: ResolvedTracing;
|
|
816
750
|
/** @internal Router basename for this request (used by redirect()) */
|
|
@@ -846,27 +780,13 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
846
780
|
*/
|
|
847
781
|
_cacheSignal?: import("../router/telemetry.js").CacheSegmentSignal[];
|
|
848
782
|
}
|
|
849
|
-
/**
|
|
850
|
-
* @internal The freshness window of a route cache() record, as ms
|
|
851
|
-
* timestamps: fresh until `freshUntil` (its `expiresAt`), stale until
|
|
852
|
-
* `staleUntil` (plus its scope's swr). `ttl`, `swr` and `written` describe
|
|
853
|
-
* the record that sets `staleUntil`: its cache() config, and whether this
|
|
854
|
-
* request wrote it (cacheRoute) rather than read it.
|
|
855
|
-
*/
|
|
856
|
-
export interface RouteRecordWindow {
|
|
857
|
-
freshUntil: number;
|
|
858
|
-
staleUntil: number;
|
|
859
|
-
ttl: number;
|
|
860
|
-
swr: number;
|
|
861
|
-
written: boolean;
|
|
862
|
-
}
|
|
863
783
|
/**
|
|
864
784
|
* Public view of RequestContext, without internal methods and fields.
|
|
865
785
|
*
|
|
866
786
|
* This is the type exported to library consumers. Internal code should
|
|
867
787
|
* use the full RequestContext interface directly.
|
|
868
788
|
*/
|
|
869
|
-
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "_readCookie" | "_readCookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhenRefs" | "_pprReplayPostMatchReason" | "_cacheStore" | "_prerender" | "_onDemandProducer" | "_searchParamsFilter" | "
|
|
789
|
+
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "_readCookie" | "_readCookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhenRefs" | "_pprReplayPostMatchReason" | "_cacheStore" | "_prerender" | "_onDemandProducer" | "_searchParamsFilter" | "_shellCaptureState" | "_shellImplicitCache" | "_shellLoaderSeed" | "_resolvedCacheKeys" | "_shellKey" | "_shellForcedMiss" | "_prerenderWarm" | "_runAtRequestEntry" | "_shellFragmentPayload" | "_explicitTaggedStores" | "_requestTags" | "_recordTagOwners" | "_recordLoaderTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "_payloadDeferred" | "_requestKind" | "_payloadVisitorLocation" | "_locationState" | "_routeName" | "_prevRouteKey" | "_visitorMoved" | "_inActionRevalidation" | "_actionRan" | "_reportedErrors" | "_printedErrors" | "_renderErrors" | "_recoveredHandlerErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_handlerTiming" | "_tracing" | "_basename" | "_routerId" | "_versions" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_freshReads" | "_setFreshReadsCookie" | "_requestRoot" | "_requestStart" | "_responseSent" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
870
790
|
/**
|
|
871
791
|
* Marker for a waitUntil-scheduled fn whose task promise must NOT enter
|
|
872
792
|
* _pendingBackgroundTasks. Used by the PPR shell capture for its own task:
|
|
@@ -1004,8 +924,8 @@ export declare function rebaseRequestContext(ctx: RequestContext<any>, request:
|
|
|
1004
924
|
/**
|
|
1005
925
|
* Wire a fresh render barrier onto `ctx`, closure-bound to THIS ctx and THIS
|
|
1006
926
|
* handle store. Called by createRequestContext for every fresh context, and by
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
927
|
+
* deriveRenderPass (server/render-pass.ts) for a derived pass whose
|
|
928
|
+
* RENDER_PASS_FIELDS row owns its barrier (the PPR capture and the HIT tail).
|
|
1009
929
|
*
|
|
1010
930
|
* The derived-context call is load-bearing (issue #684, plan 009): the capture
|
|
1011
931
|
* context is `Object.create(reqCtx)`, so without its own wiring every
|