@rangojs/router 0.0.0-experimental.31 → 0.0.0-experimental.3232cd17
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/AGENTS.md +4 -0
- package/README.md +198 -44
- package/dist/bin/rango.js +287 -105
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3248 -1117
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +73 -21
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +107 -1
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +245 -21
- package/skills/caching/SKILL.md +302 -6
- package/skills/composability/SKILL.md +27 -2
- package/skills/css/SKILL.md +76 -0
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +270 -30
- package/skills/host-router/SKILL.md +82 -22
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +49 -5
- package/skills/layout/SKILL.md +35 -9
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +294 -30
- package/skills/middleware/SKILL.md +52 -13
- package/skills/migrate-nextjs/SKILL.md +584 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +203 -7
- package/skills/prerender/SKILL.md +123 -100
- package/skills/rango/SKILL.md +250 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +122 -47
- package/skills/route/SKILL.md +97 -5
- package/skills/router-setup/SKILL.md +90 -5
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +129 -0
- package/skills/testing/bindings.md +89 -0
- package/skills/testing/cache-prerender.md +124 -0
- package/skills/testing/client-components.md +122 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +92 -0
- package/skills/testing/handles.md +129 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +121 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +84 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +120 -0
- package/skills/typesafety/SKILL.md +329 -27
- package/skills/use-cache/SKILL.md +36 -5
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +67 -40
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +86 -147
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +148 -19
- package/src/browser/navigation-client.ts +187 -67
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +76 -67
- package/src/browser/navigation-transaction.ts +18 -66
- package/src/browser/partial-update.ts +123 -94
- package/src/browser/prefetch/cache.ts +214 -36
- package/src/browser/prefetch/fetch.ts +260 -38
- package/src/browser/prefetch/policy.ts +6 -0
- package/src/browser/prefetch/queue.ts +126 -20
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +93 -11
- package/src/browser/react/NavigationProvider.tsx +115 -34
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/filter-segment-order.ts +49 -7
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +166 -8
- package/src/browser/react/location-state.ts +39 -14
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +23 -69
- package/src/browser/react/use-link-status.ts +0 -4
- package/src/browser/react/use-navigation.ts +22 -5
- package/src/browser/react/use-params.ts +20 -10
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +46 -11
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +11 -21
- package/src/browser/response-adapter.ts +52 -1
- package/src/browser/rsc-router.tsx +215 -76
- package/src/browser/scroll-restoration.ts +46 -39
- package/src/browser/segment-reconciler.ts +36 -9
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +176 -50
- package/src/browser/types.ts +95 -11
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +65 -40
- package/src/build/generate-route-types.ts +5 -0
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +137 -32
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +9 -2
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +278 -96
- package/src/build/route-types/scan-filter.ts +9 -2
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-policy.ts +68 -28
- package/src/cache/cache-runtime.ts +149 -43
- package/src/cache/cache-scope.ts +148 -81
- package/src/cache/cache-tag.ts +98 -0
- package/src/cache/cf/cf-cache-store.ts +2550 -93
- package/src/cache/cf/index.ts +11 -17
- package/src/cache/document-cache.ts +78 -27
- package/src/cache/handle-snapshot.ts +63 -0
- package/src/cache/index.ts +23 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +6 -30
- package/src/cache/read-through-swr.ts +41 -11
- package/src/cache/segment-codec.ts +0 -16
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +55 -0
- package/src/cache/types.ts +33 -100
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +799 -0
- package/src/client.rsc.tsx +6 -21
- package/src/client.tsx +108 -290
- package/src/component-utils.ts +19 -0
- package/src/context-var.ts +84 -2
- package/src/debug.ts +2 -2
- package/src/decode-loader-results.ts +36 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/errors.ts +30 -4
- package/src/handle.ts +70 -22
- package/src/handles/MetaTags.tsx +0 -14
- package/src/handles/breadcrumbs.ts +16 -5
- package/src/handles/meta.ts +0 -39
- package/src/host/cookie-handler.ts +0 -36
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +7 -50
- package/src/host/router.ts +107 -99
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +37 -4
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +137 -22
- package/src/index.rsc.ts +52 -26
- package/src/index.ts +100 -38
- package/src/internal-debug.ts +2 -4
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +20 -13
- package/src/loader.ts +12 -11
- package/src/missing-id-error.ts +68 -0
- package/src/network-error-thrower.tsx +1 -6
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +10 -11
- package/src/prerender/store.ts +37 -41
- package/src/prerender.ts +198 -82
- package/src/redirect-origin.ts +100 -0
- package/src/response-utils.ts +37 -0
- package/src/reverse.ts +65 -15
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +7 -72
- package/src/route-definition/dsl-helpers.ts +437 -274
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +113 -37
- package/src/route-definition/index.ts +3 -0
- package/src/route-definition/redirect.ts +52 -10
- package/src/route-definition/resolve-handler-use.ts +161 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-map-builder.ts +7 -17
- package/src/route-types.ts +37 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +108 -9
- package/src/router/error-handling.ts +13 -17
- package/src/router/find-match.ts +45 -22
- package/src/router/handler-context.ts +83 -41
- package/src/router/intercept-resolution.ts +25 -23
- package/src/router/lazy-includes.ts +19 -53
- package/src/router/loader-resolution.ts +213 -30
- package/src/router/logging.ts +5 -8
- package/src/router/manifest.ts +49 -45
- package/src/router/match-api.ts +121 -205
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +58 -58
- package/src/router/match-middleware/background-revalidation.ts +27 -6
- package/src/router/match-middleware/cache-lookup.ts +205 -249
- package/src/router/match-middleware/cache-store.ts +45 -32
- package/src/router/match-middleware/intercept-resolution.ts +8 -28
- package/src/router/match-middleware/segment-resolution.ts +52 -18
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +104 -40
- package/src/router/metrics.ts +5 -34
- package/src/router/middleware-types.ts +13 -142
- package/src/router/middleware.ts +173 -143
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +109 -63
- package/src/router/prerender-match.ts +192 -54
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +63 -55
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +6 -28
- package/src/router/router-interfaces.ts +100 -35
- package/src/router/router-options.ts +91 -11
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +242 -75
- package/src/router/segment-resolution/helpers.ts +64 -25
- package/src/router/segment-resolution/loader-cache.ts +41 -37
- package/src/router/segment-resolution/revalidation.ts +456 -372
- package/src/router/segment-resolution/static-store.ts +19 -5
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/segment-resolution.ts +4 -1
- package/src/router/segment-wrappers.ts +2 -3
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +0 -20
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/trie-matching.ts +91 -46
- package/src/router/types.ts +10 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +134 -43
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +492 -383
- package/src/rsc/helpers.ts +162 -46
- package/src/rsc/index.ts +1 -1
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +23 -3
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +30 -3
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +90 -63
- package/src/rsc/rsc-rendering.ts +56 -54
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +74 -67
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/types.ts +25 -6
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +4 -20
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +134 -0
- package/src/segment-system.tsx +272 -129
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +309 -61
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +26 -24
- package/src/server/loader-registry.ts +10 -28
- package/src/server/request-context.ts +348 -128
- package/src/ssr/index.tsx +23 -15
- package/src/static-handler.ts +27 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +618 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +232 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +99 -0
- package/src/testing/internal/context.ts +348 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +330 -0
- package/src/testing/render-route.tsx +566 -0
- package/src/testing/run-loader.ts +378 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- package/src/theme/ThemeProvider.tsx +0 -52
- package/src/theme/ThemeScript.tsx +0 -6
- package/src/theme/constants.ts +0 -12
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +0 -14
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +17 -8
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +233 -81
- package/src/types/index.ts +1 -10
- package/src/types/loader-types.ts +44 -15
- package/src/types/request-scope.ts +107 -0
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +19 -7
- package/src/types/segments.ts +37 -14
- package/src/urls/include-helper.ts +33 -70
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +58 -11
- package/src/urls/path-helper.ts +57 -111
- package/src/urls/pattern-types.ts +48 -19
- package/src/urls/response-types.ts +25 -22
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -18
- package/src/use-loader.tsx +346 -89
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +36 -38
- package/src/vite/discovery/discover-routers.ts +130 -85
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +192 -99
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/self-gen-tracking.ts +27 -1
- package/src/vite/discovery/state.ts +51 -6
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +8 -0
- package/src/vite/plugin-types.ts +187 -69
- package/src/vite/plugins/cjs-to-esm.ts +8 -18
- package/src/vite/plugins/client-ref-dedup.ts +16 -11
- package/src/vite/plugins/client-ref-hashing.ts +28 -15
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
- package/src/vite/plugins/expose-action-id.ts +49 -98
- package/src/vite/plugins/expose-id-utils.ts +11 -50
- package/src/vite/plugins/expose-ids/export-analysis.ts +76 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +10 -48
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -20
- package/src/vite/plugins/expose-ids/router-transform.ts +20 -16
- package/src/vite/plugins/expose-internal-ids.ts +554 -317
- package/src/vite/plugins/performance-tracks.ts +89 -0
- package/src/vite/plugins/refresh-cmd.ts +89 -27
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/vercel-output.ts +258 -0
- package/src/vite/plugins/version-injector.ts +21 -25
- package/src/vite/plugins/version-plugin.ts +41 -20
- package/src/vite/plugins/virtual-entries.ts +2 -17
- package/src/vite/rango.ts +257 -289
- package/src/vite/router-discovery.ts +930 -140
- package/src/vite/utils/ast-handler-extract.ts +15 -31
- package/src/vite/utils/banner.ts +4 -4
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +4 -59
- package/src/vite/utils/package-resolution.ts +20 -52
- package/src/vite/utils/prerender-utils.ts +27 -29
- package/src/vite/utils/shared-utils.ts +92 -42
- package/src/browser/action-response-classifier.ts +0 -99
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -7
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { registerRouteMap } from "../route-map-builder.js";
|
|
2
|
-
import { extractStaticPrefix } from "./pattern-matching.js";
|
|
2
|
+
import { extractStaticPrefix, joinPrefix } from "./pattern-matching.js";
|
|
3
3
|
import {
|
|
4
|
-
EntryData,
|
|
5
|
-
|
|
4
|
+
type EntryData,
|
|
5
|
+
RangoContext,
|
|
6
6
|
runWithPrefixes,
|
|
7
|
+
getIsolatedLazyParent,
|
|
7
8
|
} from "../server/context";
|
|
8
9
|
import type { UrlPatterns } from "../urls.js";
|
|
9
10
|
import type { AllUseItems, IncludeItem } from "../route-types.js";
|
|
@@ -14,11 +15,9 @@ export interface LazyEvalDeps<TEnv = any> {
|
|
|
14
15
|
mergedRouteMap: Record<string, string>;
|
|
15
16
|
nextMountIndex: () => number;
|
|
16
17
|
getPrecomputedByPrefix: () => Map<string, Record<string, string>> | null;
|
|
18
|
+
routerId?: string;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
// Detect lazy includes in handler result and create placeholder entries
|
|
20
|
-
// Lazy includes are IncludeItem with lazy: true and _lazyContext
|
|
21
|
-
// Moved to outer scope so it can be reused by evaluateLazyEntry for nested includes
|
|
22
21
|
export function findLazyIncludes<TEnv = any>(
|
|
23
22
|
items: AllUseItems[],
|
|
24
23
|
): Array<{
|
|
@@ -54,7 +53,6 @@ export function findLazyIncludes<TEnv = any>(
|
|
|
54
53
|
});
|
|
55
54
|
}
|
|
56
55
|
}
|
|
57
|
-
// Recursively check nested items (in layouts, etc.)
|
|
58
56
|
if ((item as any).uses && Array.isArray((item as any).uses)) {
|
|
59
57
|
lazyItems.push(...findLazyIncludes((item as any).uses));
|
|
60
58
|
}
|
|
@@ -76,14 +74,6 @@ export function evaluateLazyEntry<TEnv = any>(
|
|
|
76
74
|
return;
|
|
77
75
|
}
|
|
78
76
|
|
|
79
|
-
// Check for pre-computed routes from build-time data.
|
|
80
|
-
// Only leaf nodes (no nested includes) are precomputed, so entries with
|
|
81
|
-
// nested lazy includes fall through to the handler below.
|
|
82
|
-
// When multiple entries share the same staticPrefix (e.g., several
|
|
83
|
-
// include("/", ...) calls), the precomputed data merges all their routes
|
|
84
|
-
// into one entry. Assigning that merged set to the first matching entry
|
|
85
|
-
// causes findMatch to pick the wrong handler for routes belonging to a
|
|
86
|
-
// different include. Skip the shortcut when the prefix is shared.
|
|
87
77
|
const currentPrecomputed = deps.getPrecomputedByPrefix();
|
|
88
78
|
if (currentPrecomputed) {
|
|
89
79
|
const routes = currentPrecomputed.get(entry.staticPrefix);
|
|
@@ -103,50 +93,41 @@ export function evaluateLazyEntry<TEnv = any>(
|
|
|
103
93
|
}
|
|
104
94
|
}
|
|
105
95
|
|
|
106
|
-
// Mark as evaluated immediately to prevent concurrent evaluation.
|
|
107
|
-
// JS is single-threaded but handlers.handler() could theoretically yield,
|
|
108
|
-
// and the while-loop in findMatch retries after evaluation.
|
|
109
96
|
entry.lazyEvaluated = true;
|
|
110
97
|
|
|
111
98
|
const lazyPatterns = entry.lazyPatterns as UrlPatterns<TEnv>;
|
|
112
99
|
const lazyContext = entry.lazyContext;
|
|
113
100
|
|
|
114
|
-
// Create a new context for evaluating the lazy patterns
|
|
115
101
|
const manifest = new Map<string, EntryData>();
|
|
116
102
|
const patterns = new Map<string, string>();
|
|
117
103
|
const patternsByPrefix = new Map<string, Map<string, string>>();
|
|
118
104
|
const trailingSlashMap = new Map<string, TrailingSlashMode>();
|
|
119
105
|
|
|
120
|
-
// Capture the handler result to detect nested lazy includes
|
|
121
106
|
let handlerResult: AllUseItems[] = [];
|
|
122
107
|
|
|
123
|
-
// Merge captured counters from include() to maintain consistent
|
|
124
|
-
// shortCode indices with sibling entries from pattern extraction
|
|
125
108
|
const lazyCounters: Record<string, number> = {};
|
|
126
|
-
if (lazyContext
|
|
127
|
-
const
|
|
128
|
-
for (const [key, value] of Object.entries(captured)) {
|
|
109
|
+
if (lazyContext?.counters) {
|
|
110
|
+
for (const [key, value] of Object.entries(lazyContext.counters)) {
|
|
129
111
|
lazyCounters[key] = value;
|
|
130
112
|
}
|
|
131
113
|
}
|
|
132
114
|
|
|
133
|
-
|
|
115
|
+
RangoContext.run(
|
|
134
116
|
{
|
|
135
117
|
manifest,
|
|
136
118
|
patterns,
|
|
137
119
|
patternsByPrefix,
|
|
138
120
|
trailingSlash: trailingSlashMap,
|
|
139
121
|
namespace: "lazy",
|
|
140
|
-
parent: (lazyContext?.parent as EntryData | null)
|
|
122
|
+
parent: getIsolatedLazyParent(lazyContext?.parent as EntryData | null),
|
|
141
123
|
counters: lazyCounters,
|
|
142
|
-
cacheProfiles:
|
|
143
|
-
rootScoped:
|
|
124
|
+
cacheProfiles: lazyContext?.cacheProfiles,
|
|
125
|
+
rootScoped: lazyContext?.rootScoped,
|
|
126
|
+
includeScope: lazyContext?.includeScope,
|
|
144
127
|
},
|
|
145
128
|
() => {
|
|
146
|
-
// Run the lazy patterns handler with the original context prefixes
|
|
147
|
-
// The prefix comes from the IncludeItem stored in lazyPatterns
|
|
148
129
|
const includePrefix = (entry as any)._lazyPrefix || "";
|
|
149
|
-
const fullPrefix = (lazyContext?.urlPrefix
|
|
130
|
+
const fullPrefix = joinPrefix(lazyContext?.urlPrefix, includePrefix);
|
|
150
131
|
|
|
151
132
|
if (fullPrefix || lazyContext?.namePrefix) {
|
|
152
133
|
runWithPrefixes(fullPrefix, lazyContext?.namePrefix, () => {
|
|
@@ -158,11 +139,9 @@ export function evaluateLazyEntry<TEnv = any>(
|
|
|
158
139
|
},
|
|
159
140
|
);
|
|
160
141
|
|
|
161
|
-
// Populate the entry's routes from the patterns
|
|
162
142
|
const routesObject: Record<string, string> = {};
|
|
163
143
|
for (const [name, pattern] of patterns.entries()) {
|
|
164
144
|
routesObject[name] = pattern;
|
|
165
|
-
// Also add to merged route map for reverse() support
|
|
166
145
|
const existingPattern = deps.mergedRouteMap[name];
|
|
167
146
|
if (existingPattern !== undefined && existingPattern !== pattern) {
|
|
168
147
|
console.warn(
|
|
@@ -173,45 +152,33 @@ export function evaluateLazyEntry<TEnv = any>(
|
|
|
173
152
|
deps.mergedRouteMap[name] = pattern;
|
|
174
153
|
}
|
|
175
154
|
|
|
176
|
-
// Update the entry in-place
|
|
177
155
|
entry.routes = routesObject as ResolvedRouteMap<any>;
|
|
178
156
|
|
|
179
|
-
// Note: Do NOT clear lazyPatterns/lazyContext here.
|
|
180
|
-
// loadManifest() needs them on every request to re-run the handler
|
|
181
|
-
// in the correct AsyncLocalStorage context (Store.manifest).
|
|
182
|
-
|
|
183
|
-
// Update trailing slash config if available
|
|
184
157
|
if (trailingSlashMap.size > 0) {
|
|
185
158
|
entry.trailingSlash = Object.fromEntries(trailingSlashMap);
|
|
186
159
|
}
|
|
187
160
|
|
|
188
|
-
// Detect nested lazy includes and register them as new entries
|
|
189
161
|
const nestedLazyIncludes = findLazyIncludes(handlerResult);
|
|
190
162
|
for (const lazyInclude of nestedLazyIncludes) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
163
|
+
const fullPrefix = joinPrefix(
|
|
164
|
+
lazyInclude.context.urlPrefix,
|
|
165
|
+
lazyInclude.prefix,
|
|
166
|
+
);
|
|
195
167
|
|
|
196
168
|
const nestedEntry: RouteEntry<TEnv> & { _lazyPrefix?: string } = {
|
|
197
169
|
prefix: "",
|
|
198
170
|
staticPrefix: extractStaticPrefix(fullPrefix),
|
|
199
|
-
routes: {} as ResolvedRouteMap<any>,
|
|
171
|
+
routes: {} as ResolvedRouteMap<any>,
|
|
200
172
|
trailingSlash: entry.trailingSlash,
|
|
201
173
|
handler: (lazyInclude.patterns as UrlPatterns<TEnv>).handler,
|
|
202
174
|
mountIndex: deps.nextMountIndex(),
|
|
203
|
-
|
|
175
|
+
routerId: deps.routerId,
|
|
204
176
|
lazy: true,
|
|
205
177
|
lazyPatterns: lazyInclude.patterns,
|
|
206
178
|
lazyContext: lazyInclude.context,
|
|
207
179
|
lazyEvaluated: false,
|
|
208
|
-
// Store the include prefix for evaluation
|
|
209
180
|
_lazyPrefix: lazyInclude.prefix,
|
|
210
181
|
};
|
|
211
|
-
// Insert nested lazy entry before any entry whose staticPrefix is a
|
|
212
|
-
// prefix of (but shorter than) this lazy entry's staticPrefix.
|
|
213
|
-
// This ensures more specific lazy includes are matched before
|
|
214
|
-
// less specific eager entries (e.g., "/href/nested" before "/href/:id").
|
|
215
182
|
const nestedPrefix = nestedEntry.staticPrefix;
|
|
216
183
|
let insertIndex = deps.routesEntries.length;
|
|
217
184
|
if (nestedPrefix) {
|
|
@@ -229,6 +196,5 @@ export function evaluateLazyEntry<TEnv = any>(
|
|
|
229
196
|
deps.routesEntries.splice(insertIndex, 0, nestedEntry);
|
|
230
197
|
}
|
|
231
198
|
|
|
232
|
-
// Re-register route map for runtime reverse() usage
|
|
233
199
|
registerRouteMap(deps.mergedRouteMap);
|
|
234
200
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import type { ReactNode } from "react";
|
|
8
8
|
import { track } from "../server/context";
|
|
9
9
|
import type { EntryData } from "../server/context";
|
|
10
|
+
import { contextGet } from "../context-var.js";
|
|
10
11
|
import type {
|
|
11
12
|
ResolvedSegment,
|
|
12
13
|
HandlerContext,
|
|
@@ -18,11 +19,17 @@ import type {
|
|
|
18
19
|
ErrorBoundaryFallbackProps,
|
|
19
20
|
ErrorInfo,
|
|
20
21
|
} from "../types";
|
|
21
|
-
import
|
|
22
|
-
import {
|
|
23
|
-
import
|
|
22
|
+
import { isHandle, collectHandleData, type Handle } from "../handle.js";
|
|
23
|
+
import { withDefer } from "../defer.js";
|
|
24
|
+
import { buildHandleSnapshot } from "../server/handle-store.js";
|
|
24
25
|
import { getFetchableLoader } from "../server/fetchable-loader-store.js";
|
|
25
26
|
import { _getRequestContext } from "../server/request-context.js";
|
|
27
|
+
import {
|
|
28
|
+
isInsideLoaderScope,
|
|
29
|
+
runInsideLoaderBodyScope,
|
|
30
|
+
isInsidePushCallbackScope,
|
|
31
|
+
runInsidePushCallbackScope,
|
|
32
|
+
} from "../server/context.js";
|
|
26
33
|
import { debugLog } from "./logging.js";
|
|
27
34
|
|
|
28
35
|
/**
|
|
@@ -64,7 +71,9 @@ export function wrapLoaderWithErrorHandling<T>(
|
|
|
64
71
|
) => ErrorInfo,
|
|
65
72
|
onError?: LoaderErrorCallback,
|
|
66
73
|
): Promise<LoaderDataResult<T>> {
|
|
67
|
-
// Extract
|
|
74
|
+
// Extract the trailing token from segmentId (format: "<shortCode>D<i>.<loaderId>").
|
|
75
|
+
// The token is the loader's $$id (hash#export in prod, pathfrag#export in dev),
|
|
76
|
+
// not a clean display name.
|
|
68
77
|
const loaderName = segmentId.split(".").pop() || "unknown";
|
|
69
78
|
|
|
70
79
|
return Promise.resolve(promise)
|
|
@@ -241,6 +250,21 @@ function createLoaderExecutor<TEnv>(
|
|
|
241
250
|
pendingLoaders.add(loader.$$id);
|
|
242
251
|
|
|
243
252
|
const currentLoaderId = loader.$$id;
|
|
253
|
+
const variables = (ctx as InternalHandlerContext<any, TEnv>)._variables;
|
|
254
|
+
|
|
255
|
+
// Capture whether this loader is being started from a DSL loader scope
|
|
256
|
+
// (runInsideLoaderScope in fresh.ts). Handler-invoked loaders are NOT
|
|
257
|
+
// inside loader scope. This determines whether rendered() is allowed.
|
|
258
|
+
const isDslLoader = isInsideLoaderScope();
|
|
259
|
+
|
|
260
|
+
let renderedResolved = false;
|
|
261
|
+
let renderedPromise: Promise<void> | null = null;
|
|
262
|
+
|
|
263
|
+
// Loader functions are always fresh (never cached), so they get an
|
|
264
|
+
// unguarded get that bypasses non-cacheable read guards. This applies
|
|
265
|
+
// to ALL loaders — DSL and handler-called — because the loader
|
|
266
|
+
// function itself always re-executes. Also handles nested deps
|
|
267
|
+
// (loaderA → use(loaderB)) since all share this unguarded get.
|
|
244
268
|
const loaderCtx: LoaderContext<Record<string, string | undefined>, TEnv> = {
|
|
245
269
|
params: ctx.params,
|
|
246
270
|
routeParams: (ctx.params ?? {}) as Record<string, string>,
|
|
@@ -249,22 +273,129 @@ function createLoaderExecutor<TEnv>(
|
|
|
249
273
|
search: (ctx as any).search,
|
|
250
274
|
pathname: ctx.pathname,
|
|
251
275
|
url: ctx.url,
|
|
276
|
+
originalUrl: ctx.originalUrl,
|
|
252
277
|
env: ctx.env,
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
278
|
+
waitUntil: ctx.waitUntil.bind(ctx),
|
|
279
|
+
executionContext: ctx.executionContext,
|
|
280
|
+
get: ((keyOrVar: any) =>
|
|
281
|
+
contextGet(variables, keyOrVar)) as typeof ctx.get,
|
|
282
|
+
use: ((item: LoaderDefinition<any, any> | Handle<any, any>) => {
|
|
283
|
+
if (isHandle(item)) {
|
|
284
|
+
if (!renderedResolved) {
|
|
285
|
+
throw new Error(
|
|
286
|
+
`ctx.use(handle) in a loader requires "await ctx.rendered()" first. ` +
|
|
287
|
+
`Handle "${item.$$id}" cannot be read until the render tree has settled.`,
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
const reqCtx = reqCtxRef ?? _getRequestContext();
|
|
291
|
+
if (!reqCtx) {
|
|
292
|
+
throw new Error(
|
|
293
|
+
`ctx.use(handle) failed: request context not available.`,
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
const segmentOrder = reqCtx._renderBarrierSegmentOrder ?? [];
|
|
297
|
+
// The complete snapshot is cached at barrier resolution for
|
|
298
|
+
// non-streaming trees, and by rendered() after handleStore.settled for
|
|
299
|
+
// streaming trees (where the eager snapshot would have been incomplete
|
|
300
|
+
// because loading() handlers were still in flight). Either way it is
|
|
301
|
+
// present by the time a loader reads a handle; the fresh build is only
|
|
302
|
+
// a defensive fallback.
|
|
303
|
+
const snapshot =
|
|
304
|
+
reqCtx._renderBarrierHandleSnapshot ??
|
|
305
|
+
buildHandleSnapshot(reqCtx._handleStore, segmentOrder);
|
|
306
|
+
return collectHandleData(item, snapshot, segmentOrder);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Loader case
|
|
310
|
+
return useLoader(item as LoaderDefinition<any, any>, currentLoaderId);
|
|
311
|
+
}) as LoaderContext["use"],
|
|
260
312
|
method: "GET",
|
|
261
313
|
body: undefined,
|
|
262
314
|
reverse: ctx.reverse as LoaderContext["reverse"],
|
|
315
|
+
rendered: (): Promise<void> => {
|
|
316
|
+
// Guard: only DSL loaders may use rendered()
|
|
317
|
+
if (!isDslLoader) {
|
|
318
|
+
throw new Error(
|
|
319
|
+
`ctx.rendered() is only available in DSL loaders (registered via loader() in urls()). ` +
|
|
320
|
+
`Handler-invoked loaders (ctx.use(Loader) inside a handler) cannot use rendered().`,
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const reqCtx = reqCtxRef ?? _getRequestContext();
|
|
325
|
+
|
|
326
|
+
if (renderedPromise) return renderedPromise;
|
|
327
|
+
|
|
328
|
+
if (!reqCtx) {
|
|
329
|
+
throw new Error(
|
|
330
|
+
`ctx.rendered() failed: request context not available.`,
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Bidirectional deadlock check: if a handler already started
|
|
335
|
+
// awaiting this loader, calling rendered() would deadlock. This is the
|
|
336
|
+
// real cycle guard (it holds for both streaming and non-streaming): the
|
|
337
|
+
// handler blocks segment resolution, which blocks the barrier, which
|
|
338
|
+
// blocks this loader.
|
|
339
|
+
if (reqCtx._handlerLoaderDeps?.has(currentLoaderId)) {
|
|
340
|
+
throw new Error(
|
|
341
|
+
`Deadlock: loader "${currentLoaderId}" called ctx.rendered() but a handler ` +
|
|
342
|
+
`is already awaiting this loader via ctx.use(). The handler blocks ` +
|
|
343
|
+
`segment resolution, which blocks the barrier, which blocks this loader. ` +
|
|
344
|
+
`Move the data dependency to a loader-to-loader pattern instead.`,
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Register this loader as waiting for the barrier so that
|
|
349
|
+
// setupLoaderAccess can detect deadlocks when a handler
|
|
350
|
+
// tries to await the same loader via ctx.use().
|
|
351
|
+
if (!reqCtx._renderBarrierWaiters) {
|
|
352
|
+
reqCtx._renderBarrierWaiters = new Set();
|
|
353
|
+
}
|
|
354
|
+
reqCtx._renderBarrierWaiters.add(currentLoaderId);
|
|
355
|
+
|
|
356
|
+
// Streaming trees (loading()): the barrier resolves once the segment
|
|
357
|
+
// tree is resolved, but loading() handlers stream behind Suspense and
|
|
358
|
+
// their handle pushes are still in flight then. Their async execution
|
|
359
|
+
// IS tracked in the handle store (trackHandler -> store.track), so after
|
|
360
|
+
// the barrier we seal (no further handlers register once the tree is
|
|
361
|
+
// resolved) and wait for settled — every tracked handler, streaming
|
|
362
|
+
// included, has finished pushing. The loader's own segment streams in
|
|
363
|
+
// after, so this does not block the shell; the deadlock guard above
|
|
364
|
+
// keeps a handler from depending on this loader.
|
|
365
|
+
const streaming = reqCtx._treeHasStreaming === true;
|
|
366
|
+
renderedPromise = reqCtx._renderBarrier.then(async () => {
|
|
367
|
+
if (streaming) {
|
|
368
|
+
reqCtx._handleStore.seal();
|
|
369
|
+
await reqCtx._handleStore.settled;
|
|
370
|
+
// The eager snapshot was intentionally left unbuilt for streaming
|
|
371
|
+
// (it would have been incomplete). Build the complete one once, now
|
|
372
|
+
// that the store has settled, so every ctx.use(handle) reads the
|
|
373
|
+
// cached snapshot instead of rebuilding it per call.
|
|
374
|
+
reqCtx._renderBarrierHandleSnapshot ??= buildHandleSnapshot(
|
|
375
|
+
reqCtx._handleStore,
|
|
376
|
+
reqCtx._renderBarrierSegmentOrder ?? [],
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
renderedResolved = true;
|
|
380
|
+
});
|
|
381
|
+
return renderedPromise;
|
|
382
|
+
},
|
|
263
383
|
};
|
|
264
384
|
|
|
265
385
|
const doneLoader = track(`loader:${loader.$$id}`, 2);
|
|
386
|
+
// Run the loader body inside loader scope so request-scoped reads
|
|
387
|
+
// (cookies()/headers() and non-cacheable ctx.get) are exempt from the
|
|
388
|
+
// cache-purity guards: loaders always run fresh, so their reads never leak
|
|
389
|
+
// into a cached segment. DSL loaders are already wrapped by fresh.ts; this
|
|
390
|
+
// also covers handler-invoked loaders (ctx.use(Loader) from a handler),
|
|
391
|
+
// which otherwise execute in the caller's cache scope and would wrongly
|
|
392
|
+
// throw. rendered() gating uses the captured isDslLoader (above), so this
|
|
393
|
+
// does not grant rendered() to handler-invoked loaders. Uses a body-only
|
|
394
|
+
// scope, so isInsideLoaderScope() / barrier / deadlock gating is unchanged.
|
|
266
395
|
const promise = Promise.resolve(
|
|
267
|
-
|
|
396
|
+
runInsideLoaderBodyScope(() =>
|
|
397
|
+
loaderFn(loaderCtx as LoaderContext<any, TEnv>),
|
|
398
|
+
),
|
|
268
399
|
).finally(() => {
|
|
269
400
|
pendingLoaders.delete(loader.$$id);
|
|
270
401
|
doneLoader();
|
|
@@ -290,12 +421,13 @@ export function setupLoaderAccess<TEnv>(
|
|
|
290
421
|
ctx: HandlerContext<any, TEnv>,
|
|
291
422
|
loaderPromises: Map<string, Promise<any>>,
|
|
292
423
|
): void {
|
|
293
|
-
// Eagerly capture the HandleStore at setup time
|
|
294
|
-
// In workerd/Cloudflare, dynamic imports and
|
|
295
|
-
// can disrupt AsyncLocalStorage, causing
|
|
296
|
-
// undefined when handlers later call
|
|
297
|
-
//
|
|
298
|
-
const
|
|
424
|
+
// Eagerly capture the request context and HandleStore at setup time
|
|
425
|
+
// (before pipeline async ops). In workerd/Cloudflare, dynamic imports and
|
|
426
|
+
// fetch() in the match pipeline can disrupt AsyncLocalStorage, causing
|
|
427
|
+
// getRequestContext() to return undefined when handlers later call
|
|
428
|
+
// ctx.use(handle). Capturing early ensures references survive ALS disruption.
|
|
429
|
+
const reqCtxRef = _getRequestContext();
|
|
430
|
+
const handleStoreRef = reqCtxRef?._handleStore;
|
|
299
431
|
|
|
300
432
|
const useLoader = createLoaderExecutor(ctx, loaderPromises);
|
|
301
433
|
|
|
@@ -313,21 +445,72 @@ export function setupLoaderAccess<TEnv>(
|
|
|
313
445
|
);
|
|
314
446
|
}
|
|
315
447
|
|
|
316
|
-
return (
|
|
317
|
-
dataOrFn: unknown | Promise<unknown> | (() => Promise<unknown>)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
448
|
+
return withDefer(
|
|
449
|
+
(dataOrFn: unknown | Promise<unknown> | (() => Promise<unknown>)) => {
|
|
450
|
+
if (!store) return;
|
|
451
|
+
|
|
452
|
+
if (typeof dataOrFn === "function") {
|
|
453
|
+
// Run the callback inside the push-callback scope so ctx.use(loader)
|
|
454
|
+
// calls it makes — including after its own awaits, for an async
|
|
455
|
+
// callback — are not registered as handler-to-loader deps and do not
|
|
456
|
+
// trip the deadlock guard. A pushed promise value is not tracked by
|
|
457
|
+
// handleStore.settled and does not block segment resolution, so it
|
|
458
|
+
// cannot form a rendered() deadlock. The ALS scope (not a plain
|
|
459
|
+
// boolean) is what survives the callback's awaits.
|
|
460
|
+
const result = runInsidePushCallbackScope(() =>
|
|
461
|
+
(dataOrFn as () => Promise<unknown>)(),
|
|
462
|
+
);
|
|
463
|
+
store.push(handle.$$id, segmentId, result);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
store.push(handle.$$id, segmentId, dataOrFn);
|
|
468
|
+
},
|
|
469
|
+
);
|
|
470
|
+
}
|
|
325
471
|
|
|
326
|
-
|
|
327
|
-
|
|
472
|
+
// Deadlock guard and handler-to-loader dependency tracking.
|
|
473
|
+
// Skip when inside a DSL loader scope (resolveLoaderData also calls
|
|
474
|
+
// ctx.use() but that's DSL-to-DSL, not handler-to-loader) or when
|
|
475
|
+
// inside a handle push callback (push callbacks don't block segment
|
|
476
|
+
// resolution so they can't cause rendered() deadlocks). The push-callback
|
|
477
|
+
// check is an ALS scope so it also exempts an ASYNC callback's continuation
|
|
478
|
+
// after its first await — relevant on streaming trees, where the guard
|
|
479
|
+
// state now stays live until handleStore.settled.
|
|
480
|
+
const loader = item as LoaderDefinition<any, any>;
|
|
481
|
+
if (!isInsideLoaderScope() && !isInsidePushCallbackScope()) {
|
|
482
|
+
const reqCtx = reqCtxRef ?? _getRequestContext();
|
|
483
|
+
if (reqCtx) {
|
|
484
|
+
// Direction 1: handler awaits loader that already called rendered()
|
|
485
|
+
if (
|
|
486
|
+
loaderPromises.has(loader.$$id) &&
|
|
487
|
+
reqCtx._renderBarrierWaiters?.has(loader.$$id)
|
|
488
|
+
) {
|
|
489
|
+
throw new Error(
|
|
490
|
+
`Deadlock: handler is awaiting loader "${loader.$$id}" which called ctx.rendered(). ` +
|
|
491
|
+
`The loader is waiting for segment resolution, but the handler blocks resolution. ` +
|
|
492
|
+
`Move the data dependency to a loader-to-loader pattern instead.`,
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
// Direction 2: track dep so rendered() can detect the deadlock if the
|
|
496
|
+
// loader calls it later. Skip once the guard window is CLOSED — for a
|
|
497
|
+
// non-streaming tree that is when the barrier resolves (rendered()
|
|
498
|
+
// resolves immediately), and for a streaming tree it is when
|
|
499
|
+
// handleStore.settled completes (rendered() keeps waiting until then, so
|
|
500
|
+
// a loading() handler resuming after the barrier can still form a
|
|
501
|
+
// cycle). Using the explicit guard-closed flag rather than
|
|
502
|
+
// _renderBarrierSegmentOrder keeps tracking live across the streaming
|
|
503
|
+
// settle wait. (Handle push callbacks are already excluded above via
|
|
504
|
+
// isInsidePushCallbackScope(), so they cannot produce false positives
|
|
505
|
+
// here.)
|
|
506
|
+
if (!reqCtx._renderBarrierGuardClosed) {
|
|
507
|
+
if (!reqCtx._handlerLoaderDeps) reqCtx._handlerLoaderDeps = new Set();
|
|
508
|
+
reqCtx._handlerLoaderDeps.add(loader.$$id);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
328
511
|
}
|
|
329
512
|
|
|
330
|
-
return useLoader(
|
|
513
|
+
return useLoader(loader, null);
|
|
331
514
|
}) as typeof ctx.use;
|
|
332
515
|
}
|
|
333
516
|
|
package/src/router/logging.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
2
|
import { INTERNAL_RANGO_DEBUG } from "../internal-debug.js";
|
|
3
3
|
|
|
4
|
-
// -- Revalidation trace types --
|
|
5
|
-
|
|
6
4
|
export interface RevalidationTraceEntry {
|
|
7
5
|
segmentId: string;
|
|
8
6
|
segmentType: string;
|
|
@@ -12,7 +10,10 @@ export interface RevalidationTraceEntry {
|
|
|
12
10
|
| "cache-hit"
|
|
13
11
|
| "loader"
|
|
14
12
|
| "parallel"
|
|
15
|
-
| "orphan-layout"
|
|
13
|
+
| "orphan-layout"
|
|
14
|
+
| "route-handler"
|
|
15
|
+
| "layout-handler"
|
|
16
|
+
| "intercept-loader";
|
|
16
17
|
defaultShouldRevalidate: boolean;
|
|
17
18
|
finalShouldRevalidate: boolean;
|
|
18
19
|
reason: string;
|
|
@@ -33,8 +34,6 @@ export interface RevalidationTrace {
|
|
|
33
34
|
entries: RevalidationTraceEntry[];
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
// -- Log context --
|
|
37
|
-
|
|
38
37
|
interface RouterLogContext {
|
|
39
38
|
requestId: string;
|
|
40
39
|
transactionId: string;
|
|
@@ -71,7 +70,7 @@ function getHeaderRequestId(request: Request): string | null {
|
|
|
71
70
|
return trimmed.length > 0 ? trimmed : null;
|
|
72
71
|
}
|
|
73
72
|
|
|
74
|
-
function getOrCreateRequestId(request: Request): string {
|
|
73
|
+
export function getOrCreateRequestId(request: Request): string {
|
|
75
74
|
const existing = requestIds.get(request);
|
|
76
75
|
if (existing) return existing;
|
|
77
76
|
|
|
@@ -192,8 +191,6 @@ export function debugWarn(
|
|
|
192
191
|
console.warn(`${prefix} ${message}`);
|
|
193
192
|
}
|
|
194
193
|
|
|
195
|
-
// -- Revalidation trace helpers --
|
|
196
|
-
|
|
197
194
|
export function isTraceActive(): boolean {
|
|
198
195
|
if (!INTERNAL_RANGO_DEBUG) return false;
|
|
199
196
|
const ctx = routerLogContext.getStore();
|