@rangojs/router 0.0.0-experimental.79 → 0.0.0-experimental.7c7e4327
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 -4
- package/README.md +301 -797
- package/dist/bin/rango.js +603 -145
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3750 -1160
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +96 -24
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +85 -6
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +228 -33
- package/skills/caching/SKILL.md +336 -19
- package/skills/catalog.json +271 -0
- package/skills/comparison/SKILL.md +50 -0
- package/skills/comparison/agents/openai.yaml +4 -0
- package/skills/comparison/references/framework-comparison.md +837 -0
- package/skills/composability/SKILL.md +110 -4
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +5 -3
- package/skills/defer-hydration/SKILL.md +235 -0
- package/skills/document-cache/SKILL.md +87 -56
- package/skills/fonts/SKILL.md +1 -1
- package/skills/handler-use/SKILL.md +12 -10
- package/skills/hooks/SKILL.md +73 -691
- package/skills/hooks/data.md +273 -0
- package/skills/hooks/handle-and-actions.md +103 -0
- package/skills/hooks/navigation.md +110 -0
- package/skills/hooks/outlets.md +41 -0
- package/skills/hooks/state.md +228 -0
- package/skills/hooks/urls.md +135 -0
- package/skills/host-router/SKILL.md +129 -27
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +75 -19
- package/skills/layout/SKILL.md +40 -19
- package/skills/links/SKILL.md +247 -17
- package/skills/loader/SKILL.md +248 -10
- package/skills/middleware/SKILL.md +25 -13
- package/skills/migrate-nextjs/SKILL.md +205 -20
- package/skills/migrate-react-router/SKILL.md +59 -670
- package/skills/migrate-react-router/cloudflare-workers.md +129 -0
- package/skills/migrate-react-router/component-migration.md +196 -0
- package/skills/migrate-react-router/data-and-actions.md +225 -0
- package/skills/migrate-react-router/route-mapping.md +271 -0
- package/skills/mime-routes/SKILL.md +29 -2
- package/skills/observability/SKILL.md +202 -0
- package/skills/parallel/SKILL.md +40 -10
- package/skills/ppr/SKILL.md +616 -0
- package/skills/prerender/SKILL.md +72 -60
- package/skills/rango/SKILL.md +318 -26
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +138 -49
- package/skills/route/SKILL.md +117 -9
- package/skills/router-setup/SKILL.md +44 -9
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +776 -0
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +28 -4
- 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 +131 -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 +85 -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/theme/SKILL.md +1 -1
- package/skills/typesafety/SKILL.md +45 -626
- package/skills/typesafety/env-and-bindings.md +254 -0
- package/skills/typesafety/generated-files-and-cli.md +335 -0
- package/skills/typesafety/params-and-search.md +153 -0
- package/skills/typesafety/route-types.md +209 -0
- package/skills/use-cache/SKILL.md +74 -15
- package/skills/vercel/SKILL.md +128 -0
- 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 +252 -158
- 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/logging.ts +28 -0
- package/src/browser/merge-segment-loaders.ts +6 -4
- package/src/browser/navigation-bridge.ts +94 -25
- package/src/browser/navigation-client.ts +144 -79
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +161 -73
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +183 -144
- package/src/browser/prefetch/cache.ts +242 -77
- package/src/browser/prefetch/fetch.ts +325 -69
- package/src/browser/prefetch/queue.ts +61 -12
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +58 -20
- package/src/browser/react/NavigationProvider.tsx +202 -120
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- 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 +32 -7
- 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 +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 +145 -28
- package/src/browser/scroll-restoration.ts +37 -22
- package/src/browser/segment-reconciler.ts +31 -21
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +236 -65
- package/src/browser/types.ts +102 -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 +203 -154
- package/src/build/generate-route-types.ts +3 -1
- package/src/build/index.ts +11 -3
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +152 -21
- 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 +456 -62
- 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 +128 -51
- 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 +13 -21
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +58 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +421 -58
- package/src/cache/cache-scope.ts +187 -96
- package/src/cache/cache-tag.ts +149 -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 +2202 -372
- 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 +126 -41
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +23 -20
- package/src/cache/memory-segment-store.ts +243 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +13 -21
- package/src/cache/shell-snapshot.ts +417 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +180 -99
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1127 -0
- package/src/client.rsc.tsx +41 -21
- package/src/client.tsx +33 -61
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +108 -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 +185 -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 +67 -37
- package/src/handles/MetaTags.tsx +24 -53
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +35 -8
- package/src/handles/deferred-resolution.ts +127 -0
- package/src/handles/is-thenable.ts +18 -0
- package/src/handles/meta.ts +14 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +13 -22
- package/src/host/index.ts +9 -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 +97 -12
- package/src/index.ts +98 -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 +78 -10
- package/src/redirect-origin.ts +114 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +62 -0
- package/src/reverse.ts +65 -39
- 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 +87 -59
- 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 +41 -20
- 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 +129 -30
- package/src/router/handler-context.ts +27 -42
- package/src/router/instrument.ts +355 -0
- package/src/router/intercept-resolution.ts +39 -20
- package/src/router/lazy-includes.ts +82 -59
- package/src/router/loader-resolution.ts +167 -72
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +74 -40
- package/src/router/match-api.ts +80 -55
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +211 -165
- 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 +69 -79
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +7 -134
- package/src/router/middleware.ts +298 -172
- package/src/router/navigation-snapshot.ts +7 -56
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +181 -150
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +112 -67
- package/src/router/preview-match.ts +6 -2
- package/src/router/request-classification.ts +50 -69
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +14 -3
- package/src/router/router-context.ts +6 -29
- package/src/router/router-interfaces.ts +115 -36
- package/src/router/router-options.ts +166 -5
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +131 -86
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +139 -39
- package/src/router/segment-resolution/loader-mask.ts +67 -0
- package/src/router/segment-resolution/loader-snapshot.ts +251 -0
- 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 +75 -0
- package/src/router/telemetry-otel.ts +160 -200
- package/src/router/telemetry.ts +105 -20
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +215 -0
- package/src/router/trie-matching.ts +171 -59
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +57 -0
- package/src/router.ts +157 -71
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +291 -217
- package/src/rsc/helpers.ts +168 -46
- 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 +29 -42
- package/src/rsc/nonce.ts +10 -1
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +124 -13
- package/src/rsc/redirect-guard.ts +100 -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 +99 -189
- package/src/rsc/rsc-rendering.ts +421 -76
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +282 -116
- package/src/rsc/shell-capture.ts +1158 -0
- package/src/rsc/shell-serve.ts +150 -0
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +53 -5
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- package/src/segment-loader-promise.ts +49 -4
- package/src/segment-system.tsx +350 -149
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +208 -51
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +152 -5
- package/src/server/handle-store.ts +21 -38
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +395 -176
- package/src/ssr/index.tsx +458 -178
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +10 -13
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +46 -0
- package/src/testing/dispatch.ts +813 -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 +199 -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 +584 -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 +56 -84
- 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 +20 -52
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +135 -14
- package/src/urls/include-helper.ts +19 -64
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +2 -11
- package/src/urls/path-helper-types.ts +63 -17
- package/src/urls/path-helper.ts +22 -106
- package/src/urls/pattern-types.ts +72 -19
- package/src/urls/response-types.ts +22 -29
- package/src/urls/type-extraction.ts +98 -154
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +292 -107
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +8 -7
- package/src/vite/discovery/dev-prerender-cache.ts +117 -0
- package/src/vite/discovery/discover-routers.ts +127 -86
- package/src/vite/discovery/discovery-errors.ts +255 -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 +45 -1
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +4 -0
- package/src/vite/inject-client-debug.ts +88 -0
- package/src/vite/plugin-types.ts +210 -10
- 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-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 +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/vercel-output.ts +384 -0
- 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 +138 -27
- package/src/vite/rango.ts +236 -138
- package/src/vite/router-discovery.ts +927 -136
- 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 +71 -43
- package/src/vite/utils/shared-utils.ts +142 -43
- 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
|
@@ -19,66 +19,29 @@ import type {
|
|
|
19
19
|
} from "../../types";
|
|
20
20
|
import type { SegmentResolutionDeps } from "../types.js";
|
|
21
21
|
import { resolveLoaderData } from "./loader-cache.js";
|
|
22
|
-
import {
|
|
23
|
-
|
|
22
|
+
import {
|
|
23
|
+
isShellCaptureActive,
|
|
24
|
+
entryLoadingMasksLoaders,
|
|
25
|
+
} from "./loader-mask.js";
|
|
24
26
|
import {
|
|
25
27
|
handleHandlerResult,
|
|
26
28
|
tryStaticHandler,
|
|
27
29
|
tryStaticSlot,
|
|
28
30
|
resolveLayoutComponent,
|
|
29
31
|
resolveWithErrorBoundary,
|
|
32
|
+
warnOnStreamedResponse,
|
|
33
|
+
buildLoaderErrorContext,
|
|
30
34
|
} from "./helpers.js";
|
|
35
|
+
import { applyViewTransitionDefault } from "./view-transition-default.js";
|
|
31
36
|
import { getRouterContext } from "../router-context.js";
|
|
32
|
-
import {
|
|
37
|
+
import { observeStreamedHandler } from "./streamed-handler-telemetry.js";
|
|
38
|
+
import { observeHandler } from "../instrument.js";
|
|
33
39
|
import {
|
|
34
40
|
track,
|
|
35
|
-
|
|
41
|
+
RangoContext,
|
|
36
42
|
runInsideLoaderScope,
|
|
37
43
|
} from "../../server/context.js";
|
|
38
44
|
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
// Streamed handler telemetry
|
|
41
|
-
// ---------------------------------------------------------------------------
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Attach a fire-and-forget rejection observer to a streamed handler promise.
|
|
45
|
-
* React catches the actual error via its error boundary; this only emits
|
|
46
|
-
* the handler.error telemetry event.
|
|
47
|
-
*/
|
|
48
|
-
function observeStreamedHandler(
|
|
49
|
-
promise: Promise<ReactNode>,
|
|
50
|
-
segmentId: string,
|
|
51
|
-
segmentType: string,
|
|
52
|
-
pathname?: string,
|
|
53
|
-
routeKey?: string,
|
|
54
|
-
params?: Record<string, string>,
|
|
55
|
-
): void {
|
|
56
|
-
let routerCtx;
|
|
57
|
-
try {
|
|
58
|
-
routerCtx = getRouterContext();
|
|
59
|
-
} catch {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
if (!routerCtx?.telemetry) return;
|
|
63
|
-
const sink = resolveSink(routerCtx.telemetry);
|
|
64
|
-
const reqId = routerCtx.requestId;
|
|
65
|
-
promise.catch((err: unknown) => {
|
|
66
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
67
|
-
safeEmit(sink, {
|
|
68
|
-
type: "handler.error",
|
|
69
|
-
timestamp: performance.now(),
|
|
70
|
-
requestId: reqId,
|
|
71
|
-
segmentId,
|
|
72
|
-
segmentType,
|
|
73
|
-
error: errorObj,
|
|
74
|
-
handledByBoundary: true,
|
|
75
|
-
pathname,
|
|
76
|
-
routeKey,
|
|
77
|
-
params,
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
45
|
// ---------------------------------------------------------------------------
|
|
83
46
|
// Fresh path (full match, no revalidation)
|
|
84
47
|
// ---------------------------------------------------------------------------
|
|
@@ -100,9 +63,33 @@ export async function resolveLoaders<TEnv>(
|
|
|
100
63
|
const shortCode = shortCodeOverride ?? entry.shortCode;
|
|
101
64
|
const hasLoading = "loading" in entry && entry.loading !== undefined;
|
|
102
65
|
const loadingDisabled = hasLoading && entry.loading === false;
|
|
103
|
-
const ms = _getRequestContext()?._metricsStore;
|
|
104
66
|
|
|
105
|
-
|
|
67
|
+
// Emit the streaming (non-awaiting) loader shape when loading is enabled OR
|
|
68
|
+
// during a PPR shell capture. In capture, LIVE-lane loaders are masked with
|
|
69
|
+
// never-resolving promises (loader-mask.ts); the loading-disabled branch below
|
|
70
|
+
// AWAITS the loader promises, which would hang the capture render's match()
|
|
71
|
+
// forever on those masked promises. Forcing the streaming shape lets match()
|
|
72
|
+
// complete so the prerender can postpone the loader subtrees as holes. The
|
|
73
|
+
// `!loadingDisabled` short-circuit keeps the ALS check off the hot path (only
|
|
74
|
+
// loading-disabled entries consult it), so normal requests are unchanged.
|
|
75
|
+
const emitStreaming = !loadingDisabled || isShellCaptureActive();
|
|
76
|
+
|
|
77
|
+
// PPR lane decision for this entry's loaders (loader-container-bake): an
|
|
78
|
+
// entry WITHOUT renderable loading() puts its loaders on the BAKE lane —
|
|
79
|
+
// executed at capture (container bakes, nested pending promises hole at the
|
|
80
|
+
// consumer's Suspense) and overlay-pinned from the shell snapshot on a HIT.
|
|
81
|
+
// Renderable loading() keeps the LIVE lane (masked at capture, always
|
|
82
|
+
// fresh). Computed per entry; resolveLoaderData applies the policy.
|
|
83
|
+
const bakeLane = !entryLoadingMasksLoaders(entry.loading);
|
|
84
|
+
|
|
85
|
+
// Error context for wrapLoaderPromise: without it, a throwing DSL loader never
|
|
86
|
+
// fires createRouter({ onError }) (phase "loader") nor emits the loader.error
|
|
87
|
+
// telemetry event — wrapLoaderPromise only builds the onError/telemetry path
|
|
88
|
+
// when errorContext is supplied. Built from ctx so the live render path reports
|
|
89
|
+
// loader failures the same way handlers/actions/routing/fetchable-loaders do.
|
|
90
|
+
const errorContext = buildLoaderErrorContext(ctx);
|
|
91
|
+
|
|
92
|
+
if (emitStreaming) {
|
|
106
93
|
// Streaming loaders: promises kick off now, settle during RSC serialization.
|
|
107
94
|
const segments = loaderEntries.map((loaderEntry, i) => {
|
|
108
95
|
const { loader } = loaderEntry;
|
|
@@ -117,11 +104,17 @@ export async function resolveLoaders<TEnv>(
|
|
|
117
104
|
loaderId: loader.$$id,
|
|
118
105
|
loaderData: deps.wrapLoaderPromise(
|
|
119
106
|
runInsideLoaderScope(() =>
|
|
120
|
-
resolveLoaderData(
|
|
107
|
+
resolveLoaderData(
|
|
108
|
+
loaderEntry,
|
|
109
|
+
ctx,
|
|
110
|
+
ctx.pathname,
|
|
111
|
+
bakeLane ? segmentId : null,
|
|
112
|
+
),
|
|
121
113
|
),
|
|
122
114
|
entry,
|
|
123
115
|
segmentId,
|
|
124
116
|
ctx.pathname,
|
|
117
|
+
errorContext,
|
|
125
118
|
),
|
|
126
119
|
belongsToRoute,
|
|
127
120
|
};
|
|
@@ -132,46 +125,51 @@ export async function resolveLoaders<TEnv>(
|
|
|
132
125
|
|
|
133
126
|
// Loading disabled: still start all loaders in parallel, but only emit
|
|
134
127
|
// settled promises so handlers don't stream loading placeholders.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
128
|
+
//
|
|
129
|
+
// Wrap each loader promise with wrapLoaderPromise BEFORE awaiting. The wrapped
|
|
130
|
+
// promise resolves to a LoaderDataResult and never rejects, routing a failed
|
|
131
|
+
// loader to its own per-loader error boundary. Awaiting the RAW promises here
|
|
132
|
+
// instead would (1) propagate a rejection to the segment-level boundary,
|
|
133
|
+
// collapsing the whole entry and discarding successful sibling data, and
|
|
134
|
+
// (2) leave the other in-flight raw promises without a .catch, producing
|
|
135
|
+
// unhandled rejections. Mirrors the loading path and intercept-resolution.
|
|
136
|
+
const pendingLoaderData = loaderEntries.map((loaderEntry, i) => {
|
|
137
|
+
const { loader } = loaderEntry;
|
|
138
|
+
const segmentId = `${shortCode}D${i}.${loader.$$id}`;
|
|
139
|
+
const wrapped = deps.wrapLoaderPromise(
|
|
140
|
+
runInsideLoaderScope(() =>
|
|
141
|
+
resolveLoaderData(
|
|
142
|
+
loaderEntry,
|
|
143
|
+
ctx,
|
|
144
|
+
ctx.pathname,
|
|
145
|
+
bakeLane ? segmentId : null,
|
|
146
|
+
),
|
|
147
|
+
),
|
|
148
|
+
entry,
|
|
149
|
+
segmentId,
|
|
150
|
+
ctx.pathname,
|
|
151
|
+
errorContext,
|
|
139
152
|
);
|
|
140
|
-
return {
|
|
153
|
+
return { wrapped, segmentId };
|
|
141
154
|
});
|
|
142
|
-
await Promise.all(pendingLoaderData.map((p) => p.
|
|
155
|
+
await Promise.all(pendingLoaderData.map((p) => p.wrapped));
|
|
143
156
|
|
|
144
157
|
return loaderEntries.map((loaderEntry, i) => {
|
|
145
158
|
const { loader } = loaderEntry;
|
|
146
|
-
const segmentId = `${shortCode}D${i}.${loader.$$id}`;
|
|
147
159
|
const pending = pendingLoaderData[i]!;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const batchEnd = performance.now();
|
|
153
|
-
appendMetric(
|
|
154
|
-
ms,
|
|
155
|
-
`loader:${loader.$$id}`,
|
|
156
|
-
pending.start,
|
|
157
|
-
batchEnd - pending.start,
|
|
158
|
-
2,
|
|
159
|
-
);
|
|
160
|
-
}
|
|
160
|
+
// The "loader:<id>" perf metric is recorded by observePhase at the single
|
|
161
|
+
// loader-metering site (useLoader, reached via ctx.use during
|
|
162
|
+
// resolveLoaderData), with the real per-loader duration rather than a
|
|
163
|
+
// Promise.all batch ceiling.
|
|
161
164
|
return {
|
|
162
|
-
id: segmentId,
|
|
165
|
+
id: pending.segmentId,
|
|
163
166
|
namespace: entry.id,
|
|
164
167
|
type: "loader" as const,
|
|
165
168
|
index: i,
|
|
166
169
|
component: null,
|
|
167
170
|
params: ctx.params,
|
|
168
171
|
loaderId: loader.$$id,
|
|
169
|
-
loaderData:
|
|
170
|
-
pending.promise,
|
|
171
|
-
entry,
|
|
172
|
-
segmentId,
|
|
173
|
-
ctx.pathname,
|
|
174
|
-
),
|
|
172
|
+
loaderData: pending.wrapped,
|
|
175
173
|
belongsToRoute,
|
|
176
174
|
};
|
|
177
175
|
});
|
|
@@ -183,6 +181,15 @@ export async function resolveLoaders<TEnv>(
|
|
|
183
181
|
export interface ResolveSegmentOptions {
|
|
184
182
|
/** When true, skip resolveLoaders() calls (used for pre-rendering) */
|
|
185
183
|
skipLoaders?: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* When true, a thrown render error is re-thrown instead of being converted
|
|
186
|
+
* into an error-boundary segment. Set only by the pre-render path so a
|
|
187
|
+
* build-time render failure (and a `throw new Skip()` inside a render fn)
|
|
188
|
+
* surfaces to the build instead of being silently baked into a frozen error
|
|
189
|
+
* page served as a 200 (issue #587). The live request path leaves this unset,
|
|
190
|
+
* so error boundaries keep catching at request time.
|
|
191
|
+
*/
|
|
192
|
+
throwOnError?: boolean;
|
|
186
193
|
}
|
|
187
194
|
|
|
188
195
|
/**
|
|
@@ -224,7 +231,11 @@ export async function resolveSegment<TEnv>(
|
|
|
224
231
|
index: 0,
|
|
225
232
|
component,
|
|
226
233
|
loading: entry.loading === false ? null : entry.loading,
|
|
227
|
-
transition:
|
|
234
|
+
transition: applyViewTransitionDefault(
|
|
235
|
+
entry.transition,
|
|
236
|
+
deps.viewTransitionDefault,
|
|
237
|
+
entry.shortCode,
|
|
238
|
+
),
|
|
228
239
|
params,
|
|
229
240
|
belongsToRoute: false,
|
|
230
241
|
layoutName: entry.id,
|
|
@@ -291,8 +302,11 @@ export async function resolveSegment<TEnv>(
|
|
|
291
302
|
!context.build && entry.liveHandler ? entry.liveHandler : entry.handler;
|
|
292
303
|
const doneRouteHandler = track(`handler:${entry.id}`, 2);
|
|
293
304
|
if (entry.loading) {
|
|
294
|
-
const result = handleHandlerResult(
|
|
305
|
+
const result = handleHandlerResult(
|
|
306
|
+
observeHandler(entry.id, handler, context),
|
|
307
|
+
);
|
|
295
308
|
if (result instanceof Promise) {
|
|
309
|
+
warnOnStreamedResponse(result, entry.id);
|
|
296
310
|
result.finally(doneRouteHandler).catch(() => {});
|
|
297
311
|
const tracked = deps.trackHandler(result, {
|
|
298
312
|
segmentId: entry.shortCode,
|
|
@@ -312,7 +326,9 @@ export async function resolveSegment<TEnv>(
|
|
|
312
326
|
component = result;
|
|
313
327
|
}
|
|
314
328
|
} else {
|
|
315
|
-
component = handleHandlerResult(
|
|
329
|
+
component = handleHandlerResult(
|
|
330
|
+
await observeHandler(entry.id, handler, context),
|
|
331
|
+
);
|
|
316
332
|
doneRouteHandler();
|
|
317
333
|
}
|
|
318
334
|
}
|
|
@@ -359,7 +375,11 @@ export async function resolveSegment<TEnv>(
|
|
|
359
375
|
index: 0,
|
|
360
376
|
component: component ?? null,
|
|
361
377
|
loading: entry.loading === false ? null : entry.loading,
|
|
362
|
-
transition:
|
|
378
|
+
transition: applyViewTransitionDefault(
|
|
379
|
+
entry.transition,
|
|
380
|
+
deps.viewTransitionDefault,
|
|
381
|
+
entry.shortCode,
|
|
382
|
+
),
|
|
363
383
|
params,
|
|
364
384
|
belongsToRoute: true,
|
|
365
385
|
...(entry.mountPath ? { mountPath: entry.mountPath } : {}),
|
|
@@ -443,7 +463,11 @@ export async function resolveOrphanLayout<TEnv>(
|
|
|
443
463
|
belongsToRoute,
|
|
444
464
|
layoutName: orphan.id,
|
|
445
465
|
loading: orphan.loading === false ? null : orphan.loading,
|
|
446
|
-
transition:
|
|
466
|
+
transition: applyViewTransitionDefault(
|
|
467
|
+
orphan.transition,
|
|
468
|
+
deps.viewTransitionDefault,
|
|
469
|
+
orphan.shortCode,
|
|
470
|
+
),
|
|
447
471
|
...(orphan.mountPath ? { mountPath: orphan.mountPath } : {}),
|
|
448
472
|
});
|
|
449
473
|
|
|
@@ -515,6 +539,14 @@ export async function resolveParallelEntry<TEnv>(
|
|
|
515
539
|
if (handler === undefined) {
|
|
516
540
|
continue;
|
|
517
541
|
}
|
|
542
|
+
// Pin `_currentSegmentId` to the slot's own id so handle pushes from
|
|
543
|
+
// inside the slot handler get their own bucket in the HandleStore.
|
|
544
|
+
// Parent-keying would collapse them into the parent layout's bucket;
|
|
545
|
+
// the partial-update merge then replaces the parent's bucket on a
|
|
546
|
+
// slot-only revalidation and drops layout-pushed Meta/Breadcrumbs.
|
|
547
|
+
// filterSegmentOrder() retains slot ids so the client preserves them.
|
|
548
|
+
(context as InternalHandlerContext<any, TEnv>)._currentSegmentId =
|
|
549
|
+
`${parentShortCode}.${slot}`;
|
|
518
550
|
const doneParallelHandler = track(
|
|
519
551
|
`handler:${parallelEntry.id}.${slot}`,
|
|
520
552
|
2,
|
|
@@ -523,7 +555,9 @@ export async function resolveParallelEntry<TEnv>(
|
|
|
523
555
|
parallelEntry.loading !== undefined && parallelEntry.loading !== false;
|
|
524
556
|
if (hasLoadingFallback) {
|
|
525
557
|
const result =
|
|
526
|
-
typeof handler === "function"
|
|
558
|
+
typeof handler === "function"
|
|
559
|
+
? observeHandler(`${parallelEntry.id}.${slot}`, handler, context)
|
|
560
|
+
: handler;
|
|
527
561
|
if (result instanceof Promise) {
|
|
528
562
|
result.finally(doneParallelHandler).catch(() => {});
|
|
529
563
|
const tracked = deps.trackHandler(result, {
|
|
@@ -545,7 +579,13 @@ export async function resolveParallelEntry<TEnv>(
|
|
|
545
579
|
}
|
|
546
580
|
} else {
|
|
547
581
|
component =
|
|
548
|
-
typeof handler === "function"
|
|
582
|
+
typeof handler === "function"
|
|
583
|
+
? await observeHandler(
|
|
584
|
+
`${parallelEntry.id}.${slot}`,
|
|
585
|
+
handler,
|
|
586
|
+
context,
|
|
587
|
+
)
|
|
588
|
+
: handler;
|
|
549
589
|
doneParallelHandler();
|
|
550
590
|
}
|
|
551
591
|
}
|
|
@@ -557,7 +597,11 @@ export async function resolveParallelEntry<TEnv>(
|
|
|
557
597
|
index: 0,
|
|
558
598
|
component,
|
|
559
599
|
loading: parallelEntry.loading === false ? null : parallelEntry.loading,
|
|
560
|
-
transition:
|
|
600
|
+
transition: applyViewTransitionDefault(
|
|
601
|
+
parallelEntry.transition,
|
|
602
|
+
deps.viewTransitionDefault,
|
|
603
|
+
`${parentShortCode}.${slot}`,
|
|
604
|
+
),
|
|
561
605
|
params,
|
|
562
606
|
slot,
|
|
563
607
|
belongsToRoute,
|
|
@@ -624,7 +668,7 @@ export async function resolveAllSegments<TEnv>(
|
|
|
624
668
|
// can guard non-cacheable variable reads. Also guards response-level
|
|
625
669
|
// side effects (headers.set). Persists for all descendant entries.
|
|
626
670
|
if (entry.type === "cache") {
|
|
627
|
-
const store =
|
|
671
|
+
const store = RangoContext.getStore();
|
|
628
672
|
if (store) store.insideCacheScope = true;
|
|
629
673
|
}
|
|
630
674
|
const doneEntry = track(`segment:${entry.id}`, 1);
|
|
@@ -646,6 +690,7 @@ export async function resolveAllSegments<TEnv>(
|
|
|
646
690
|
deps,
|
|
647
691
|
{ request: safeRequest, url: context.url, routeKey, telemetry },
|
|
648
692
|
context.pathname,
|
|
693
|
+
options?.throwOnError,
|
|
649
694
|
);
|
|
650
695
|
doneEntry();
|
|
651
696
|
// Deduplicate by segment ID. include() scopes can produce entries that
|
|
@@ -19,13 +19,48 @@ import {
|
|
|
19
19
|
import { getRequestContext } from "../../server/request-context.js";
|
|
20
20
|
import { DefaultErrorFallback } from "../../default-error-boundary.js";
|
|
21
21
|
import type { EntryData } from "../../server/context";
|
|
22
|
-
import type {
|
|
22
|
+
import type {
|
|
23
|
+
ResolvedSegment,
|
|
24
|
+
ErrorInfo,
|
|
25
|
+
HandlerContext,
|
|
26
|
+
InternalHandlerContext,
|
|
27
|
+
} from "../../types";
|
|
23
28
|
import type { SegmentResolutionDeps } from "../types.js";
|
|
24
29
|
import { debugLog } from "../logging.js";
|
|
25
30
|
import { tryStaticLookup } from "./static-store.js";
|
|
31
|
+
import { observeHandler } from "../instrument.js";
|
|
26
32
|
import type { TelemetrySink } from "../telemetry.js";
|
|
27
33
|
import { resolveSink, safeEmit, getRequestId } from "../telemetry.js";
|
|
28
34
|
|
|
35
|
+
/** The errorContext shape wrapLoaderPromise expects as its 5th argument. */
|
|
36
|
+
type LoaderErrorContext<TEnv> = NonNullable<
|
|
37
|
+
Parameters<SegmentResolutionDeps<TEnv>["wrapLoaderPromise"]>[4]
|
|
38
|
+
>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Build the errorContext passed to wrapLoaderPromise so a throwing DSL loader
|
|
42
|
+
* fires createRouter({ onError }) (phase "loader") and emits the loader.error
|
|
43
|
+
* telemetry event. wrapLoaderPromise only wires the onError/telemetry path when
|
|
44
|
+
* this 5th argument is present; every real call site previously omitted it, so
|
|
45
|
+
* loaders were the one phase whose failures were silently dropped (handlers,
|
|
46
|
+
* actions, routing, rendering, and fetchable loaders all reported correctly).
|
|
47
|
+
*
|
|
48
|
+
* The fields come off the handler context, which already carries the request,
|
|
49
|
+
* url, params, env, and (on the internal shape) the matched route name.
|
|
50
|
+
*/
|
|
51
|
+
export function buildLoaderErrorContext<TEnv>(
|
|
52
|
+
ctx: HandlerContext<any, TEnv>,
|
|
53
|
+
): LoaderErrorContext<TEnv> {
|
|
54
|
+
const internal = ctx as InternalHandlerContext<any, TEnv>;
|
|
55
|
+
return {
|
|
56
|
+
request: ctx.request,
|
|
57
|
+
url: ctx.url,
|
|
58
|
+
routeKey: internal._routeName,
|
|
59
|
+
params: ctx.params as Record<string, string>,
|
|
60
|
+
env: ctx.env,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
29
64
|
// ---------------------------------------------------------------------------
|
|
30
65
|
// Handler result processing
|
|
31
66
|
// ---------------------------------------------------------------------------
|
|
@@ -52,6 +87,40 @@ export function handleHandlerResult(
|
|
|
52
87
|
return result;
|
|
53
88
|
}
|
|
54
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Dev-only: warn when a handler on a route that declares loading() resolves or
|
|
92
|
+
* rejects with a Response (e.g. redirect()).
|
|
93
|
+
*
|
|
94
|
+
* On a non-loading route a returned/thrown Response short-circuits to an HTTP
|
|
95
|
+
* redirect. But when the route declares loading(), the handler result is
|
|
96
|
+
* streamed (not awaited at the resolution boundary), so the Response surfaces
|
|
97
|
+
* only during RSC serialization and is rendered into the stream instead of
|
|
98
|
+
* becoming a 302/308 — a silent failure mode. Issue redirects from middleware,
|
|
99
|
+
* a loader, or a synchronous handler return instead. Compiled out in production.
|
|
100
|
+
*/
|
|
101
|
+
export function warnOnStreamedResponse(
|
|
102
|
+
result: Promise<unknown>,
|
|
103
|
+
entryId: string,
|
|
104
|
+
): void {
|
|
105
|
+
if (process.env.NODE_ENV === "production") return;
|
|
106
|
+
// A Response can surface either as a rejection (handleHandlerResult rethrows a
|
|
107
|
+
// resolved Response) or as a resolved value (the raw parallel-slot handler is
|
|
108
|
+
// not run through handleHandlerResult). Check both so every streamed path is
|
|
109
|
+
// covered. Each handler is an independent observer; it does not consume the
|
|
110
|
+
// rejection for the trackHandler/observeStreamedHandler chains.
|
|
111
|
+
const check = (value: unknown) => {
|
|
112
|
+
if (value instanceof Response) {
|
|
113
|
+
console.warn(
|
|
114
|
+
`[rango] Handler for "${entryId}" returned a Response (e.g. ` +
|
|
115
|
+
`redirect()), but it declares loading(): the Response is rendered ` +
|
|
116
|
+
`into the RSC stream, NOT sent as an HTTP redirect. Issue redirects ` +
|
|
117
|
+
`from middleware, a loader, or a synchronous handler return.`,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
result.then(check, check);
|
|
122
|
+
}
|
|
123
|
+
|
|
55
124
|
// ---------------------------------------------------------------------------
|
|
56
125
|
// Static handler interception
|
|
57
126
|
// ---------------------------------------------------------------------------
|
|
@@ -96,11 +165,16 @@ export async function resolveLayoutComponent<TEnv>(
|
|
|
96
165
|
entry: EntryData,
|
|
97
166
|
context: HandlerContext<any, TEnv>,
|
|
98
167
|
): Promise<ReactNode> {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
168
|
+
// Static/prerender hit: no handler runs, so emit no rango.handler span.
|
|
169
|
+
const staticComponent = await tryStaticHandler(entry, entry.shortCode);
|
|
170
|
+
if (staticComponent !== undefined) return staticComponent;
|
|
171
|
+
const handler = entry.handler;
|
|
172
|
+
if (typeof handler !== "function") return handler as ReactNode;
|
|
173
|
+
// Wrap ONLY the handler call in the rango.handler span (the perf metric is owned
|
|
174
|
+
// by track("handler:<id>") at the call site). handleHandlerResult stays OUTSIDE
|
|
175
|
+
// the span so a handler that returns a Response (redirect control flow, which it
|
|
176
|
+
// rethrows) is not recorded as a span error — mirrors the route-handler sites.
|
|
177
|
+
return handleHandlerResult(await observeHandler(entry.id, handler, context));
|
|
104
178
|
}
|
|
105
179
|
|
|
106
180
|
// ---------------------------------------------------------------------------
|
|
@@ -250,11 +324,17 @@ export async function resolveWithErrorBoundary<TEnv, TResult>(
|
|
|
250
324
|
deps: SegmentResolutionDeps<TEnv>,
|
|
251
325
|
report?: ErrorReportContext,
|
|
252
326
|
pathname?: string,
|
|
327
|
+
throwOnError?: boolean,
|
|
253
328
|
): Promise<TResult> {
|
|
254
329
|
try {
|
|
255
330
|
return await resolveFn();
|
|
256
331
|
} catch (error) {
|
|
257
332
|
if (error instanceof Response) throw error;
|
|
333
|
+
// Pre-render surfaces render failures to the build instead of baking the
|
|
334
|
+
// error boundary as a frozen 200 (issue #587). A `throw new Skip()` in a
|
|
335
|
+
// render fn also propagates here so the build can skip that URL rather than
|
|
336
|
+
// bake its error page. The live request path leaves throwOnError unset.
|
|
337
|
+
if (throwOnError) throw error;
|
|
258
338
|
const segment = catchSegmentError(
|
|
259
339
|
error,
|
|
260
340
|
entry,
|