@rangojs/router 0.21.0 → 0.22.1
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 +13 -1
- package/dist/types/browser/event-controller.d.ts +30 -13
- package/dist/types/browser/navigation-store.d.ts +9 -0
- package/dist/types/browser/partial-update.d.ts +2 -1
- package/dist/types/browser/prefetch/default-strategy.d.ts +16 -20
- package/dist/types/browser/react/NavigationProvider.d.ts +14 -1
- package/dist/types/browser/react/context.d.ts +14 -0
- package/dist/types/browser/rsc-router.d.ts +13 -2
- package/dist/types/browser/types.d.ts +10 -0
- package/dist/types/build/generate-manifest.d.ts +2 -0
- package/dist/types/cache/background-task.d.ts +22 -0
- package/dist/types/cache/cache-key-utils.d.ts +50 -5
- package/dist/types/cache/cache-policy.d.ts +17 -0
- package/dist/types/cache/cache-scope.d.ts +1 -1
- package/dist/types/cache/cf/cf-cache-store.d.ts +7 -1
- package/dist/types/cache/document-cache.d.ts +8 -5
- package/dist/types/cache/handle-snapshot.d.ts +23 -0
- package/dist/types/cache/index.d.ts +1 -1
- package/dist/types/cache/invalidation-order.d.ts +14 -0
- package/dist/types/cache/memory-segment-store.d.ts +33 -1
- package/dist/types/cache/shell-snapshot.d.ts +10 -1
- package/dist/types/cache/store-scope.d.ts +22 -0
- package/dist/types/cache/tag-invalidation.d.ts +7 -6
- package/dist/types/cache/types.d.ts +63 -14
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +7 -1
- package/dist/types/errors.d.ts +6 -0
- package/dist/types/handles/deferred-resolution.d.ts +7 -0
- package/dist/types/internal-suspense-audit.d.ts +1 -0
- package/dist/types/loader-store.d.ts +4 -8
- package/dist/types/outlet-provider.d.ts +2 -1
- package/dist/types/prerender/cloudflare.d.ts +49 -0
- package/dist/types/prerender/create-prerender-trigger.d.ts +121 -0
- package/dist/types/prerender/index.d.ts +12 -0
- package/dist/types/prerender/memory-prerender-store.d.ts +29 -0
- package/dist/types/prerender/on-demand.d.ts +272 -0
- package/dist/types/prerender/producer-guard.d.ts +33 -0
- package/dist/types/prerender/shell-manifest-key.d.ts +1 -18
- package/dist/types/prerender/warm-request.d.ts +65 -0
- package/dist/types/prerender/warm.d.ts +65 -0
- package/dist/types/prerender/writable-store.d.ts +170 -0
- package/dist/types/prerender.d.ts +27 -0
- package/dist/types/reverse.d.ts +1 -1
- package/dist/types/route-content-wrapper.d.ts +3 -1
- package/dist/types/router/error-handling.d.ts +2 -0
- package/dist/types/router/handler-context.d.ts +1 -1
- package/dist/types/router/match-middleware/cache-lookup.d.ts +14 -0
- package/dist/types/router/pattern-matching.d.ts +2 -0
- package/dist/types/router/prefetch-default.d.ts +4 -4
- package/dist/types/router/prerender-match.d.ts +23 -1
- package/dist/types/router/route-trie-builder.d.ts +8 -1
- package/dist/types/router/router-context.d.ts +1 -0
- package/dist/types/router/router-interfaces.d.ts +30 -0
- package/dist/types/router/router-options.d.ts +24 -0
- package/dist/types/router/segment-resolution/fresh.d.ts +7 -0
- package/dist/types/router/segment-resolution/loader-cache.d.ts +2 -1
- package/dist/types/router/segment-resolution/revalidation.d.ts +5 -1
- package/dist/types/router/segment-resolution/streamed-handler-boundary.d.ts +43 -0
- package/dist/types/router/trie-matching.d.ts +2 -0
- package/dist/types/rsc/shell-build-manifest.d.ts +6 -4
- package/dist/types/rsc/shell-capture-constants.d.ts +20 -5
- package/dist/types/rsc/shell-capture.d.ts +14 -1
- package/dist/types/rsc/shell-serve.d.ts +2 -2
- package/dist/types/rsc/ssr-module-loader.d.ts +15 -0
- package/dist/types/rsc/types.d.ts +8 -0
- package/dist/types/segment-boundary-content.d.ts +17 -0
- package/dist/types/segment-loader-promise.d.ts +2 -6
- package/dist/types/server/build-version-table.d.ts +9 -0
- package/dist/types/server/context.d.ts +12 -4
- package/dist/types/server/handle-store.d.ts +2 -0
- package/dist/types/server/request-context.d.ts +63 -2
- package/dist/types/suspense-audit-react.d.ts +26 -0
- package/dist/types/suspense-audit.d.ts +157 -0
- package/dist/types/testing/action-form.d.ts +34 -0
- package/dist/types/testing/flight.entry.d.ts +2 -0
- package/dist/types/testing/index.d.ts +4 -0
- package/dist/types/testing/internal/server-modules.d.ts +8 -0
- package/dist/types/testing/serve-shell-request.d.ts +34 -4
- package/dist/types/testing/shell-status.d.ts +14 -6
- package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +9 -6
- package/dist/types/thenable-status.d.ts +6 -0
- package/dist/types/types/handler-context.d.ts +7 -0
- package/dist/types/types/route-entry.d.ts +5 -0
- package/dist/types/urls/path-helper.d.ts +18 -0
- package/dist/types/vite/discovery/state.d.ts +11 -0
- package/dist/types/vite/inject-client-debug.d.ts +6 -25
- package/dist/types/vite/utils/bundle-analysis.d.ts +6 -2
- package/dist/vite/index.js +180 -497
- package/package.json +13 -3
- package/skills/cache-guide/SKILL.md +18 -17
- package/skills/caching/SKILL.md +40 -4
- package/skills/catalog.json +1 -1
- package/skills/cloudflare/SKILL.md +131 -0
- package/skills/comparison/references/framework-comparison.md +1 -1
- package/skills/deployment-caching/SKILL.md +33 -12
- package/skills/document-cache/SKILL.md +16 -14
- package/skills/hooks/SKILL.md +22 -0
- package/skills/hooks/handle-and-actions.md +3 -4
- package/skills/hooks/navigation.md +10 -0
- package/skills/hooks/state.md +5 -4
- package/skills/host-router/SKILL.md +18 -0
- package/skills/loader/SKILL.md +6 -4
- package/skills/middleware/SKILL.md +1 -1
- package/skills/migrate-nextjs/SKILL.md +82 -9
- package/skills/ppr/SKILL.md +31 -8
- package/skills/prerender/SKILL.md +645 -8
- package/skills/rango/SKILL.md +1 -0
- package/skills/response-routes/SKILL.md +5 -5
- package/skills/route/SKILL.md +29 -0
- package/skills/testing/SKILL.md +2 -1
- package/skills/testing/cache-prerender.md +18 -17
- package/skills/testing/serve-shell-request.md +104 -8
- package/skills/use-cache/SKILL.md +9 -5
- package/skills/vercel/SKILL.md +2 -0
- package/skills/view-transitions/SKILL.md +9 -4
- package/src/browser/event-controller.ts +69 -25
- package/src/browser/link-interceptor.ts +2 -2
- package/src/browser/navigation-bridge.ts +75 -35
- package/src/browser/navigation-store.ts +26 -0
- package/src/browser/navigation-transaction.ts +9 -2
- package/src/browser/network-error-handler.ts +2 -0
- package/src/browser/partial-update.ts +48 -12
- package/src/browser/prefetch/default-strategy.ts +22 -42
- package/src/browser/react/Link.tsx +37 -42
- package/src/browser/react/NavigationProvider.tsx +63 -3
- package/src/browser/react/context.ts +17 -0
- package/src/browser/react/location-state.ts +5 -19
- package/src/browser/react/use-action.ts +4 -1
- package/src/browser/react/use-handle.ts +4 -20
- package/src/browser/react/use-link-status.ts +4 -3
- package/src/browser/react/use-navigation.ts +4 -1
- package/src/browser/react/use-params.ts +4 -1
- package/src/browser/react/use-pathname.ts +4 -1
- package/src/browser/react/use-search-params.ts +5 -3
- package/src/browser/react/use-segments.ts +36 -54
- package/src/browser/rsc-router.tsx +79 -39
- package/src/browser/segment-reconciler.ts +3 -3
- package/src/browser/server-action-bridge.ts +26 -6
- package/src/browser/types.ts +11 -0
- package/src/build/generate-manifest.ts +17 -0
- package/src/build/merge-full-manifests.ts +5 -0
- package/src/build/route-trie.ts +1 -0
- package/src/cache/background-task.ts +61 -0
- package/src/cache/cache-key-utils.ts +91 -12
- package/src/cache/cache-policy.ts +11 -2
- package/src/cache/cache-runtime.ts +23 -23
- package/src/cache/cache-scope.ts +38 -36
- package/src/cache/cf/cf-cache-store.ts +16 -11
- package/src/cache/document-cache.ts +35 -14
- package/src/cache/handle-snapshot.ts +50 -0
- package/src/cache/index.ts +1 -0
- package/src/cache/invalidation-order.ts +53 -0
- package/src/cache/memory-segment-store.ts +52 -1
- package/src/cache/shell-snapshot.ts +17 -0
- package/src/cache/store-scope.ts +36 -0
- package/src/cache/tag-invalidation.ts +7 -5
- package/src/cache/types.ts +69 -14
- package/src/cache/vercel/vercel-cache-store.ts +20 -6
- package/src/client.tsx +40 -3
- package/src/errors.ts +13 -6
- package/src/handles/deferred-resolution.ts +7 -2
- package/src/internal-suspense-audit.ts +12 -0
- package/src/loader-store.ts +4 -9
- package/src/outlet-provider.tsx +25 -1
- package/src/prerender/cloudflare.ts +130 -0
- package/src/prerender/create-prerender-trigger.ts +780 -0
- package/src/prerender/index.ts +39 -0
- package/src/prerender/memory-prerender-store.ts +115 -0
- package/src/prerender/on-demand.ts +339 -0
- package/src/prerender/producer-guard.ts +66 -0
- package/src/prerender/shell-manifest-key.ts +12 -17
- package/src/prerender/warm-request.ts +154 -0
- package/src/prerender/warm.ts +193 -0
- package/src/prerender/writable-store.ts +278 -0
- package/src/prerender.ts +29 -0
- package/src/reverse.ts +1 -1
- package/src/route-content-wrapper.tsx +107 -13
- package/src/router/error-handling.ts +12 -12
- package/src/router/find-match.ts +1 -0
- package/src/router/handler-context.ts +2 -0
- package/src/router/intercept-resolution.ts +15 -8
- package/src/router/loader-resolution.ts +2 -10
- package/src/router/match-middleware/background-revalidation.ts +2 -0
- package/src/router/match-middleware/cache-lookup.ts +230 -38
- package/src/router/pattern-matching.ts +14 -0
- package/src/router/prefetch-default.ts +4 -4
- package/src/router/prerender-match.ts +460 -352
- package/src/router/route-trie-builder.ts +9 -0
- package/src/router/router-context.ts +1 -0
- package/src/router/router-interfaces.ts +33 -0
- package/src/router/router-options.ts +30 -0
- package/src/router/segment-resolution/fresh.ts +20 -19
- package/src/router/segment-resolution/loader-cache.ts +15 -17
- package/src/router/segment-resolution/revalidation.ts +34 -24
- package/src/router/segment-resolution/streamed-handler-boundary.ts +133 -0
- package/src/router/trie-matching.ts +3 -0
- package/src/router.ts +107 -1
- package/src/rsc/handler.ts +51 -4
- package/src/rsc/progressive-enhancement.ts +5 -1
- package/src/rsc/response-cache-serve.ts +10 -4
- package/src/rsc/rsc-rendering.ts +53 -11
- package/src/rsc/shell-build-manifest.ts +10 -8
- package/src/rsc/shell-capture-constants.ts +39 -7
- package/src/rsc/shell-capture.ts +108 -19
- package/src/rsc/shell-serve.ts +12 -6
- package/src/rsc/ssr-module-loader.ts +26 -0
- package/src/rsc/types.ts +8 -0
- package/src/segment-boundary-content.ts +25 -0
- package/src/segment-loader-promise.ts +28 -38
- package/src/segment-system.tsx +117 -57
- package/src/server/build-version-table.ts +15 -0
- package/src/server/context.ts +40 -17
- package/src/server/cookie-store.ts +5 -0
- package/src/server/handle-store.ts +13 -0
- package/src/server/loader-registry.ts +6 -1
- package/src/server/request-context.ts +87 -1
- package/src/ssr/ssr-root.tsx +20 -13
- package/src/suspense-audit-react.tsx +98 -0
- package/src/suspense-audit.ts +1030 -0
- package/src/testing/action-form.ts +66 -0
- package/src/testing/flight-runtime.d.ts +27 -0
- package/src/testing/flight.entry.ts +3 -0
- package/src/testing/index.ts +19 -0
- package/src/testing/internal/server-modules.ts +32 -0
- package/src/testing/render-route.tsx +25 -12
- package/src/testing/serve-shell-request.ts +190 -34
- package/src/testing/shell-status.ts +17 -6
- package/src/testing/vitest-stubs/plugin-rsc.ts +37 -11
- package/src/thenable-status.ts +10 -0
- package/src/types/handler-context.ts +7 -0
- package/src/types/route-entry.ts +6 -0
- package/src/urls/path-helper.ts +69 -9
- package/src/use-loader.tsx +57 -30
- package/src/vite/discovery/bundle-postprocess.ts +4 -0
- package/src/vite/discovery/discover-routers.ts +15 -0
- package/src/vite/discovery/shell-prerender-phase.ts +5 -5
- package/src/vite/discovery/state.ts +17 -1
- package/src/vite/inject-client-debug.ts +42 -20
- package/src/vite/plugins/virtual-entries.ts +8 -1
- package/src/vite/router-discovery.ts +14 -0
- package/src/vite/utils/bundle-analysis.ts +39 -7
- package/dist/types/browser/react/subscribe-to-nothing.d.ts +0 -7
- package/dist/types/segment-content-promise.d.ts +0 -13
- package/src/browser/react/subscribe-to-nothing.ts +0 -7
- package/src/segment-content-promise.ts +0 -67
|
@@ -991,6 +991,14 @@ export function createRouterDiscoveryPlugin(
|
|
|
991
991
|
(globalThis as any).__rscRouterDiscoveryActive ?? false,
|
|
992
992
|
);
|
|
993
993
|
s.devServerOrigin = getDevServerOrigin();
|
|
994
|
+
// The temp Node realm below shares this globalThis and runs the dev
|
|
995
|
+
// /__rsc_shell capture, which must replay the prerender store as
|
|
996
|
+
// the worker's HIT does: a capture that renders the Prerender
|
|
997
|
+
// handler live stores a doc record the HIT never reads, and the
|
|
998
|
+
// HIT loses the loader pushes its prelude rendered (#1057). That
|
|
999
|
+
// realm never evaluates the virtual module that sets this on the
|
|
1000
|
+
// Node preset.
|
|
1001
|
+
globalThis.__PRERENDER_DEV_URL = s.devServerOrigin;
|
|
994
1002
|
|
|
995
1003
|
// Create a temp Node.js server to run runtime discovery and generate
|
|
996
1004
|
// named route types (static parser can't resolve factory calls).
|
|
@@ -2497,6 +2505,12 @@ export function createRouterDiscoveryPlugin(
|
|
|
2497
2505
|
s.resolvedPrerenderModules,
|
|
2498
2506
|
"Prerender",
|
|
2499
2507
|
false,
|
|
2508
|
+
// Mark onDemand exports (retained, not evicted) from the
|
|
2509
|
+
// discovery-derived $$id set — the same evaluated source that sets
|
|
2510
|
+
// the runtime od trie flag, so retention and serve can never
|
|
2511
|
+
// disagree. Populated by discoverRouters (buildStart), which runs
|
|
2512
|
+
// before this generateBundle pass.
|
|
2513
|
+
s.onDemandHandlerIds,
|
|
2500
2514
|
);
|
|
2501
2515
|
if (handlers.length > 0) {
|
|
2502
2516
|
const existing = s.handlerChunkInfoMap.get(fileName);
|
|
@@ -29,20 +29,40 @@ export function findMatchingParenInBundle(
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Scan a bundled chunk for handler exports and extract their names + $$id values.
|
|
32
|
-
* Optionally detects passthrough flag
|
|
32
|
+
* Optionally detects the passthrough flag by parsing the call body, and marks
|
|
33
|
+
* onDemand from the authoritative discovery-derived handlerId set.
|
|
34
|
+
* @internal Exported for testing only.
|
|
33
35
|
*/
|
|
34
36
|
export function extractHandlerExportsFromChunk(
|
|
35
37
|
chunkCode: string,
|
|
36
38
|
handlerModules: Map<string, string[]>,
|
|
37
39
|
fnName: string,
|
|
38
40
|
detectPassthrough: boolean,
|
|
39
|
-
)
|
|
41
|
+
// handlerIds ($$id) of routes the evaluated source marks onDemand — the
|
|
42
|
+
// single source of truth shared with the runtime od trie flag. Keyed on the
|
|
43
|
+
// same $$id the chunk scan extracts, so any spelling of the option (literal,
|
|
44
|
+
// spread, imported const) retains the producer; a textual scan of the call
|
|
45
|
+
// body cannot see non-literal spellings and silently evicted them.
|
|
46
|
+
onDemandHandlerIds?: ReadonlyMap<string, string>,
|
|
47
|
+
): Array<{
|
|
48
|
+
name: string;
|
|
49
|
+
handlerId: string;
|
|
50
|
+
passthrough: boolean;
|
|
51
|
+
onDemand: boolean;
|
|
52
|
+
}> {
|
|
40
53
|
const handlers: Array<{
|
|
41
54
|
name: string;
|
|
42
55
|
handlerId: string;
|
|
43
56
|
passthrough: boolean;
|
|
57
|
+
onDemand: boolean;
|
|
44
58
|
}> = [];
|
|
45
59
|
|
|
60
|
+
// Only parse a call body (an O(callBody) paren walk per export) when the whole
|
|
61
|
+
// chunk actually contains the marker we're detecting — the common case (no
|
|
62
|
+
// passthrough opt-in anywhere in the chunk) skips the walk entirely.
|
|
63
|
+
const scanPassthrough =
|
|
64
|
+
detectPassthrough && chunkCode.includes("passthrough");
|
|
65
|
+
|
|
46
66
|
for (const [, handlerNames] of handlerModules) {
|
|
47
67
|
for (const name of handlerNames) {
|
|
48
68
|
const eName = escapeRegExp(name);
|
|
@@ -53,7 +73,7 @@ export function extractHandlerExportsFromChunk(
|
|
|
53
73
|
if (!match) continue;
|
|
54
74
|
|
|
55
75
|
let isPassthrough = false;
|
|
56
|
-
if (
|
|
76
|
+
if (scanPassthrough) {
|
|
57
77
|
const eFnName = escapeRegExp(fnName);
|
|
58
78
|
const callStartRe = new RegExp(
|
|
59
79
|
`(?:const|let|var)\\s+${eName}\\s*=\\s*${eFnName}\\s*(?:<[^>]*>)?\\s*\\(`,
|
|
@@ -68,7 +88,12 @@ export function extractHandlerExportsFromChunk(
|
|
|
68
88
|
}
|
|
69
89
|
}
|
|
70
90
|
}
|
|
71
|
-
handlers.push({
|
|
91
|
+
handlers.push({
|
|
92
|
+
name,
|
|
93
|
+
handlerId: match[1],
|
|
94
|
+
passthrough: isPassthrough,
|
|
95
|
+
onDemand: onDemandHandlerIds?.has(match[1]) ?? false,
|
|
96
|
+
});
|
|
72
97
|
}
|
|
73
98
|
}
|
|
74
99
|
|
|
@@ -82,7 +107,12 @@ export function extractHandlerExportsFromChunk(
|
|
|
82
107
|
*/
|
|
83
108
|
export function evictHandlerCode(
|
|
84
109
|
code: string,
|
|
85
|
-
exports: Array<{
|
|
110
|
+
exports: Array<{
|
|
111
|
+
name: string;
|
|
112
|
+
handlerId: string;
|
|
113
|
+
passthrough?: boolean;
|
|
114
|
+
onDemand?: boolean;
|
|
115
|
+
}>,
|
|
86
116
|
fnName: string,
|
|
87
117
|
brand: string,
|
|
88
118
|
): { code: string; savedBytes: number } | null {
|
|
@@ -90,8 +120,10 @@ export function evictHandlerCode(
|
|
|
90
120
|
let modified = code;
|
|
91
121
|
|
|
92
122
|
const eFnName = escapeRegExp(fnName);
|
|
93
|
-
for (const { name, handlerId, passthrough } of exports) {
|
|
94
|
-
|
|
123
|
+
for (const { name, handlerId, passthrough, onDemand } of exports) {
|
|
124
|
+
// Keep the producer body for passthrough (live fallback) and onDemand
|
|
125
|
+
// (router.prerender() must be able to invoke the retained producer).
|
|
126
|
+
if (passthrough || onDemand) continue;
|
|
95
127
|
|
|
96
128
|
const eName = escapeRegExp(name);
|
|
97
129
|
// Match const/let/var: Rolldown (Vite 8) emits top-level bindings in the
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `subscribe` for a useSyncExternalStore whose snapshot nothing notifies: the
|
|
3
|
-
* hook is there for its server snapshot (useLocationState, useHandle), or the
|
|
4
|
-
* value only changes with a render (Link's non-adaptive prefetch strategy).
|
|
5
|
-
* One function, so its identity is stable across renders and hooks.
|
|
6
|
-
*/
|
|
7
|
-
export declare const subscribeToNothing: () => () => void;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
/**
|
|
3
|
-
* Return a stable Promise wrapping `component`, memoized on the component ref.
|
|
4
|
-
*
|
|
5
|
-
* A fresh `Promise.resolve(component)` each render would suspend for one
|
|
6
|
-
* microtask and briefly commit the loading fallback inside Suspender — the
|
|
7
|
-
* intercept / parallel-slot flicker this indirection prevents. Reusing the
|
|
8
|
-
* same Promise ref keeps React's `use()` in "known fulfilled" state after
|
|
9
|
-
* the first observation.
|
|
10
|
-
*
|
|
11
|
-
* @internal
|
|
12
|
-
*/
|
|
13
|
-
export declare function getMemoizedContentPromise(component: ReactNode): Promise<ReactNode>;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `subscribe` for a useSyncExternalStore whose snapshot nothing notifies: the
|
|
3
|
-
* hook is there for its server snapshot (useLocationState, useHandle), or the
|
|
4
|
-
* value only changes with a render (Link's non-adaptive prefetch strategy).
|
|
5
|
-
* One function, so its identity is stable across renders and hooks.
|
|
6
|
-
*/
|
|
7
|
-
export const subscribeToNothing: () => () => void = () => () => {};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Stable Promise wrappers keyed on the component itself. Objects (React
|
|
5
|
-
* elements, functions, lazy payloads) land in a WeakMap so entries GC when
|
|
6
|
-
* the underlying component is released; primitives (string, number, boolean,
|
|
7
|
-
* null) land in a Map so memoization still applies to text-/null-backed
|
|
8
|
-
* segments like those in partial-update flows. Keeping this cache outside
|
|
9
|
-
* the segment eliminates preservation fields on ResolvedSegment — it survives
|
|
10
|
-
* reconciliation naturally because the component ref is what's stable.
|
|
11
|
-
*
|
|
12
|
-
* Browser-only. On the server each SSR render needs a fresh pending promise
|
|
13
|
-
* so Suspense can emit the loading fallback HTML before content streams. A
|
|
14
|
-
* shared already-resolved promise has `.status === "fulfilled"` attached by
|
|
15
|
-
* React on its first observation — subsequent `use()` calls return
|
|
16
|
-
* synchronously without suspending, so the Suspense fallback never makes it
|
|
17
|
-
* into the initial HTML. Route-definition components share refs across
|
|
18
|
-
* requests, so a global cache would leak tracked state between renders.
|
|
19
|
-
*/
|
|
20
|
-
const IS_BROWSER = typeof window !== "undefined";
|
|
21
|
-
const objectContentCache = IS_BROWSER
|
|
22
|
-
? new WeakMap<object, Promise<ReactNode>>()
|
|
23
|
-
: null;
|
|
24
|
-
const primitiveContentCache = IS_BROWSER
|
|
25
|
-
? new Map<unknown, Promise<ReactNode>>()
|
|
26
|
-
: null;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Return a stable Promise wrapping `component`, memoized on the component ref.
|
|
30
|
-
*
|
|
31
|
-
* A fresh `Promise.resolve(component)` each render would suspend for one
|
|
32
|
-
* microtask and briefly commit the loading fallback inside Suspender — the
|
|
33
|
-
* intercept / parallel-slot flicker this indirection prevents. Reusing the
|
|
34
|
-
* same Promise ref keeps React's `use()` in "known fulfilled" state after
|
|
35
|
-
* the first observation.
|
|
36
|
-
*
|
|
37
|
-
* @internal
|
|
38
|
-
*/
|
|
39
|
-
export function getMemoizedContentPromise(
|
|
40
|
-
component: ReactNode,
|
|
41
|
-
): Promise<ReactNode> {
|
|
42
|
-
if (component instanceof Promise) {
|
|
43
|
-
return component as Promise<ReactNode>;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!objectContentCache || !primitiveContentCache) {
|
|
47
|
-
return Promise.resolve(component);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (component !== null && typeof component === "object") {
|
|
51
|
-
const cached = objectContentCache.get(component);
|
|
52
|
-
if (cached) {
|
|
53
|
-
return cached;
|
|
54
|
-
}
|
|
55
|
-
const promise = Promise.resolve(component);
|
|
56
|
-
objectContentCache.set(component, promise);
|
|
57
|
-
return promise;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const cached = primitiveContentCache.get(component);
|
|
61
|
-
if (cached) {
|
|
62
|
-
return cached;
|
|
63
|
-
}
|
|
64
|
-
const promise = Promise.resolve(component);
|
|
65
|
-
primitiveContentCache.set(component, promise);
|
|
66
|
-
return promise;
|
|
67
|
-
}
|