@rangojs/router 0.31.0 → 0.33.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/bin/browser-7KIJ5HSV.js +15 -0
- package/dist/bin/chunk-3B7CKBRO.js +463 -0
- package/dist/bin/chunk-524VACCG.js +71 -0
- package/dist/bin/chunk-LD7UBHT4.js +196 -0
- package/dist/bin/chunk-TO6CRWLN.js +1429 -0
- package/dist/bin/chunk-TTXC2U3G.js +2477 -0
- package/dist/bin/client-urls-projection-DQLWPDAT.js +28 -0
- package/dist/bin/forward-user-plugins-URBZKJP4.js +62 -0
- package/dist/bin/rango.js +42 -10143
- package/dist/bin/runtime-EPUDEHO4.js +596 -0
- package/dist/bin/runtime-discovery-CZ2QHT4Q.js +352 -0
- package/dist/bin/state-ACD2MGKJ.js +16 -0
- package/dist/bin/temp-rsc-server-QRR6HD6T.js +3190 -0
- package/dist/types/bin/rango.d.ts +1 -0
- package/dist/types/browser/action-fence.d.ts +20 -0
- package/dist/types/browser/cookie-name.d.ts +51 -10
- package/dist/types/browser/history-state.d.ts +13 -2
- package/dist/types/browser/invalidate-client-cache.d.ts +8 -6
- package/dist/types/browser/navigation-bridge.d.ts +36 -1
- package/dist/types/browser/navigation-client.d.ts +19 -0
- package/dist/types/browser/navigation-store-handle.d.ts +37 -4
- package/dist/types/browser/navigation-store.d.ts +2 -2
- package/dist/types/browser/navigation-transaction.d.ts +0 -1
- package/dist/types/browser/partial-update.d.ts +13 -0
- package/dist/types/browser/prefetch/cache.d.ts +96 -8
- package/dist/types/browser/prefetch/fetch.d.ts +26 -2
- package/dist/types/browser/prefetch/queue.d.ts +3 -2
- package/dist/types/browser/rango-state.d.ts +34 -5
- package/dist/types/browser/react/Link.d.ts +19 -13
- package/dist/types/browser/react/location-state-shared.d.ts +2 -1
- package/dist/types/browser/types.d.ts +25 -0
- package/dist/types/build/generate-route-types.d.ts +1 -1
- package/dist/types/build/route-types/include-resolution.d.ts +9 -1
- package/dist/types/build/route-types/router-processing.d.ts +3 -1
- package/dist/types/cache/cache-key-utils.d.ts +12 -8
- package/dist/types/cache/cache-scope.d.ts +4 -2
- package/dist/types/cache/cf/cf-cache-types.d.ts +9 -5
- package/dist/types/cache/document-cache-policy.d.ts +9 -1
- package/dist/types/cache/memory-segment-store.d.ts +3 -2
- package/dist/types/cache/segment-codec.d.ts +2 -2
- package/dist/types/cache/shell-snapshot.d.ts +1 -1
- package/dist/types/cache/types.d.ts +12 -7
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +2 -1
- package/dist/types/client-urls/types.d.ts +7 -5
- package/dist/types/prefetch-markers.d.ts +9 -0
- package/dist/types/prefetch-source-scope.d.ts +66 -0
- package/dist/types/route-definition/helpers-types.d.ts +8 -5
- package/dist/types/route-definition/redirect.d.ts +5 -0
- package/dist/types/router/intercept-resolution.d.ts +25 -11
- package/dist/types/router/match-context.d.ts +1 -0
- package/dist/types/router/match-handlers.d.ts +1 -1
- package/dist/types/router/middleware-types.d.ts +6 -0
- package/dist/types/router/prefetch-cache-ttl.d.ts +11 -3
- package/dist/types/router/router-context.d.ts +1 -1
- package/dist/types/router/router-options.d.ts +6 -3
- package/dist/types/router/segment-resolution/loader-cache.d.ts +8 -0
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +23 -7
- package/dist/types/router/segment-resolution/revalidation.d.ts +19 -0
- package/dist/types/router/source-reads.d.ts +53 -0
- package/dist/types/router/types.d.ts +1 -1
- package/dist/types/rsc/helpers.d.ts +8 -3
- package/dist/types/rsc/prefetch-render-error.d.ts +7 -2
- package/dist/types/rsc/request-stages.d.ts +4 -0
- package/dist/types/rsc/shell-serve.d.ts +6 -1
- package/dist/types/server/context.d.ts +23 -6
- package/dist/types/server/cookie-store.d.ts +15 -1
- package/dist/types/server/document-location-state.d.ts +59 -0
- package/dist/types/server/handle-store.d.ts +2 -0
- package/dist/types/server/request-context.d.ts +65 -12
- package/dist/types/testing/e2e/server.d.ts +16 -1
- package/dist/types/testing/render-route.d.ts +83 -2
- package/dist/types/testing/serve-shell-request.d.ts +15 -3
- package/dist/types/types/handler-context.d.ts +21 -4
- package/dist/types/types/loader-types.d.ts +7 -4
- package/dist/types/types/segments.d.ts +18 -1
- package/dist/types/urls/path-helper-types.d.ts +7 -5
- package/dist/types/vite/temp-rsc-server.d.ts +2 -2
- package/dist/types/vite/utils/forward-user-plugins.d.ts +32 -2
- package/dist/vite/index.js +451 -191
- package/package.json +2 -2
- package/skills/app-structure/SKILL.md +74 -0
- package/skills/app-structure/e-commerce.md +10 -9
- package/skills/app-structure/large-app.md +15 -2
- package/skills/caching/SKILL.md +10 -5
- package/skills/client-urls/SKILL.md +18 -11
- package/skills/comparison/references/framework-comparison.md +16 -10
- package/skills/document-cache/SKILL.md +13 -0
- package/skills/hooks/navigation.md +8 -8
- package/skills/hooks/state.md +132 -12
- package/skills/intercept/SKILL.md +33 -11
- package/skills/layout/SKILL.md +11 -0
- package/skills/links/SKILL.md +101 -4
- package/skills/loader/SKILL.md +49 -22
- package/skills/migrate-nextjs/SKILL.md +8 -2
- package/skills/migrate-react-router/data-and-actions.md +5 -0
- package/skills/ppr/SKILL.md +38 -5
- package/skills/prerender/SKILL.md +4 -1
- package/skills/route/SKILL.md +6 -6
- package/skills/router-setup/SKILL.md +2 -1
- package/skills/server-actions/SKILL.md +49 -8
- package/skills/testing/client-components.md +73 -32
- package/skills/testing/serve-shell-request.md +45 -20
- package/skills/testing/server-actions.md +8 -0
- package/skills/ux-architecture/SKILL.md +67 -15
- package/src/bin/rango.ts +39 -13
- package/src/browser/action-fence.ts +72 -0
- package/src/browser/cookie-name.ts +82 -14
- package/src/browser/history-state.ts +24 -2
- package/src/browser/invalidate-client-cache.ts +9 -7
- package/src/browser/navigation-bridge.ts +164 -32
- package/src/browser/navigation-client.ts +95 -20
- package/src/browser/navigation-store-handle.ts +67 -5
- package/src/browser/navigation-store.ts +86 -17
- package/src/browser/navigation-transaction.ts +0 -6
- package/src/browser/partial-update.ts +31 -12
- package/src/browser/prefetch/cache.ts +188 -11
- package/src/browser/prefetch/fetch.ts +211 -51
- package/src/browser/prefetch/queue.ts +3 -2
- package/src/browser/rango-state.ts +50 -8
- package/src/browser/react/Link.tsx +24 -16
- package/src/browser/react/location-state-shared.ts +8 -1
- package/src/browser/react/use-navigation.ts +1 -1
- package/src/browser/rsc-router.tsx +13 -3
- package/src/browser/server-action-bridge.ts +3 -3
- package/src/browser/types.ts +25 -0
- package/src/build/generate-route-types.ts +1 -0
- package/src/build/route-types/include-resolution.ts +40 -3
- package/src/build/route-types/router-processing.ts +170 -25
- package/src/build/route-types/scan-filter.ts +1 -0
- package/src/build/runtime-discovery.ts +46 -8
- package/src/cache/cache-key-utils.ts +12 -8
- package/src/cache/cache-runtime.ts +5 -1
- package/src/cache/cache-scope.ts +28 -7
- package/src/cache/cf/cf-cache-types.ts +9 -5
- package/src/cache/document-cache-policy.ts +37 -1
- package/src/cache/document-cache.ts +12 -0
- package/src/cache/memory-segment-store.ts +3 -2
- package/src/cache/segment-codec.ts +2 -2
- package/src/cache/shell-snapshot.ts +1 -1
- package/src/cache/types.ts +12 -7
- package/src/cache/vercel/vercel-cache-store.ts +2 -1
- package/src/client-urls/types.ts +7 -5
- package/src/prefetch-markers.ts +10 -0
- package/src/prefetch-source-scope.ts +137 -0
- package/src/route-definition/helpers-types.ts +8 -5
- package/src/route-definition/redirect.ts +5 -0
- package/src/router/intercept-resolution.ts +94 -50
- package/src/router/loader-resolution.ts +8 -6
- package/src/router/match-api.ts +33 -29
- package/src/router/match-context.ts +5 -0
- package/src/router/match-handlers.ts +2 -1
- package/src/router/match-middleware/cache-lookup.ts +39 -14
- package/src/router/match-result.ts +45 -85
- package/src/router/middleware-types.ts +6 -0
- package/src/router/navigation-snapshot.ts +18 -3
- package/src/router/prefetch-cache-ttl.ts +15 -3
- package/src/router/revalidation.ts +63 -13
- package/src/router/router-context.ts +2 -1
- package/src/router/router-options.ts +6 -3
- package/src/router/segment-resolution/loader-cache.ts +21 -3
- package/src/router/segment-resolution/prefetch-deferral.ts +38 -31
- package/src/router/segment-resolution/revalidation.ts +40 -12
- package/src/router/source-reads.ts +122 -0
- package/src/router/types.ts +2 -1
- package/src/router.ts +11 -12
- package/src/rsc/helpers.ts +20 -6
- package/src/rsc/prefetch-render-error.ts +7 -2
- package/src/rsc/progressive-enhancement.ts +8 -2
- package/src/rsc/request-stages.ts +87 -1
- package/src/rsc/rsc-rendering.ts +78 -32
- package/src/rsc/server-action.ts +2 -1
- package/src/rsc/shell-capture.ts +4 -5
- package/src/rsc/shell-serve.ts +12 -1
- package/src/segment-system.tsx +1 -1
- package/src/server/context.ts +37 -6
- package/src/server/cookie-store.ts +22 -1
- package/src/server/document-location-state.ts +334 -0
- package/src/server/handle-store.ts +2 -0
- package/src/server/request-context.ts +137 -33
- package/src/testing/dispatch.ts +6 -0
- package/src/testing/e2e/fixture.ts +4 -12
- package/src/testing/e2e/server.ts +91 -4
- package/src/testing/render-route.tsx +309 -10
- package/src/testing/run-revalidate.ts +11 -1
- package/src/testing/serve-shell-request.ts +22 -3
- package/src/types/handler-context.ts +21 -4
- package/src/types/loader-types.ts +7 -4
- package/src/types/segments.ts +18 -1
- package/src/urls/path-helper-types.ts +7 -5
- package/src/vite/temp-rsc-server.ts +2 -2
- package/src/vite/utils/forward-user-plugins.ts +13 -5
|
@@ -7,20 +7,15 @@
|
|
|
7
7
|
import type { EntryData, InterceptEntry, InterceptSelectorContext } from "../server/context";
|
|
8
8
|
import type { ResolvedSegment } from "../types";
|
|
9
9
|
import type { ResolutionPass } from "./segment-resolution/resolution-pass.js";
|
|
10
|
+
import { type InterceptResult } from "./router-context.js";
|
|
10
11
|
/**
|
|
11
12
|
* Check if an intercept's when conditions are satisfied.
|
|
12
13
|
* All when() functions must return true for the intercept to activate.
|
|
13
14
|
* If no when() conditions are defined, the intercept always activates.
|
|
14
15
|
* A selector that throws yields the conservative default, no intercept (the
|
|
15
16
|
* full page renders), and is logged; it never fails the request.
|
|
16
|
-
*
|
|
17
|
-
* During action revalidation, when() is NOT evaluated.
|
|
18
|
-
*/
|
|
19
|
-
export declare function evaluateInterceptWhen(intercept: InterceptEntry, selectorContext: InterceptSelectorContext | null, isAction: boolean): boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Find an intercept for the target route by walking up the entry chain.
|
|
22
|
-
* Returns the first (innermost) matching intercept along with the entry that defines it.
|
|
23
17
|
*/
|
|
18
|
+
export declare function evaluateInterceptWhen(intercept: InterceptEntry, selectorContext: InterceptSelectorContext | null): boolean;
|
|
24
19
|
/**
|
|
25
20
|
* Collect every intercept TARGET route name reachable from an origin entry —
|
|
26
21
|
* the same chain walk findInterceptForRoute() performs when this location is
|
|
@@ -33,10 +28,29 @@ export declare function evaluateInterceptWhen(intercept: InterceptEntry, selecto
|
|
|
33
28
|
* loses its optimistic loading, never the reverse.
|
|
34
29
|
*/
|
|
35
30
|
export declare function collectInterceptTargetNames(fromEntry: EntryData | null): string[];
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
/**
|
|
32
|
+
* The intercept for the target route, with the entry that declares it.
|
|
33
|
+
* `targetRouteKeys` are the names it may be declared for, in precedence
|
|
34
|
+
* order: the route's own name, then its local name inside include()
|
|
35
|
+
* (match-api.ts). A navigation, or an action with no `held`, takes the first
|
|
36
|
+
* along the chain from `fromEntry` up under the first name that has one: on a
|
|
37
|
+
* navigation, the first whose when() passes; on an action, the first, when()
|
|
38
|
+
* not evaluated.
|
|
39
|
+
*
|
|
40
|
+
* An action given `held` (the request's segment ids) re-renders the intercept
|
|
41
|
+
* on screen: one whose slot id the client holds, null when it holds none. Its
|
|
42
|
+
* candidates are collected under every name in one walk, the route's own
|
|
43
|
+
* name's first: a held id under the own name (a parallel() default of the
|
|
44
|
+
* slot's name) must not win before the local name is looked at. One held:
|
|
45
|
+
* that one, when() not evaluated, so an open intercept stays open when its
|
|
46
|
+
* when() would now reject. Several held (intercepts on one entry that fill one
|
|
47
|
+
* slot share its id, as does a parallel() slot of that name): the ones whose
|
|
48
|
+
* slot has no parallel() default on their entry, if any (a default holds its
|
|
49
|
+
* slot id whether or not an intercept is open there). One left: that one,
|
|
50
|
+
* when() not evaluated. Else the first whose when() passes against the
|
|
51
|
+
* action's intercept source, else the first.
|
|
52
|
+
*/
|
|
53
|
+
export declare function findInterceptForRoute(targetRouteKeys: string | readonly string[], fromEntry: EntryData | null, selectorContext?: InterceptSelectorContext | null, isAction?: boolean, held?: ReadonlySet<string>): InterceptResult | null;
|
|
40
54
|
/** The segment id of `intercept`'s slot on `parentEntry`. */
|
|
41
55
|
export declare function interceptSlotId(parentEntry: EntryData, intercept: InterceptEntry): string;
|
|
42
56
|
/**
|
|
@@ -177,6 +177,7 @@ export interface MatchPipelineState {
|
|
|
177
177
|
cachedSegments?: ResolvedSegment[];
|
|
178
178
|
cachedMatchedIds?: string[];
|
|
179
179
|
shouldRevalidate?: boolean;
|
|
180
|
+
storedStale?: boolean;
|
|
180
181
|
cacheSource?: "runtime" | "prerender";
|
|
181
182
|
segments: ResolvedSegment[];
|
|
182
183
|
matchedIds: string[];
|
|
@@ -11,7 +11,7 @@ export interface MatchHandlerDeps<TEnv = any> {
|
|
|
11
11
|
matchApiDeps: MatchApiDeps<TEnv>;
|
|
12
12
|
defaultErrorBoundary: ReactNode | ErrorBoundaryHandler | undefined;
|
|
13
13
|
findMatch: (pathname: string, ms?: any) => any;
|
|
14
|
-
findInterceptForRoute: (
|
|
14
|
+
findInterceptForRoute: (routeKeys: string | readonly string[], parentEntry: EntryData | null, selectorContext: InterceptSelectorContext | null, isAction: boolean, held?: ReadonlySet<string>) => {
|
|
15
15
|
intercept: InterceptEntry;
|
|
16
16
|
entry: EntryData;
|
|
17
17
|
} | null;
|
|
@@ -56,6 +56,12 @@ export interface MiddlewareContext<TEnv = any, TParams = Record<string, string |
|
|
|
56
56
|
*/
|
|
57
57
|
readonly theme?: Theme;
|
|
58
58
|
setTheme?: (theme: Theme) => void;
|
|
59
|
+
/**
|
|
60
|
+
* Attach location state entries to this response (see the handler
|
|
61
|
+
* context's `setLocationState`). Entries accumulate across definitions;
|
|
62
|
+
* for one definition the last write wins. Set it here rather than in a
|
|
63
|
+
* handler on a `ppr` route: a shell HIT runs no handler.
|
|
64
|
+
*/
|
|
59
65
|
setLocationState(entries: LocationStateEntry | LocationStateEntry[]): void;
|
|
60
66
|
/** Global route names only; see {@link GlobalReverseFunction}. */
|
|
61
67
|
reverse: GlobalReverseFunction<DefaultReverseRouteMap>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolve the prefetch cache TTL once, at router init, into the values the
|
|
3
3
|
* rest of the router consumes: seconds, and milliseconds for the client-side
|
|
4
|
-
* in-memory prefetch cache (shipped in payload metadata).
|
|
5
|
-
*
|
|
6
|
-
* render failed after its 200 went out (#1170).
|
|
4
|
+
* in-memory prefetch cache (shipped in payload metadata). A prefetch with a
|
|
5
|
+
* live part carries no Cache-Control: the browser HTTP cache would keep a
|
|
6
|
+
* prefetch whose render failed after its 200 went out (#1170). One answered
|
|
7
|
+
* from storage carries storedPrefetchCacheControl.
|
|
7
8
|
*
|
|
8
9
|
* `false` disables prefetch caching (seconds 0). A non-finite input
|
|
9
10
|
* (NaN/Infinity, e.g. from an env-derived number that failed to parse) is
|
|
@@ -22,3 +23,10 @@ export interface ResolvedPrefetchCacheTTL {
|
|
|
22
23
|
ms: number;
|
|
23
24
|
}
|
|
24
25
|
export declare function resolvePrefetchCacheTTL(rawTTL: number | false | undefined): ResolvedPrefetchCacheTTL;
|
|
26
|
+
/**
|
|
27
|
+
* The Cache-Control of a prefetch answer with nothing live in it
|
|
28
|
+
* (`_servedFromStorage`): the browser HTTP cache keeps it as long
|
|
29
|
+
* as the in-memory prefetch cache would. Undefined when prefetch caching is
|
|
30
|
+
* off.
|
|
31
|
+
*/
|
|
32
|
+
export declare function storedPrefetchCacheControl(ttlMs: number): string | undefined;
|
|
@@ -33,7 +33,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
33
33
|
};
|
|
34
34
|
getMetricsStore: () => MetricsStore | undefined;
|
|
35
35
|
createCacheScope: (cacheConfig: any, parent: CacheScope | null) => CacheScope | null;
|
|
36
|
-
findInterceptForRoute: (
|
|
36
|
+
findInterceptForRoute: (routeKeys: string | readonly string[], parentEntry: EntryData | null, selectorContext: InterceptSelectorContext, isAction: boolean, held?: ReadonlySet<string>) => InterceptResult | null;
|
|
37
37
|
/** The segment walker; a full match passes freshPassInput (FRESH). */
|
|
38
38
|
resolveAllSegments: (pass: ResolutionPassInput<TEnv>, entries: EntryData[], walk: RevalidatingWalkOptions) => Promise<{
|
|
39
39
|
segments: ResolvedSegment[];
|
|
@@ -493,9 +493,12 @@ export interface RangoOptions<TEnv = any> {
|
|
|
493
493
|
* TTL (in seconds) for the client-side in-memory prefetch cache.
|
|
494
494
|
*
|
|
495
495
|
* Controls how long prefetch responses are kept in the client-side
|
|
496
|
-
* in-memory cache.
|
|
497
|
-
*
|
|
498
|
-
*
|
|
496
|
+
* in-memory cache. A prefetch with nothing live in it (a document cache
|
|
497
|
+
* HIT, or every sent segment from a `cache()` record or a Prerender entry,
|
|
498
|
+
* with no loader) also carries `Cache-Control: private, max-age=<ttl>`,
|
|
499
|
+
* so the browser's HTTP cache keeps it as long. Any other prefetch carries
|
|
500
|
+
* none: a prefetch whose render failed after its 200 went out would
|
|
501
|
+
* otherwise answer later requests.
|
|
499
502
|
*
|
|
500
503
|
* The cache is automatically invalidated on server actions regardless
|
|
501
504
|
* of TTL, so this is primarily a staleness safety net.
|
|
@@ -61,6 +61,14 @@ export declare function bindsLoaderCache(entries: readonly EntryData[]): boolean
|
|
|
61
61
|
* one is live (shell-capture.ts deriveShellCaptureContext).
|
|
62
62
|
*/
|
|
63
63
|
export declare function routeLoaderLanes(entries: readonly EntryData[]): ReadonlyMap<string, "live" | "bake">;
|
|
64
|
+
/**
|
|
65
|
+
* This request serves `loaderEntry` from a pin (servedPins), so its body does
|
|
66
|
+
* not decide the value: resolveLoaderData serves a pin to an `ssr: false`
|
|
67
|
+
* registration only. A prefetch does not defer such a loader
|
|
68
|
+
* (prefetch-deferral.ts defersLoader): nothing would run, and the pin is the
|
|
69
|
+
* value the document shows.
|
|
70
|
+
*/
|
|
71
|
+
export declare function servesLoaderPin(loaderEntry: LoaderEntry, reqCtx?: RequestContext<any> | undefined): boolean;
|
|
64
72
|
/**
|
|
65
73
|
* What a record restored on a request over the matched chain `entries` is to
|
|
66
74
|
* each loader's handle pushes (HandleStore RecordAuthority), from the pins
|
|
@@ -30,11 +30,18 @@ import type { CacheScope } from "../../cache/cache-scope.js";
|
|
|
30
30
|
/**
|
|
31
31
|
* What a request says it is, read once when its context is created
|
|
32
32
|
* (RequestContext._requestKind). A fill is marked on the raw URL and wins
|
|
33
|
-
* over the prefetch header.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* over the prefetch header. `"prefetch"` is a speculative prefetch (viewport,
|
|
34
|
+
* render) and `"intent"` a hover or an explicit `prefetch()` call
|
|
35
|
+
* (PREFETCH_INTENT): both are prefetches, and only the first defers. Whether
|
|
36
|
+
* a prefetch defers anything is decided per match, by partialDeferralMode: a
|
|
37
|
+
* shell capture inherits the context of the request that scheduled it and is
|
|
38
|
+
* never a prefetch.
|
|
36
39
|
*/
|
|
37
|
-
export declare function requestKind(request: Request, rawUrl: URL):
|
|
40
|
+
export declare function requestKind(request: Request, rawUrl: URL): RequestKind | undefined;
|
|
41
|
+
/** requestKind's answer for a marked request. */
|
|
42
|
+
export type RequestKind = "prefetch" | "intent" | "fill";
|
|
43
|
+
/** A prefetch of either kind: speculative or intent. */
|
|
44
|
+
export declare function isPrefetchKind(kind: RequestKind | undefined): boolean;
|
|
38
45
|
/** Static, per matched chain. */
|
|
39
46
|
interface DeferralScope {
|
|
40
47
|
/**
|
|
@@ -158,7 +165,9 @@ export declare function resolveDeferralScope(entries: readonly EntryData[]): Def
|
|
|
158
165
|
export declare function resolveInterceptDeferralScope(intercept: InterceptEntry): DeferralScope;
|
|
159
166
|
/**
|
|
160
167
|
* Which half of the feature a partial request is, if either (`fill` and
|
|
161
|
-
* `prefetch` are requestKind's answer).
|
|
168
|
+
* `prefetch` are requestKind's answer). `prefetch` is a speculative prefetch
|
|
169
|
+
* only: an intent prefetch defers nothing, like the navigation it starts
|
|
170
|
+
* early (R16). Both halves are GETs: a request of
|
|
162
171
|
* another method that carries either marker is a normal request. A prefetch
|
|
163
172
|
* defers only on a plain GET navigation: an action re-renders what it
|
|
164
173
|
* changed, and a shell capture is never a prefetch whatever the request that
|
|
@@ -234,7 +243,7 @@ export declare function startDeferredLoader(ctx: HandlerContext<any, any>, loade
|
|
|
234
243
|
/**
|
|
235
244
|
* The segment a run of `loaderId` files its handle pushes under: the one
|
|
236
245
|
* that registers it when it is registered (registerDeferredLoader), else the
|
|
237
|
-
* segment
|
|
246
|
+
* segment whose code starts it (segmentPinOf).
|
|
238
247
|
*/
|
|
239
248
|
export declare function loaderOwner(ctx: HandlerContext<any, any>, loaderId: string): string | undefined;
|
|
240
249
|
/**
|
|
@@ -242,8 +251,15 @@ export declare function loaderOwner(ctx: HandlerContext<any, any>, loaderId: str
|
|
|
242
251
|
* does not hold that segment, and the loader is flagged itself or sits behind
|
|
243
252
|
* the fallback of a flagged entry the client does not hold either. Under a
|
|
244
253
|
* flagged layout the client holds, a new route's loaders run.
|
|
254
|
+
*
|
|
255
|
+
* `servesPin` (loader-cache.ts servesLoaderPin) answers whether this request
|
|
256
|
+
* serves the loader from a pin of a document-captured shell. Such a loader
|
|
257
|
+
* is not deferred: its body does not decide the value, and the pin is what
|
|
258
|
+
* the document shows. On every other request it would run, so it is
|
|
259
|
+
* deferred as on a route without ppr. Asked when loaders resolve, after a
|
|
260
|
+
* replay HIT has armed the pins (rsc-rendering.ts matchPartialWithPprReplay).
|
|
245
261
|
*/
|
|
246
|
-
export declare function defersLoader(ctx: HandlerContext<any, any>, loaderEntry: LoaderEntry, segmentId: string): boolean;
|
|
262
|
+
export declare function defersLoader(ctx: HandlerContext<any, any>, loaderEntry: LoaderEntry, segmentId: string, servesPin: (loaderEntry: LoaderEntry) => boolean): boolean;
|
|
247
263
|
/**
|
|
248
264
|
* This prefetch skips the handler of the entry whose segment is `segmentId`:
|
|
249
265
|
* a unit the client does not hold, or anything the client does not hold
|
|
@@ -53,6 +53,25 @@ export interface LoaderOwner {
|
|
|
53
53
|
}
|
|
54
54
|
/** A route entry as a LoaderOwner, under `shortCodeOverride` when inherited. */
|
|
55
55
|
export declare function ownerOf(entry: EntryData, shortCodeOverride?: string): LoaderOwner;
|
|
56
|
+
/**
|
|
57
|
+
* A route's loader copies inherited into a child layout with parallel slots
|
|
58
|
+
* are redundant beside the route's own loader segments: true when the route
|
|
59
|
+
* renders no loading() fallback on any request, so nothing hides the route's
|
|
60
|
+
* copy from useLoader() in the slots. A redundant copy is never resolved, on
|
|
61
|
+
* any request: the walkers check this before they inherit.
|
|
62
|
+
*
|
|
63
|
+
* Decided from the entry, never from the route segment's `loading`, which
|
|
64
|
+
* differs between requests: `loading(fallback, { ssr: false })` is `null` on
|
|
65
|
+
* a document (applyDocumentModeLoading) and the fallback on partials, and the
|
|
66
|
+
* walkers emit `loading(false)` as `null` too. A copy sent on one request and
|
|
67
|
+
* not on the next gives the layout a loader entry it did not have, so
|
|
68
|
+
* renderSegments wraps it in StreamedLoaderErrorBoundary and React remounts
|
|
69
|
+
* it with its Outlet (docs/tree-structure.md). Resolving a redundant copy and
|
|
70
|
+
* dropping it from the payload later is not enough: when the route's own
|
|
71
|
+
* loader is held (its revalidate() declines), the copy is new to the client,
|
|
72
|
+
* so it re-runs and is sent without the route's copy beside it.
|
|
73
|
+
*/
|
|
74
|
+
export declare function inheritedCopyRedundant(route: EntryData): boolean;
|
|
56
75
|
/**
|
|
57
76
|
* The walker's one loader funnel: each loader is a segment, run when the
|
|
58
77
|
* client lacks it, asked its revalidate() when held, kept outright in a fill
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recording what revalidate() rules read of the source page, so a prefetch
|
|
3
|
+
* answer a rule kept is shared between the pages with equal values of what
|
|
4
|
+
* was read (prefetch-source-scope.ts).
|
|
5
|
+
*/
|
|
6
|
+
import { type SourcePage, type SourceReads } from "../prefetch-source-scope.js";
|
|
7
|
+
/**
|
|
8
|
+
* The source group of a match whose diff a source read decided: the reads
|
|
9
|
+
* every kept decision made, unioned, and the source page they read.
|
|
10
|
+
*/
|
|
11
|
+
export interface SourceHeld extends SourcePage {
|
|
12
|
+
reads: SourceReads;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A copy of `params` whose reads land in `reads`: an enumerable getter per
|
|
16
|
+
* key, so a spread, Object.entries, JSON.stringify or structuredClone reads
|
|
17
|
+
* every key. Not a Proxy: structuredClone refuses one. A read of an absent
|
|
18
|
+
* key is not recorded and needs no record: the key set is part of the group
|
|
19
|
+
* (`reads.keys`), so a page in the group lacks that key too.
|
|
20
|
+
*/
|
|
21
|
+
export declare function recordingParams(params: Readonly<Record<string, string>>, reads: SourceReads): Record<string, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Add `reads` to the source group of the match `context` decides for. All
|
|
24
|
+
* of one match's decisions read the same source page; a caller that reads
|
|
25
|
+
* no route name passes none.
|
|
26
|
+
*/
|
|
27
|
+
export declare function markSourceHeld(context: {
|
|
28
|
+
_sourceHeld?: SourceHeld;
|
|
29
|
+
}, reads: SourceReads, page: SourcePage): void;
|
|
30
|
+
/**
|
|
31
|
+
* The `x-rsc-prefetch-scope` of a partial response, or undefined when every
|
|
32
|
+
* source page may share it.
|
|
33
|
+
*
|
|
34
|
+
* - `source`: the exact source page's. A route an intercept targets renders
|
|
35
|
+
* the modal or the full page depending on the source, so a full page
|
|
36
|
+
* prefetched where the intercept does not apply would otherwise serve a
|
|
37
|
+
* later click where it does (#1007); a response with deferred units
|
|
38
|
+
* answers one page's prefetch (`sourceOnly`); a kept rule that read
|
|
39
|
+
* `currentUrl` can depend on anything in it; and a source-held answer that
|
|
40
|
+
* sends nothing (`sentNothing`) commits treeless on the page that adopts
|
|
41
|
+
* it, which keeps its whole tree without checking it holds the ids the
|
|
42
|
+
* answer kept (partial-update.ts): only the source is known to hold them.
|
|
43
|
+
* - `params; <label>`: a revalidate() rule read the source's params or route
|
|
44
|
+
* name and kept a segment. A page that adopted the answer would keep its
|
|
45
|
+
* own copy of that segment (#1331), which is right only where the rule
|
|
46
|
+
* decides the same: on pages with equal values of what it read. The label
|
|
47
|
+
* names them (prefetch-source-scope.ts); the browser stores the answer
|
|
48
|
+
* under it. A page that lacks a kept id refetches (the commit's
|
|
49
|
+
* missing-segment check), as for a shared answer.
|
|
50
|
+
*/
|
|
51
|
+
export declare function prefetchScopeOf(sourceOnly: boolean, held: SourceHeld | undefined, sentNothing: boolean): string | undefined;
|
|
52
|
+
/** Every param of the source read: its params must equal the page's. */
|
|
53
|
+
export declare function readsOfAllParams(params: Readonly<Record<string, string>>): SourceReads;
|
|
@@ -60,7 +60,7 @@ export interface SegmentResolutionDeps<TEnv = any> {
|
|
|
60
60
|
export interface MatchApiDeps<TEnv = any> {
|
|
61
61
|
findMatch: (pathname: string, ms?: any) => any;
|
|
62
62
|
getMetricsStore: () => any;
|
|
63
|
-
findInterceptForRoute: (
|
|
63
|
+
findInterceptForRoute: (routeKeys: string | readonly string[], parentEntry: EntryData | null, selectorContext: InterceptSelectorContext | null, isAction: boolean, held?: ReadonlySet<string>) => {
|
|
64
64
|
intercept: InterceptEntry;
|
|
65
65
|
entry: EntryData;
|
|
66
66
|
} | null;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Utility functions for RSC request handling.
|
|
5
5
|
*/
|
|
6
6
|
import type { RequestContext } from "../server/request-context.js";
|
|
7
|
+
import { type LocationStateEntry } from "../browser/react/location-state-shared.js";
|
|
7
8
|
import type { MiddlewareEntry, MiddlewareFn } from "../router/middleware.js";
|
|
8
9
|
import type { RscPayload } from "./types.js";
|
|
9
10
|
import type { HandlerContext } from "./handler-context.js";
|
|
@@ -95,10 +96,14 @@ export declare function interceptRedirectForPartial(response: Response, createRe
|
|
|
95
96
|
/**
|
|
96
97
|
* Attach location state set during a request to a payload's metadata.
|
|
97
98
|
* No-op if no location state was set. Callers must ensure payload.metadata
|
|
98
|
-
* is populated (
|
|
99
|
-
* that
|
|
99
|
+
* is populated. A `document` payload (a page load's or a no-JS form post's
|
|
100
|
+
* bootstrap payload) that carries state marks the request
|
|
101
|
+
* `_documentLocationState`: it is the visitor's, so no shared cache keeps it
|
|
102
|
+
* (server/document-location-state.ts). `locationState` defaults to the
|
|
103
|
+
* current request context's; a shell HIT's tail passes the state set before
|
|
104
|
+
* its render (rsc/rsc-rendering.ts serveShellHit).
|
|
100
105
|
*/
|
|
101
|
-
export declare function attachLocationStateIfPresent(payload: RscPayload): void;
|
|
106
|
+
export declare function attachLocationStateIfPresent(payload: RscPayload, document?: boolean, locationState?: LocationStateEntry[] | undefined): void;
|
|
102
107
|
/**
|
|
103
108
|
* Only cache successful responses. Non-200 statuses (errors, redirects) are
|
|
104
109
|
* not cached -- notFound() produces 500 in response routes, and explicit
|
|
@@ -11,8 +11,13 @@
|
|
|
11
11
|
* So the body ends cleanly with one more row, PREFETCH_FAILED_ROW, which the
|
|
12
12
|
* Flight decoder skips and teeWithCompletion (browser/response-adapter.ts)
|
|
13
13
|
* reads as a stream that did not end cleanly: the client evicts the prefetch
|
|
14
|
-
* and never respawns it.
|
|
15
|
-
*
|
|
14
|
+
* and never respawns it. The router puts no Cache-Control of its own on a
|
|
15
|
+
* prefetch with a live part, the only kind whose render can report an error
|
|
16
|
+
* here, so the browser HTTP cache keeps none of it unless the route sets one;
|
|
17
|
+
* a prefetch with nothing live in it carries `private, max-age`
|
|
18
|
+
* (request-stages.ts applyStoredPrefetchCacheControl); a prefetch
|
|
19
|
+
* scoped to its source page or carrying deferred units is sent
|
|
20
|
+
* `private, no-cache` (rsc-rendering.ts NOT_REUSED).
|
|
16
21
|
*
|
|
17
22
|
* The errors are the render's `_renderErrors`: a Flight error row, a streamed
|
|
18
23
|
* handler recovered into its boundary, a loader that threw (redirect() and
|
|
@@ -36,6 +36,10 @@ export interface StageRouter<TEnv = unknown> {
|
|
|
36
36
|
readonly telemetry?: TelemetrySink;
|
|
37
37
|
readonly timeouts?: ResolvedTimeouts;
|
|
38
38
|
readonly onTimeout?: OnTimeoutCallback<TEnv>;
|
|
39
|
+
/** Names the cookie location state crosses a document redirect in. */
|
|
40
|
+
readonly resolvedStateCookieName: string;
|
|
41
|
+
/** The in-memory prefetch TTL in ms; also a stored prefetch's max-age. */
|
|
42
|
+
readonly prefetchCacheTTL: number;
|
|
39
43
|
}
|
|
40
44
|
/** Report an error through the router's onError. */
|
|
41
45
|
export type ReportError<TEnv = unknown> = (error: unknown, phase: ErrorPhase, context: InvokeOnErrorContext<TEnv>) => void;
|
|
@@ -99,8 +99,13 @@ export declare function withoutShellMissMarker(request: Request): Request | unde
|
|
|
99
99
|
* the page. window.stop() runs only when it reloads: it keeps the half-sent
|
|
100
100
|
* Flight stream from being closed by DOMContentLoaded, which would throw
|
|
101
101
|
* React's "Connection closed" (#412) before the reload lands.
|
|
102
|
+
*
|
|
103
|
+
* `restoreCookie` is the request's `_carriedLocationStateCookie`: the HIT's
|
|
104
|
+
* headers already cleared the location state cookie a document redirect left
|
|
105
|
+
* (server/document-location-state.ts), so the script sets it again before it
|
|
106
|
+
* reloads, and the reload carries the state.
|
|
102
107
|
*/
|
|
103
|
-
export declare function shellReloadScript(): string;
|
|
108
|
+
export declare function shellReloadScript(restoreCookie?: string): string;
|
|
104
109
|
/**
|
|
105
110
|
* An inline script a shell HIT's tail appends. It carries no CSP nonce: a
|
|
106
111
|
* request with an active per-request nonce never reaches a HIT
|
|
@@ -92,9 +92,10 @@ export type EntryPropRender = {
|
|
|
92
92
|
loading?: ReactNode | false;
|
|
93
93
|
/**
|
|
94
94
|
* loading(fallback, { prefetch: false }) with a renderable fallback: a
|
|
95
|
-
* prefetch defers what the fallback covers while the entry's
|
|
96
|
-
* new to the client
|
|
97
|
-
* on both DSL
|
|
95
|
+
* speculative prefetch defers what the fallback covers while the entry's
|
|
96
|
+
* segment is new to the client
|
|
97
|
+
* (router/segment-resolution/prefetch-deferral.ts). Set on both DSL
|
|
98
|
+
* evaluations, whatever `ssr` did to `loading`.
|
|
98
99
|
*/
|
|
99
100
|
loadingPrefetch?: false;
|
|
100
101
|
/**
|
|
@@ -136,8 +137,8 @@ export type LoaderEntry = {
|
|
|
136
137
|
*/
|
|
137
138
|
bake?: true;
|
|
138
139
|
/**
|
|
139
|
-
* loader(Def, { prefetch: false }): a prefetch defers this
|
|
140
|
-
* while its segment is new to the client
|
|
140
|
+
* loader(Def, { prefetch: false }): a speculative prefetch defers this
|
|
141
|
+
* registration while its segment is new to the client
|
|
141
142
|
* (router/segment-resolution/prefetch-deferral.ts).
|
|
142
143
|
*/
|
|
143
144
|
prefetch?: false;
|
|
@@ -174,7 +175,10 @@ export type InterceptSegmentsState = {
|
|
|
174
175
|
* @internal This type is an implementation detail and may change without notice.
|
|
175
176
|
*/
|
|
176
177
|
export type InterceptSelectorContext<TEnv = any> = {
|
|
177
|
-
/**
|
|
178
|
+
/**
|
|
179
|
+
* Where the navigation comes from: the intercept source while one is open.
|
|
180
|
+
* Its `url` never carries a #fragment.
|
|
181
|
+
*/
|
|
178
182
|
from: ServerRouteLocation;
|
|
179
183
|
/** The navigation target. */
|
|
180
184
|
to: ServerRouteLocation;
|
|
@@ -818,6 +822,19 @@ export declare function findEnclosingLoaderBody(match: (loaderId: string) => boo
|
|
|
818
822
|
* reader runs in that request only reaches the page through the replay.
|
|
819
823
|
*/
|
|
820
824
|
export declare function isInsideLoaderBody(loaderId: string): boolean;
|
|
825
|
+
/**
|
|
826
|
+
* Run `fn` as segment `segmentId`'s code: a handle push, a loader kickoff or
|
|
827
|
+
* a "use cache" call it makes, before or after an await, files under
|
|
828
|
+
* `segmentId` (segmentPinOf).
|
|
829
|
+
*/
|
|
830
|
+
export declare function runAsSegment<R>(segmentId: string | undefined, fn: () => R): R;
|
|
831
|
+
/**
|
|
832
|
+
* The segment code here runs for: the innermost runAsSegment scope, else
|
|
833
|
+
* `ctx`'s pin (a handler the walker awaits).
|
|
834
|
+
*/
|
|
835
|
+
export declare function segmentPinOf(ctx: {
|
|
836
|
+
_currentSegmentId?: string;
|
|
837
|
+
}): string | undefined;
|
|
821
838
|
/**
|
|
822
839
|
* Check if the current execution is inside a handle push callback (sync or an
|
|
823
840
|
* async callback's continuation). Used by the handler-to-loader deadlock guard
|
|
@@ -134,7 +134,21 @@ export declare function invalidateClientCache(): void;
|
|
|
134
134
|
*
|
|
135
135
|
* Sets an internal response header the bridge reads. Idempotent within a
|
|
136
136
|
* request. Inert (a dev warning) outside a request context — there is no
|
|
137
|
-
* automatic invalidation to suppress.
|
|
137
|
+
* automatic invalidation to suppress. It also keeps the state's write part
|
|
138
|
+
* (runActionBody).
|
|
138
139
|
*/
|
|
139
140
|
export declare function keepClientCache(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Run a server action's body (the JS call or a no-JS form post), then bump the
|
|
143
|
+
* rango state's write part for the client that called it: the response's
|
|
144
|
+
* state `Set-Cookie` keeps the client's timestamp and carries a new write part
|
|
145
|
+
* (browser/cookie-name.ts). Every later request of every tab and reload sends
|
|
146
|
+
* the new `X-Rango-State`, so a prefetch or navigation the browser HTTP cache
|
|
147
|
+
* holds from before the write (a response's own `Cache-Control: max-age`)
|
|
148
|
+
* misses, while the client's in-memory caches only go stale, as the action
|
|
149
|
+
* bridge marks them. Bumped however the body ends (returned, threw, or
|
|
150
|
+
* redirected), since the write may have committed either way, and not after
|
|
151
|
+
* keepClientCache() or invalidateClientCache() (whose rotation covers it).
|
|
152
|
+
*/
|
|
153
|
+
export declare function runActionBody<T>(body: () => T | Promise<T>): Promise<T>;
|
|
140
154
|
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Location state on document responses (#1330).
|
|
3
|
+
*
|
|
4
|
+
* A client navigation or an action carries server-set location state in its
|
|
5
|
+
* Flight payload, and a redirect on either becomes a Flight redirect that
|
|
6
|
+
* carries it too. A document request has no such channel for a 3xx: the
|
|
7
|
+
* browser follows it with a plain GET. This module carries the state across
|
|
8
|
+
* that one hop in a short-lived cookie:
|
|
9
|
+
*
|
|
10
|
+
* - `carryLocationStateAcrossRedirect` (rsc/request-stages.ts
|
|
11
|
+
* finalizeRequestResponse) writes it on a document request's same-origin
|
|
12
|
+
* 3xx when the request set location state;
|
|
13
|
+
* - `consumeDocumentLocationState` (rsc/request-stages.ts runRequestPasses)
|
|
14
|
+
* reads it on the next GET document request that navigates to the target
|
|
15
|
+
* pathname (`Sec-Fetch-Dest` a browsing context, where sent), seeds
|
|
16
|
+
* `_locationState` with its entries (so the render attaches them to the
|
|
17
|
+
* bootstrap payload, rsc/rsc-rendering.ts) and clears it. A shell HIT that
|
|
18
|
+
* degrades into a reload after its headers cleared the cookie sets it
|
|
19
|
+
* again from script first (`_carriedLocationStateCookie`), so the reload
|
|
20
|
+
* carries the state.
|
|
21
|
+
*
|
|
22
|
+
* A document that carries location state is per visitor: it is marked
|
|
23
|
+
* `_documentLocationState`, never stored by the document cache or as a PPR
|
|
24
|
+
* shell, and leaves with `Cache-Control: private, no-store`
|
|
25
|
+
* (`markDocumentResponsePrivate`).
|
|
26
|
+
*
|
|
27
|
+
* The value is JSON, not Flight: a cookie holds text, and the client merges
|
|
28
|
+
* it as `history.state` would hold it. `Path=/` because the `__Host-` prefix
|
|
29
|
+
* (https) requires it, which keeps a sibling subdomain from planting state;
|
|
30
|
+
* the target pathname inside the value decides who consumes it.
|
|
31
|
+
*/
|
|
32
|
+
import { type RequestContext } from "./request-context.js";
|
|
33
|
+
/** The cookie's name for a router: `__Host-` on https. */
|
|
34
|
+
export declare function documentLocationStateCookieName(stateCookieName: string, secure: boolean): string;
|
|
35
|
+
/**
|
|
36
|
+
* Read the cookie a document redirect left for this request: seed
|
|
37
|
+
* `_locationState` with its slots and clear it. Only a GET document request
|
|
38
|
+
* of the target pathname that navigates consumes it (the request the browser
|
|
39
|
+
* makes for a 301/302/303, see isNavigationRequest); any other request, a
|
|
40
|
+
* form POST to that path or a prefetch of it included, leaves it to its
|
|
41
|
+
* expiry. A malformed value is cleared and ignored, and only `__rsc_ls_*`
|
|
42
|
+
* slots are taken from it (the value comes from the browser).
|
|
43
|
+
*/
|
|
44
|
+
export declare function consumeDocumentLocationState(reqCtx: Pick<RequestContext, "_locationState" | "_carriedLocationStateCookie" | "setCookie">, request: Request, url: URL, stateCookieName: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Write the cookie on a document request's redirect that set location state,
|
|
47
|
+
* and mark the redirect private. Not for a partial or action request (their
|
|
48
|
+
* redirect is a Flight payload), an external or cross-origin target (the
|
|
49
|
+
* cookie would never reach it) or a response that is not a 3xx with a
|
|
50
|
+
* Location. Returns the response to send: a new one when its headers are
|
|
51
|
+
* immutable.
|
|
52
|
+
*/
|
|
53
|
+
export declare function carryLocationStateAcrossRedirect(response: Response, reqCtx: Pick<RequestContext, "_locationState">, request: Request, url: URL, stateCookieName: string): Response;
|
|
54
|
+
/**
|
|
55
|
+
* `Cache-Control: private, no-store` on a document that carries location
|
|
56
|
+
* state, after every middleware: a shared cache must never store or replay
|
|
57
|
+
* one visitor's state. Returns the response to send.
|
|
58
|
+
*/
|
|
59
|
+
export declare function markDocumentResponsePrivate(response: Response, reqCtx: Pick<RequestContext, "_documentLocationState">): Response;
|
|
@@ -158,6 +158,8 @@ export interface HandleStore {
|
|
|
158
158
|
* so a loader that throws or skips its push shows none rather than the
|
|
159
159
|
* record's. A hole's replays go with them. Any other loader's replays stay
|
|
160
160
|
* (a dependency another entry's HIT replayed), and so do restored copies.
|
|
161
|
+
* A prefetch that defers the loader calls it too (revalidation.ts
|
|
162
|
+
* resolveOwnerLoaders): no run is made, so none of its placeholders stand.
|
|
161
163
|
*/
|
|
162
164
|
settleLoaderRun(loaderId: string): void;
|
|
163
165
|
/**
|