@rangojs/router 0.0.0-experimental.eb0645d3 → 0.0.0-experimental.f1468e3c
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 +8 -0
- package/README.md +126 -16
- package/dist/bin/rango.js +319 -95
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +2724 -1053
- package/package.json +68 -14
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +64 -2
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +224 -32
- package/skills/caching/SKILL.md +279 -17
- package/skills/composability/SKILL.md +27 -3
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +4 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +11 -9
- package/skills/hooks/SKILL.md +243 -29
- package/skills/host-router/SKILL.md +83 -23
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +68 -19
- package/skills/layout/SKILL.md +13 -9
- package/skills/links/SKILL.md +190 -23
- package/skills/loader/SKILL.md +235 -9
- package/skills/middleware/SKILL.md +18 -10
- package/skills/migrate-nextjs/SKILL.md +43 -19
- package/skills/migrate-react-router/SKILL.md +8 -2
- package/skills/mime-routes/SKILL.md +28 -1
- package/skills/observability/SKILL.md +172 -0
- package/skills/parallel/SKILL.md +18 -7
- package/skills/prerender/SKILL.md +65 -60
- package/skills/rango/SKILL.md +251 -24
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +115 -48
- package/skills/route/SKILL.md +46 -5
- package/skills/router-setup/SKILL.md +30 -8
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +130 -0
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -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 +122 -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 +123 -0
- package/skills/typesafety/SKILL.md +322 -29
- package/skills/use-cache/SKILL.md +57 -14
- package/skills/view-transitions/SKILL.md +337 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +0 -65
- 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/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +192 -150
- 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/navigation-bridge.ts +94 -25
- package/src/browser/navigation-client.ts +121 -84
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +115 -67
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +147 -128
- package/src/browser/prefetch/cache.ts +107 -56
- package/src/browser/prefetch/fetch.ts +204 -34
- package/src/browser/prefetch/queue.ts +6 -3
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +30 -7
- package/src/browser/react/NavigationProvider.tsx +283 -118
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/deferred-handle-resolution.ts +75 -0
- package/src/browser/react/filter-segment-order.ts +66 -7
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +178 -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 +17 -14
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +33 -8
- package/src/browser/react/use-navigation.ts +10 -5
- package/src/browser/react/use-params.ts +11 -11
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +25 -3
- 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 +99 -8
- package/src/browser/rsc-router.tsx +91 -24
- package/src/browser/scroll-restoration.ts +30 -17
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +214 -55
- package/src/browser/types.ts +80 -9
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +2 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +117 -14
- package/src/build/route-types/ast-route-extraction.ts +15 -8
- package/src/build/route-types/codegen.ts +16 -5
- package/src/build/route-types/include-resolution.ts +117 -23
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +22 -6
- package/src/build/route-types/router-processing.ts +55 -28
- package/src/build/route-types/scan-filter.ts +1 -1
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +29 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +224 -41
- package/src/cache/cache-scope.ts +188 -82
- package/src/cache/cache-tag.ts +103 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +1989 -378
- package/src/cache/cf/cf-cache-types.ts +349 -0
- package/src/cache/cf/cf-kv-utils.ts +46 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
- package/src/cache/cf/index.ts +6 -16
- package/src/cache/document-cache.ts +89 -21
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +10 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +9 -17
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +37 -100
- package/src/client.rsc.tsx +44 -21
- package/src/client.tsx +36 -61
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +19 -0
- package/src/components/DefaultDocument.tsx +8 -2
- package/src/context-var.ts +18 -6
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +30 -4
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +31 -23
- package/src/handles/MetaTags.tsx +62 -19
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +37 -8
- package/src/handles/is-thenable.ts +19 -0
- package/src/handles/meta.ts +51 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +23 -52
- 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 +96 -12
- package/src/index.ts +94 -14
- package/src/internal-debug.ts +11 -10
- 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/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/store.ts +32 -37
- package/src/prerender.ts +61 -6
- package/src/redirect-origin.ts +100 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +34 -0
- package/src/reverse.ts +65 -40
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +19 -77
- package/src/route-definition/dsl-helpers.ts +304 -309
- package/src/route-definition/helper-factories.ts +28 -140
- package/src/route-definition/helpers-types.ts +82 -55
- package/src/route-definition/index.ts +1 -2
- package/src/route-definition/redirect.ts +44 -11
- package/src/route-definition/resolve-handler-use.ts +12 -1
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-map-builder.ts +0 -16
- package/src/route-types.ts +19 -46
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +73 -25
- package/src/router/error-handling.ts +45 -18
- package/src/router/find-match.ts +44 -23
- package/src/router/handler-context.ts +27 -43
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +39 -20
- package/src/router/lazy-includes.ts +10 -47
- package/src/router/loader-resolution.ts +155 -72
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +18 -29
- package/src/router/match-api.ts +9 -24
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +58 -58
- package/src/router/match-middleware/background-revalidation.ts +40 -24
- package/src/router/match-middleware/cache-lookup.ts +159 -285
- package/src/router/match-middleware/cache-store.ts +64 -52
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +0 -22
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +44 -74
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +7 -134
- package/src/router/middleware.ts +247 -166
- package/src/router/navigation-snapshot.ts +0 -51
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +85 -94
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prerender-match.ts +104 -65
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +28 -62
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +0 -1
- package/src/router/router-context.ts +3 -28
- package/src/router/router-interfaces.ts +83 -35
- package/src/router/router-options.ts +136 -5
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +97 -84
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +76 -39
- package/src/router/segment-resolution/revalidation.ts +272 -320
- 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 +56 -0
- package/src/router/segment-resolution.ts +5 -1
- package/src/router/segment-wrappers.ts +6 -5
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +161 -199
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +162 -64
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +0 -5
- package/src/router.ts +110 -55
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +264 -220
- package/src/rsc/helpers.ts +100 -6
- package/src/rsc/index.ts +2 -5
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +114 -38
- package/src/rsc/manifest-init.ts +28 -41
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +117 -11
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +88 -188
- package/src/rsc/rsc-rendering.ts +98 -76
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +281 -117
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +23 -5
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- package/src/segment-loader-promise.ts +31 -4
- package/src/segment-system.tsx +254 -143
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +163 -51
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +21 -38
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +287 -178
- package/src/ssr/index.tsx +21 -16
- package/src/static-handler.ts +10 -13
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +701 -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 +257 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +371 -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 +357 -0
- package/src/testing/render-route.tsx +581 -0
- package/src/testing/run-loader.ts +385 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/run-transition-when.ts +164 -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 +20 -58
- package/src/theme/ThemeScript.tsx +7 -9
- package/src/theme/constants.ts +52 -13
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +22 -21
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +13 -4
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +110 -62
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +11 -9
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +135 -14
- package/src/urls/include-helper.ts +9 -56
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +29 -12
- package/src/urls/path-helper.ts +17 -106
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +22 -29
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +292 -107
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +8 -7
- package/src/vite/discovery/discover-routers.ts +126 -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 +96 -68
- 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 +44 -0
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +2 -0
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +126 -8
- package/src/vite/plugins/cjs-to-esm.ts +16 -19
- 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-stub.ts +1 -21
- package/src/vite/plugins/expose-action-id.ts +48 -95
- package/src/vite/plugins/expose-id-utils.ts +88 -55
- package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +11 -90
- package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
- package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
- package/src/vite/plugins/expose-internal-ids.ts +505 -486
- package/src/vite/plugins/performance-tracks.ts +26 -25
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/version-injector.ts +40 -29
- package/src/vite/plugins/version-plugin.ts +37 -40
- package/src/vite/plugins/virtual-entries.ts +39 -25
- package/src/vite/rango.ts +109 -118
- package/src/vite/router-discovery.ts +718 -119
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/directive-prologue.ts +40 -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 +54 -39
- package/src/vite/utils/shared-utils.ts +90 -41
- 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/network-error-thrower.tsx +0 -23
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
getParallelEntries,
|
|
15
15
|
getParallelSlotEntries,
|
|
16
16
|
type EntryData,
|
|
17
|
+
type ParallelEntryData,
|
|
17
18
|
} from "../../server/context";
|
|
18
19
|
import type {
|
|
19
20
|
HandlerContext,
|
|
@@ -34,58 +35,41 @@ import {
|
|
|
34
35
|
import { resolveLoaderData } from "./loader-cache.js";
|
|
35
36
|
import {
|
|
36
37
|
handleHandlerResult,
|
|
38
|
+
warnOnStreamedResponse,
|
|
37
39
|
tryStaticHandler,
|
|
38
40
|
tryStaticSlot,
|
|
39
41
|
resolveLayoutComponent,
|
|
40
42
|
resolveWithErrorBoundary,
|
|
43
|
+
buildLoaderErrorContext,
|
|
41
44
|
} from "./helpers.js";
|
|
45
|
+
import { applyViewTransitionDefault } from "./view-transition-default.js";
|
|
42
46
|
import { getRouterContext } from "../router-context.js";
|
|
43
|
-
import {
|
|
47
|
+
import { observeEvent, observeHandler } from "../instrument.js";
|
|
48
|
+
import { observeStreamedHandler } from "./streamed-handler-telemetry.js";
|
|
44
49
|
import {
|
|
45
50
|
track,
|
|
46
|
-
|
|
51
|
+
RangoContext,
|
|
47
52
|
runInsideLoaderScope,
|
|
48
53
|
} from "../../server/context.js";
|
|
49
54
|
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
|
-
// Telemetry helpers
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
|
|
54
55
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
56
|
+
* Trace a parallel slot that's being force-rendered on a full refetch (client
|
|
57
|
+
* has no cached state). User revalidate fns are bypassed in this case — see
|
|
58
|
+
* the call sites for the load-bearing rationale.
|
|
57
59
|
*/
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
segmentType: string,
|
|
62
|
-
pathname?: string,
|
|
63
|
-
routeKey?: string,
|
|
64
|
-
params?: Record<string, string>,
|
|
60
|
+
function traceFullRefetchedParallelSlot(
|
|
61
|
+
parallelId: string,
|
|
62
|
+
belongsToRoute: boolean,
|
|
65
63
|
): void {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
promise.catch((err: unknown) => {
|
|
76
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
77
|
-
safeEmit(sink, {
|
|
78
|
-
type: "handler.error",
|
|
79
|
-
timestamp: performance.now(),
|
|
80
|
-
requestId: reqId,
|
|
81
|
-
segmentId,
|
|
82
|
-
segmentType,
|
|
83
|
-
error: errorObj,
|
|
84
|
-
handledByBoundary: true,
|
|
85
|
-
pathname,
|
|
86
|
-
routeKey,
|
|
87
|
-
params,
|
|
88
|
-
});
|
|
64
|
+
if (!isTraceActive()) return;
|
|
65
|
+
pushRevalidationTraceEntry({
|
|
66
|
+
segmentId: parallelId,
|
|
67
|
+
segmentType: "parallel",
|
|
68
|
+
belongsToRoute,
|
|
69
|
+
source: "parallel",
|
|
70
|
+
defaultShouldRevalidate: true,
|
|
71
|
+
finalShouldRevalidate: true,
|
|
72
|
+
reason: "full-refetch",
|
|
89
73
|
});
|
|
90
74
|
}
|
|
91
75
|
|
|
@@ -104,23 +88,14 @@ function emitRevalidationDecision(
|
|
|
104
88
|
routeKey: string,
|
|
105
89
|
shouldRevalidate: boolean,
|
|
106
90
|
): void {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
type: "revalidation.decision",
|
|
116
|
-
timestamp: performance.now(),
|
|
117
|
-
requestId: routerCtx.requestId,
|
|
118
|
-
segmentId,
|
|
119
|
-
pathname,
|
|
120
|
-
routeKey,
|
|
121
|
-
shouldRevalidate,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
91
|
+
observeEvent({
|
|
92
|
+
type: "revalidation.decision",
|
|
93
|
+
timestamp: performance.now(),
|
|
94
|
+
segmentId,
|
|
95
|
+
pathname,
|
|
96
|
+
routeKey,
|
|
97
|
+
shouldRevalidate,
|
|
98
|
+
});
|
|
124
99
|
}
|
|
125
100
|
|
|
126
101
|
// ---------------------------------------------------------------------------
|
|
@@ -225,6 +200,10 @@ export async function resolveLoadersWithRevalidation<TEnv>(
|
|
|
225
200
|
),
|
|
226
201
|
);
|
|
227
202
|
|
|
203
|
+
// Partial (revalidation) render path: a throwing DSL loader must still fire
|
|
204
|
+
// onError/loader.error. isPartial flags the reporting phase accordingly.
|
|
205
|
+
const errorContext = { ...buildLoaderErrorContext(ctx), isPartial: true };
|
|
206
|
+
|
|
228
207
|
const loadersToRun = revalidationChecks.filter((c) => c.shouldRun);
|
|
229
208
|
const segments: ResolvedSegment[] = loadersToRun.map(
|
|
230
209
|
({ loaderEntry, loader, segmentId, index }) => ({
|
|
@@ -242,6 +221,7 @@ export async function resolveLoadersWithRevalidation<TEnv>(
|
|
|
242
221
|
entry,
|
|
243
222
|
segmentId,
|
|
244
223
|
ctx.pathname,
|
|
224
|
+
errorContext,
|
|
245
225
|
),
|
|
246
226
|
belongsToRoute,
|
|
247
227
|
}),
|
|
@@ -404,6 +384,97 @@ export function buildEntryRevalidateMap(
|
|
|
404
384
|
return map;
|
|
405
385
|
}
|
|
406
386
|
|
|
387
|
+
/**
|
|
388
|
+
* Resolve the component for a single parallel slot on the revalidation path.
|
|
389
|
+
* Pure component resolution shared verbatim by
|
|
390
|
+
* resolveParallelSegmentsWithRevalidation and the orphan-inlined loop in
|
|
391
|
+
* resolveOrphanLayoutWithRevalidation: try the static slot cache, else run the
|
|
392
|
+
* slot handler (pinning _currentSegmentId to the slot id so handle pushes land
|
|
393
|
+
* in the slot's own bucket, and wrapping a streamed handler). Returns the
|
|
394
|
+
* resolved component and whether the handler actually ran. Does NOT touch the
|
|
395
|
+
* revalidate-default policy (the caller decides shouldResolve, including the
|
|
396
|
+
* orphan-vs-main defaultOverride divergence) or loader-resolution ordering.
|
|
397
|
+
*/
|
|
398
|
+
async function resolveParallelSlotComponent<TEnv>(args: {
|
|
399
|
+
shouldResolve: boolean;
|
|
400
|
+
parallelEntry: ParallelEntryData;
|
|
401
|
+
slot: string;
|
|
402
|
+
parallelId: string;
|
|
403
|
+
handler:
|
|
404
|
+
| ((ctx: HandlerContext<any, TEnv>) => ReactNode | Promise<ReactNode>)
|
|
405
|
+
| ReactNode
|
|
406
|
+
| undefined;
|
|
407
|
+
context: HandlerContext<any, TEnv>;
|
|
408
|
+
deps: SegmentResolutionDeps<TEnv>;
|
|
409
|
+
routeKey: string;
|
|
410
|
+
params: Record<string, string>;
|
|
411
|
+
}): Promise<{ component: ReactNode | undefined; handlerRan: boolean }> {
|
|
412
|
+
const {
|
|
413
|
+
shouldResolve,
|
|
414
|
+
parallelEntry,
|
|
415
|
+
slot,
|
|
416
|
+
parallelId,
|
|
417
|
+
handler,
|
|
418
|
+
context,
|
|
419
|
+
deps,
|
|
420
|
+
routeKey,
|
|
421
|
+
params,
|
|
422
|
+
} = args;
|
|
423
|
+
|
|
424
|
+
let component: ReactNode | undefined;
|
|
425
|
+
let handlerRan = false;
|
|
426
|
+
if (shouldResolve) {
|
|
427
|
+
component = await tryStaticSlot(parallelEntry, slot, parallelId);
|
|
428
|
+
// tryStaticSlot returning a value means the static cache supplied the
|
|
429
|
+
// component — handler did NOT run. handlerRan stays false.
|
|
430
|
+
}
|
|
431
|
+
if (component === undefined) {
|
|
432
|
+
const hasLoadingFallback =
|
|
433
|
+
parallelEntry.loading !== undefined && parallelEntry.loading !== false;
|
|
434
|
+
if (!shouldResolve) {
|
|
435
|
+
component = null;
|
|
436
|
+
} else if (handler === undefined) {
|
|
437
|
+
// Handler evicted (production static slot) but static lookup missed.
|
|
438
|
+
// Nothing to render — use null so the client keeps its cached version.
|
|
439
|
+
component = null;
|
|
440
|
+
} else {
|
|
441
|
+
// Slot-keyed pushes — slot owns its own bucket, parent layout owns its
|
|
442
|
+
// own. On slot-only revalidations the partial merge updates only the
|
|
443
|
+
// slot's bucket; the parent's bucket stays intact.
|
|
444
|
+
(context as InternalHandlerContext<any, TEnv>)._currentSegmentId =
|
|
445
|
+
parallelId;
|
|
446
|
+
handlerRan = true;
|
|
447
|
+
if (hasLoadingFallback) {
|
|
448
|
+
const result =
|
|
449
|
+
typeof handler === "function" ? handler(context) : handler;
|
|
450
|
+
if (result instanceof Promise) {
|
|
451
|
+
warnOnStreamedResponse(result, parallelId);
|
|
452
|
+
const tracked = deps.trackHandler(result, {
|
|
453
|
+
segmentId: parallelId,
|
|
454
|
+
segmentType: "parallel",
|
|
455
|
+
});
|
|
456
|
+
observeStreamedHandler(
|
|
457
|
+
tracked,
|
|
458
|
+
parallelId,
|
|
459
|
+
"parallel",
|
|
460
|
+
context.pathname,
|
|
461
|
+
routeKey,
|
|
462
|
+
params,
|
|
463
|
+
);
|
|
464
|
+
component = tracked as ReactNode;
|
|
465
|
+
} else {
|
|
466
|
+
component = result as ReactNode;
|
|
467
|
+
}
|
|
468
|
+
} else {
|
|
469
|
+
component =
|
|
470
|
+
typeof handler === "function" ? await handler(context) : handler;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return { component, handlerRan };
|
|
476
|
+
}
|
|
477
|
+
|
|
407
478
|
/**
|
|
408
479
|
* Resolve parallel segments with revalidation.
|
|
409
480
|
*/
|
|
@@ -421,9 +492,30 @@ export async function resolveParallelSegmentsWithRevalidation<TEnv>(
|
|
|
421
492
|
deps: SegmentResolutionDeps<TEnv>,
|
|
422
493
|
actionContext?: ActionContext,
|
|
423
494
|
stale?: boolean,
|
|
495
|
+
options?: {
|
|
496
|
+
/**
|
|
497
|
+
* Seed for an unknown parent-chain slot (slot not in clientSegmentIds) when
|
|
498
|
+
* there are no deciding revalidate fns. "type-derived" (default, main path):
|
|
499
|
+
* `belongsToRoute || isNewParent`. "force-render" (orphan path): always
|
|
500
|
+
* `true` — orphan parallels always belong to the route and must render
|
|
501
|
+
* unless the user opts out via revalidate(); the #482 blank-parent-chain-
|
|
502
|
+
* slot guard.
|
|
503
|
+
*/
|
|
504
|
+
parentChainDefault?: "type-derived" | "force-render";
|
|
505
|
+
/**
|
|
506
|
+
* When a slot's loaders are resolved relative to the slot segment push.
|
|
507
|
+
* "after" (default, main path) pushes the slot segment first; "before"
|
|
508
|
+
* (orphan path) resolves loaders first. This only changes the
|
|
509
|
+
* segments/matchedIds emission ORDER (the client reconciler is insensitive
|
|
510
|
+
* to it: loader sub-ids are filtered out and slots are re-grouped by parent).
|
|
511
|
+
*/
|
|
512
|
+
loaderOrder?: "after" | "before";
|
|
513
|
+
},
|
|
424
514
|
): Promise<SegmentRevalidationResult> {
|
|
425
515
|
const segments: ResolvedSegment[] = [];
|
|
426
516
|
const matchedIds: string[] = [];
|
|
517
|
+
const parentChainDefault = options?.parentChainDefault ?? "type-derived";
|
|
518
|
+
const loaderOrder = options?.loaderOrder ?? "after";
|
|
427
519
|
|
|
428
520
|
const resolvedParallelEntries = new Set<string>();
|
|
429
521
|
for (const { slot, entry: parallelEntry } of getParallelSlotEntries(
|
|
@@ -448,44 +540,61 @@ export async function resolveParallelSegmentsWithRevalidation<TEnv>(
|
|
|
448
540
|
|
|
449
541
|
const isFullRefetch = clientSegmentIds.size === 0;
|
|
450
542
|
const isNewParent = !clientSegmentIds.has(entry.shortCode);
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
543
|
+
|
|
544
|
+
// A slot's loaders (never cached) are deduped per parallel entry and
|
|
545
|
+
// emitted either before or after the slot segment per loaderOrder.
|
|
546
|
+
const resolveSlotLoaders = async () => {
|
|
547
|
+
if (resolvedParallelEntries.has(parallelEntry.id)) return;
|
|
548
|
+
const loaderResult = await resolveLoadersWithRevalidation(
|
|
549
|
+
parallelEntry,
|
|
550
|
+
context,
|
|
551
|
+
belongsToRoute,
|
|
552
|
+
clientSegmentIds,
|
|
553
|
+
prevParams,
|
|
554
|
+
request,
|
|
555
|
+
prevUrl,
|
|
556
|
+
nextUrl,
|
|
557
|
+
routeKey,
|
|
558
|
+
deps,
|
|
559
|
+
actionContext,
|
|
560
|
+
entry.shortCode,
|
|
561
|
+
stale,
|
|
562
|
+
);
|
|
563
|
+
segments.push(...loaderResult.segments);
|
|
564
|
+
matchedIds.push(...loaderResult.matchedIds);
|
|
565
|
+
resolvedParallelEntries.add(parallelEntry.id);
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
if (loaderOrder === "before") {
|
|
569
|
+
await resolveSlotLoaders();
|
|
458
570
|
}
|
|
571
|
+
// Always announce the slot in matchedIds — it's unconditionally appended
|
|
572
|
+
// to `segments` below, and a segment present in segments but missing from
|
|
573
|
+
// matched lets the client prune it (then it's missing from clientSegmentIds
|
|
574
|
+
// on the next request, perpetuating the staleness).
|
|
575
|
+
matchedIds.push(parallelId);
|
|
459
576
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
return true;
|
|
474
|
-
}
|
|
577
|
+
let shouldResolve: boolean;
|
|
578
|
+
if (isFullRefetch) {
|
|
579
|
+
// Client has nothing cached — slot MUST render. User revalidate fns are
|
|
580
|
+
// bypassed here because returning false would leave the segment blank
|
|
581
|
+
// with no client-side fallback.
|
|
582
|
+
traceFullRefetchedParallelSlot(parallelId, belongsToRoute);
|
|
583
|
+
shouldResolve = true;
|
|
584
|
+
} else {
|
|
585
|
+
// For non-empty client sets, consult user revalidate fns. When the slot
|
|
586
|
+
// is unknown to the client, override the type-derived default so the
|
|
587
|
+
// soft chain seeds with the right "new segment" / "parent-chain" value.
|
|
588
|
+
let defaultOverride: { value: boolean; reason: string } | undefined;
|
|
475
589
|
if (!clientSegmentIds.has(parallelId)) {
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
finalShouldRevalidate: result,
|
|
485
|
-
reason: result ? "new-segment" : "skip-parent-chain",
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
return result;
|
|
590
|
+
const value =
|
|
591
|
+
parentChainDefault === "force-render"
|
|
592
|
+
? true
|
|
593
|
+
: belongsToRoute || isNewParent;
|
|
594
|
+
defaultOverride = {
|
|
595
|
+
value,
|
|
596
|
+
reason: value ? "new-segment" : "skip-parent-chain",
|
|
597
|
+
};
|
|
489
598
|
}
|
|
490
599
|
|
|
491
600
|
const dummySegment: ResolvedSegment = {
|
|
@@ -503,7 +612,7 @@ export async function resolveParallelSegmentsWithRevalidation<TEnv>(
|
|
|
503
612
|
: {}),
|
|
504
613
|
};
|
|
505
614
|
|
|
506
|
-
|
|
615
|
+
shouldResolve = await evaluateRevalidation({
|
|
507
616
|
segment: dummySegment,
|
|
508
617
|
prevParams,
|
|
509
618
|
getPrevSegment: null,
|
|
@@ -519,8 +628,9 @@ export async function resolveParallelSegmentsWithRevalidation<TEnv>(
|
|
|
519
628
|
actionContext,
|
|
520
629
|
stale,
|
|
521
630
|
traceSource: "parallel",
|
|
631
|
+
defaultOverride,
|
|
522
632
|
});
|
|
523
|
-
}
|
|
633
|
+
}
|
|
524
634
|
emitRevalidationDecision(
|
|
525
635
|
parallelId,
|
|
526
636
|
context.pathname,
|
|
@@ -528,44 +638,17 @@ export async function resolveParallelSegmentsWithRevalidation<TEnv>(
|
|
|
528
638
|
shouldResolve,
|
|
529
639
|
);
|
|
530
640
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
// Nothing to render — use null so the client keeps its cached version.
|
|
543
|
-
component = null;
|
|
544
|
-
} else if (hasLoadingFallback) {
|
|
545
|
-
const result =
|
|
546
|
-
typeof handler === "function" ? handler(context) : handler;
|
|
547
|
-
if (result instanceof Promise) {
|
|
548
|
-
const tracked = deps.trackHandler(result, {
|
|
549
|
-
segmentId: parallelId,
|
|
550
|
-
segmentType: "parallel",
|
|
551
|
-
});
|
|
552
|
-
observeStreamedHandler(
|
|
553
|
-
tracked,
|
|
554
|
-
parallelId,
|
|
555
|
-
"parallel",
|
|
556
|
-
context.pathname,
|
|
557
|
-
routeKey,
|
|
558
|
-
params,
|
|
559
|
-
);
|
|
560
|
-
component = tracked as ReactNode;
|
|
561
|
-
} else {
|
|
562
|
-
component = result as ReactNode;
|
|
563
|
-
}
|
|
564
|
-
} else {
|
|
565
|
-
component =
|
|
566
|
-
typeof handler === "function" ? await handler(context) : handler;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
641
|
+
const { component, handlerRan } = await resolveParallelSlotComponent({
|
|
642
|
+
shouldResolve,
|
|
643
|
+
parallelEntry,
|
|
644
|
+
slot,
|
|
645
|
+
parallelId,
|
|
646
|
+
handler,
|
|
647
|
+
context,
|
|
648
|
+
deps,
|
|
649
|
+
routeKey,
|
|
650
|
+
params,
|
|
651
|
+
});
|
|
569
652
|
|
|
570
653
|
segments.push({
|
|
571
654
|
id: parallelId,
|
|
@@ -574,9 +657,14 @@ export async function resolveParallelSegmentsWithRevalidation<TEnv>(
|
|
|
574
657
|
index: 0,
|
|
575
658
|
component,
|
|
576
659
|
loading: parallelEntry.loading === false ? null : parallelEntry.loading,
|
|
577
|
-
transition:
|
|
660
|
+
transition: applyViewTransitionDefault(
|
|
661
|
+
parallelEntry.transition,
|
|
662
|
+
deps.viewTransitionDefault,
|
|
663
|
+
parallelId,
|
|
664
|
+
),
|
|
578
665
|
params,
|
|
579
666
|
slot,
|
|
667
|
+
_handlerRan: handlerRan,
|
|
580
668
|
belongsToRoute,
|
|
581
669
|
parallelName: `${parallelEntry.id}.${slot}`,
|
|
582
670
|
...(parallelEntry.mountPath
|
|
@@ -584,28 +672,9 @@ export async function resolveParallelSegmentsWithRevalidation<TEnv>(
|
|
|
584
672
|
: {}),
|
|
585
673
|
});
|
|
586
674
|
|
|
587
|
-
if (
|
|
588
|
-
|
|
675
|
+
if (loaderOrder === "after") {
|
|
676
|
+
await resolveSlotLoaders();
|
|
589
677
|
}
|
|
590
|
-
|
|
591
|
-
const loaderResult = await resolveLoadersWithRevalidation(
|
|
592
|
-
parallelEntry,
|
|
593
|
-
context,
|
|
594
|
-
belongsToRoute,
|
|
595
|
-
clientSegmentIds,
|
|
596
|
-
prevParams,
|
|
597
|
-
request,
|
|
598
|
-
prevUrl,
|
|
599
|
-
nextUrl,
|
|
600
|
-
routeKey,
|
|
601
|
-
deps,
|
|
602
|
-
actionContext,
|
|
603
|
-
entry.shortCode,
|
|
604
|
-
stale,
|
|
605
|
-
);
|
|
606
|
-
segments.push(...loaderResult.segments);
|
|
607
|
-
matchedIds.push(...loaderResult.matchedIds);
|
|
608
|
-
resolvedParallelEntries.add(parallelEntry.id);
|
|
609
678
|
}
|
|
610
679
|
|
|
611
680
|
return { segments, matchedIds };
|
|
@@ -631,6 +700,7 @@ export async function resolveEntryHandlerWithRevalidation<TEnv>(
|
|
|
631
700
|
): Promise<{ segment: ResolvedSegment; matchedId: string }> {
|
|
632
701
|
const matchedId = entry.shortCode;
|
|
633
702
|
|
|
703
|
+
let handlerRan = false;
|
|
634
704
|
const component = await revalidate(
|
|
635
705
|
async () => {
|
|
636
706
|
const hasSegment = clientSegmentIds.has(entry.shortCode);
|
|
@@ -707,6 +777,7 @@ export async function resolveEntryHandlerWithRevalidation<TEnv>(
|
|
|
707
777
|
return shouldRevalidate;
|
|
708
778
|
},
|
|
709
779
|
async () => {
|
|
780
|
+
handlerRan = true;
|
|
710
781
|
const doneHandler = track(`handler:${entry.id}`, 2);
|
|
711
782
|
(context as InternalHandlerContext<any, TEnv>)._currentSegmentId =
|
|
712
783
|
entry.shortCode;
|
|
@@ -729,13 +800,18 @@ export async function resolveEntryHandlerWithRevalidation<TEnv>(
|
|
|
729
800
|
? routeEntry.liveHandler
|
|
730
801
|
: routeEntry.handler;
|
|
731
802
|
if (!routeEntry.loading) {
|
|
732
|
-
const result = handleHandlerResult(
|
|
803
|
+
const result = handleHandlerResult(
|
|
804
|
+
await observeHandler(entry.id, handler, context),
|
|
805
|
+
);
|
|
733
806
|
doneHandler();
|
|
734
807
|
return result;
|
|
735
808
|
}
|
|
736
809
|
if (!actionContext) {
|
|
737
|
-
const result = handleHandlerResult(
|
|
810
|
+
const result = handleHandlerResult(
|
|
811
|
+
observeHandler(entry.id, handler, context),
|
|
812
|
+
);
|
|
738
813
|
if (result instanceof Promise) {
|
|
814
|
+
warnOnStreamedResponse(result, routeEntry.id);
|
|
739
815
|
result.finally(doneHandler).catch(() => {});
|
|
740
816
|
const tracked = deps.trackHandler(result, {
|
|
741
817
|
segmentId: entry.shortCode,
|
|
@@ -757,7 +833,9 @@ export async function resolveEntryHandlerWithRevalidation<TEnv>(
|
|
|
757
833
|
debugLog("segment.action", "resolving action route with awaited value", {
|
|
758
834
|
entryId: entry.id,
|
|
759
835
|
});
|
|
760
|
-
const actionResult = handleHandlerResult(
|
|
836
|
+
const actionResult = handleHandlerResult(
|
|
837
|
+
await observeHandler(entry.id, handler, context),
|
|
838
|
+
);
|
|
761
839
|
doneHandler();
|
|
762
840
|
return {
|
|
763
841
|
content: Promise.resolve(actionResult),
|
|
@@ -781,13 +859,18 @@ export async function resolveEntryHandlerWithRevalidation<TEnv>(
|
|
|
781
859
|
index: 0,
|
|
782
860
|
component: resolvedComponent,
|
|
783
861
|
loading: entry.loading === false ? null : entry.loading,
|
|
784
|
-
transition:
|
|
862
|
+
transition: applyViewTransitionDefault(
|
|
863
|
+
entry.transition,
|
|
864
|
+
deps.viewTransitionDefault,
|
|
865
|
+
entry.shortCode,
|
|
866
|
+
),
|
|
785
867
|
params,
|
|
786
868
|
belongsToRoute,
|
|
787
869
|
...(entry.type === "layout" || entry.type === "cache"
|
|
788
870
|
? { layoutName: entry.id }
|
|
789
871
|
: {}),
|
|
790
872
|
...(entry.mountPath ? { mountPath: entry.mountPath } : {}),
|
|
873
|
+
_handlerRan: handlerRan,
|
|
791
874
|
};
|
|
792
875
|
|
|
793
876
|
return { segment, matchedId };
|
|
@@ -806,7 +889,6 @@ export async function resolveSegmentWithRevalidation<TEnv>(
|
|
|
806
889
|
request: Request,
|
|
807
890
|
prevUrl: URL,
|
|
808
891
|
nextUrl: URL,
|
|
809
|
-
loaderPromises: Map<string, Promise<any>>,
|
|
810
892
|
deps: SegmentResolutionDeps<TEnv>,
|
|
811
893
|
actionContext?: ActionContext,
|
|
812
894
|
stale?: boolean,
|
|
@@ -868,7 +950,6 @@ export async function resolveSegmentWithRevalidation<TEnv>(
|
|
|
868
950
|
prevUrl,
|
|
869
951
|
nextUrl,
|
|
870
952
|
routeKey,
|
|
871
|
-
loaderPromises,
|
|
872
953
|
true,
|
|
873
954
|
deps,
|
|
874
955
|
actionContext,
|
|
@@ -953,7 +1034,6 @@ export async function resolveSegmentWithRevalidation<TEnv>(
|
|
|
953
1034
|
prevUrl,
|
|
954
1035
|
nextUrl,
|
|
955
1036
|
routeKey,
|
|
956
|
-
loaderPromises,
|
|
957
1037
|
false,
|
|
958
1038
|
deps,
|
|
959
1039
|
actionContext,
|
|
@@ -980,7 +1060,6 @@ export async function resolveOrphanLayoutWithRevalidation<TEnv>(
|
|
|
980
1060
|
prevUrl: URL,
|
|
981
1061
|
nextUrl: URL,
|
|
982
1062
|
routeKey: string,
|
|
983
|
-
loaderPromises: Map<string, Promise<any>>,
|
|
984
1063
|
belongsToRoute: boolean,
|
|
985
1064
|
deps: SegmentResolutionDeps<TEnv>,
|
|
986
1065
|
actionContext?: ActionContext,
|
|
@@ -1117,166 +1196,41 @@ export async function resolveOrphanLayoutWithRevalidation<TEnv>(
|
|
|
1117
1196
|
belongsToRoute,
|
|
1118
1197
|
layoutName: orphan.id,
|
|
1119
1198
|
loading: orphan.loading === false ? null : orphan.loading,
|
|
1120
|
-
transition:
|
|
1199
|
+
transition: applyViewTransitionDefault(
|
|
1200
|
+
orphan.transition,
|
|
1201
|
+
deps.viewTransitionDefault,
|
|
1202
|
+
orphan.shortCode,
|
|
1203
|
+
),
|
|
1121
1204
|
...(orphan.mountPath ? { mountPath: orphan.mountPath } : {}),
|
|
1122
1205
|
});
|
|
1123
1206
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
)
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
matchedIds.push(...loaderResult.matchedIds);
|
|
1152
|
-
resolvedParallelEntries.add(parallelEntry.id);
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
|
-
const slots = parallelEntry.handler as Record<
|
|
1156
|
-
`@${string}`,
|
|
1157
|
-
| ((ctx: HandlerContext<any, TEnv>) => ReactNode | Promise<ReactNode>)
|
|
1158
|
-
| ReactNode
|
|
1159
|
-
>;
|
|
1160
|
-
// Handler may be undefined in production after static handler eviction.
|
|
1161
|
-
const handler = slots[slot];
|
|
1162
|
-
|
|
1163
|
-
// Use orphan.shortCode (the parent layout) to match the SSR path
|
|
1164
|
-
// (resolveParallelEntry receives parentShortCode = orphan.shortCode).
|
|
1165
|
-
// Using parallelEntry.shortCode would generate IDs the client doesn't know about.
|
|
1166
|
-
const parallelId = `${orphan.shortCode}.${slot}`;
|
|
1167
|
-
matchedIds.push(parallelId);
|
|
1168
|
-
|
|
1169
|
-
const shouldResolve = await (async () => {
|
|
1170
|
-
if (!clientSegmentIds.has(parallelId)) {
|
|
1171
|
-
if (isTraceActive()) {
|
|
1172
|
-
pushRevalidationTraceEntry({
|
|
1173
|
-
segmentId: parallelId,
|
|
1174
|
-
segmentType: "parallel",
|
|
1175
|
-
belongsToRoute,
|
|
1176
|
-
source: "parallel",
|
|
1177
|
-
defaultShouldRevalidate: true,
|
|
1178
|
-
finalShouldRevalidate: true,
|
|
1179
|
-
reason: "new-segment",
|
|
1180
|
-
});
|
|
1181
|
-
}
|
|
1182
|
-
return true;
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
const dummySegment: ResolvedSegment = {
|
|
1186
|
-
id: parallelId,
|
|
1187
|
-
namespace: parallelEntry.id,
|
|
1188
|
-
type: "parallel",
|
|
1189
|
-
index: 0,
|
|
1190
|
-
component: null as any,
|
|
1191
|
-
params,
|
|
1192
|
-
slot,
|
|
1193
|
-
belongsToRoute,
|
|
1194
|
-
parallelName: `${parallelEntry.id}.${slot}`,
|
|
1195
|
-
...(parallelEntry.mountPath
|
|
1196
|
-
? { mountPath: parallelEntry.mountPath }
|
|
1197
|
-
: {}),
|
|
1198
|
-
};
|
|
1199
|
-
|
|
1200
|
-
return await evaluateRevalidation({
|
|
1201
|
-
segment: dummySegment,
|
|
1202
|
-
prevParams,
|
|
1203
|
-
getPrevSegment: null,
|
|
1204
|
-
request,
|
|
1205
|
-
prevUrl,
|
|
1206
|
-
nextUrl,
|
|
1207
|
-
revalidations: parallelEntry.revalidate.map((fn, i) => ({
|
|
1208
|
-
name: `revalidate${i}`,
|
|
1209
|
-
fn,
|
|
1210
|
-
})),
|
|
1211
|
-
routeKey,
|
|
1212
|
-
context,
|
|
1213
|
-
actionContext,
|
|
1214
|
-
stale,
|
|
1215
|
-
traceSource: "parallel",
|
|
1216
|
-
});
|
|
1217
|
-
})();
|
|
1218
|
-
emitRevalidationDecision(
|
|
1219
|
-
parallelId,
|
|
1220
|
-
context.pathname,
|
|
1221
|
-
routeKey,
|
|
1222
|
-
shouldResolve,
|
|
1223
|
-
);
|
|
1224
|
-
|
|
1225
|
-
let component: ReactNode | undefined;
|
|
1226
|
-
if (shouldResolve) {
|
|
1227
|
-
component = await tryStaticSlot(parallelEntry, slot, parallelId);
|
|
1228
|
-
}
|
|
1229
|
-
if (component === undefined) {
|
|
1230
|
-
const hasLoadingFallback =
|
|
1231
|
-
parallelEntry.loading !== undefined && parallelEntry.loading !== false;
|
|
1232
|
-
if (!shouldResolve) {
|
|
1233
|
-
component = null;
|
|
1234
|
-
} else if (handler === undefined) {
|
|
1235
|
-
// Handler evicted (production static slot) but static lookup missed.
|
|
1236
|
-
component = null;
|
|
1237
|
-
} else if (hasLoadingFallback) {
|
|
1238
|
-
const result =
|
|
1239
|
-
typeof handler === "function" ? handler(context) : handler;
|
|
1240
|
-
if (result instanceof Promise) {
|
|
1241
|
-
const tracked = deps.trackHandler(result, {
|
|
1242
|
-
segmentId: parallelId,
|
|
1243
|
-
segmentType: "parallel",
|
|
1244
|
-
});
|
|
1245
|
-
observeStreamedHandler(
|
|
1246
|
-
tracked,
|
|
1247
|
-
parallelId,
|
|
1248
|
-
"parallel",
|
|
1249
|
-
context.pathname,
|
|
1250
|
-
routeKey,
|
|
1251
|
-
params,
|
|
1252
|
-
);
|
|
1253
|
-
component = tracked as ReactNode;
|
|
1254
|
-
} else {
|
|
1255
|
-
component = result as ReactNode;
|
|
1256
|
-
}
|
|
1257
|
-
} else {
|
|
1258
|
-
component =
|
|
1259
|
-
typeof handler === "function" ? await handler(context) : handler;
|
|
1260
|
-
}
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
segments.push({
|
|
1264
|
-
id: parallelId,
|
|
1265
|
-
namespace: parallelEntry.id,
|
|
1266
|
-
type: "parallel",
|
|
1267
|
-
index: 0,
|
|
1268
|
-
component,
|
|
1269
|
-
loading: parallelEntry.loading === false ? null : parallelEntry.loading,
|
|
1270
|
-
transition: parallelEntry.transition,
|
|
1271
|
-
params,
|
|
1272
|
-
slot,
|
|
1273
|
-
belongsToRoute,
|
|
1274
|
-
parallelName: `${parallelEntry.id}.${slot}`,
|
|
1275
|
-
...(parallelEntry.mountPath
|
|
1276
|
-
? { mountPath: parallelEntry.mountPath }
|
|
1277
|
-
: {}),
|
|
1278
|
-
});
|
|
1279
|
-
}
|
|
1207
|
+
// Resolve the orphan layout's parallel slots through the shared main-path
|
|
1208
|
+
// helper. The orphan policy is carried by explicit args, byte-for-byte:
|
|
1209
|
+
// - parentChainDefault "force-render": an unknown parent-chain slot seeds
|
|
1210
|
+
// `true` (orphan parallels always belong to the route — the #482 guard),
|
|
1211
|
+
// where the main path would seed `belongsToRoute || isNewParent`.
|
|
1212
|
+
// - loaderOrder "before": a slot's loaders are emitted before the slot
|
|
1213
|
+
// segment, matching the prior inlined order.
|
|
1214
|
+
// `entry.shortCode` inside the helper is `orphan.shortCode` (orphan is passed
|
|
1215
|
+
// as `entry`), so the parallel ids + loader shortCodeOverride are unchanged.
|
|
1216
|
+
const parallelResult = await resolveParallelSegmentsWithRevalidation(
|
|
1217
|
+
orphan,
|
|
1218
|
+
params,
|
|
1219
|
+
context,
|
|
1220
|
+
belongsToRoute,
|
|
1221
|
+
clientSegmentIds,
|
|
1222
|
+
prevParams,
|
|
1223
|
+
request,
|
|
1224
|
+
prevUrl,
|
|
1225
|
+
nextUrl,
|
|
1226
|
+
routeKey,
|
|
1227
|
+
deps,
|
|
1228
|
+
actionContext,
|
|
1229
|
+
stale,
|
|
1230
|
+
{ parentChainDefault: "force-render", loaderOrder: "before" },
|
|
1231
|
+
);
|
|
1232
|
+
segments.push(...parallelResult.segments);
|
|
1233
|
+
matchedIds.push(...parallelResult.matchedIds);
|
|
1280
1234
|
|
|
1281
1235
|
return { segments, matchedIds };
|
|
1282
1236
|
}
|
|
@@ -1294,7 +1248,6 @@ export async function resolveAllSegmentsWithRevalidation<TEnv>(
|
|
|
1294
1248
|
request: Request,
|
|
1295
1249
|
prevUrl: URL,
|
|
1296
1250
|
nextUrl: URL,
|
|
1297
|
-
loaderPromises: Map<string, Promise<any>>,
|
|
1298
1251
|
actionContext: ActionContext | undefined,
|
|
1299
1252
|
interceptResult: { intercept: any; entry: EntryData } | null,
|
|
1300
1253
|
localRouteName: string,
|
|
@@ -1328,7 +1281,7 @@ export async function resolveAllSegmentsWithRevalidation<TEnv>(
|
|
|
1328
1281
|
|
|
1329
1282
|
const nonParallelEntry = entry as Exclude<EntryData, { type: "parallel" }>;
|
|
1330
1283
|
if (entry.type === "cache") {
|
|
1331
|
-
const store =
|
|
1284
|
+
const store = RangoContext.getStore();
|
|
1332
1285
|
if (store) store.insideCacheScope = true;
|
|
1333
1286
|
}
|
|
1334
1287
|
const doneEntry = track(`segment:${entry.id}`, 1);
|
|
@@ -1346,7 +1299,6 @@ export async function resolveAllSegmentsWithRevalidation<TEnv>(
|
|
|
1346
1299
|
request,
|
|
1347
1300
|
prevUrl,
|
|
1348
1301
|
nextUrl,
|
|
1349
|
-
loaderPromises,
|
|
1350
1302
|
deps,
|
|
1351
1303
|
actionContext,
|
|
1352
1304
|
stale,
|