@rangojs/router 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +255 -89
- package/dist/testing/vitest.js +252 -0
- package/dist/types/browser/cookie-name.d.ts +6 -0
- package/dist/types/browser/history-state.d.ts +16 -0
- package/dist/types/browser/navigation-transaction.d.ts +6 -0
- package/dist/types/browser/partial-update.d.ts +11 -0
- package/dist/types/browser/react/ScrollRestoration.d.ts +6 -6
- package/dist/types/browser/rsc-router.d.ts +1 -1
- package/dist/types/browser/scroll-restoration.d.ts +7 -0
- package/dist/types/cache/cache-exec-scope.d.ts +18 -1
- package/dist/types/cache/cache-key-utils.d.ts +17 -2
- package/dist/types/cache/cache-policy.d.ts +17 -0
- package/dist/types/cache/cache-scope.d.ts +132 -19
- package/dist/types/cache/cache-tag.d.ts +92 -7
- package/dist/types/cache/cf/cf-base64.d.ts +6 -0
- package/dist/types/cache/cf/cf-cache-constants.d.ts +11 -0
- package/dist/types/cache/cf/cf-cache-store.d.ts +185 -44
- package/dist/types/cache/cf/cf-cache-types.d.ts +31 -4
- package/dist/types/cache/cf/cf-shell-frame.d.ts +95 -0
- package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +34 -0
- package/dist/types/cache/handle-capture.d.ts +41 -3
- package/dist/types/cache/handle-snapshot.d.ts +54 -13
- package/dist/types/cache/index.d.ts +1 -0
- package/dist/types/cache/isolate-tag-memo.d.ts +149 -0
- package/dist/types/cache/segment-codec.d.ts +10 -3
- package/dist/types/cache/shell-memo.d.ts +178 -0
- package/dist/types/cache/shell-snapshot.d.ts +110 -21
- package/dist/types/cache/tag-invalidation.d.ts +30 -3
- package/dist/types/cache/taint.d.ts +1 -1
- package/dist/types/cache/types.d.ts +220 -44
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +111 -13
- package/dist/types/client.d.ts +4 -4
- package/dist/types/client.rsc.d.ts +4 -5
- package/dist/types/components/DefaultDocument.d.ts +5 -2
- package/dist/types/context-var.d.ts +6 -5
- package/dist/types/escape-script.d.ts +1 -1
- package/dist/types/handles/MetaTags.d.ts +5 -4
- package/dist/types/handles/Scripts.d.ts +8 -7
- package/dist/types/handles/meta.d.ts +2 -2
- package/dist/types/handles/script.d.ts +17 -16
- package/dist/types/href-client.d.ts +1 -1
- package/dist/types/html.d.ts +12 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.rsc.d.ts +3 -2
- package/dist/types/loader-store.d.ts +7 -4
- package/dist/types/prerender/build-shell-capture.d.ts +11 -4
- package/dist/types/reverse.d.ts +36 -4
- package/dist/types/route-definition/dsl-helpers.d.ts +3 -3
- package/dist/types/route-definition/helpers-types.d.ts +33 -9
- package/dist/types/route-definition/resolve-handler-use.d.ts +23 -1
- package/dist/types/route-types.d.ts +1 -1
- package/dist/types/router/debug-manifest.d.ts +3 -2
- package/dist/types/router/error-handling.d.ts +20 -0
- package/dist/types/router/handler-context.d.ts +6 -0
- package/dist/types/router/instrument.d.ts +8 -0
- package/dist/types/router/match-middleware/background-revalidation.d.ts +46 -5
- package/dist/types/router/middleware-types.d.ts +9 -3
- package/dist/types/router/router-context.d.ts +3 -1
- package/dist/types/router/router-interfaces.d.ts +24 -2
- package/dist/types/router/router-options.d.ts +8 -5
- package/dist/types/router/segment-resolution/fresh.d.ts +10 -0
- package/dist/types/router/segment-resolution/loader-cache.d.ts +66 -1
- package/dist/types/router/segment-resolution/loader-mask.d.ts +9 -19
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +23 -12
- package/dist/types/router/segment-resolution/mask-nested.d.ts +67 -26
- package/dist/types/router/segment-resolution/revalidation.d.ts +6 -2
- package/dist/types/router/segment-wrappers.d.ts +1 -1
- package/dist/types/rsc/full-payload.d.ts +14 -0
- package/dist/types/rsc/handler.d.ts +1 -1
- package/dist/types/rsc/response-route-handler.d.ts +1 -1
- package/dist/types/rsc/rsc-rendering.d.ts +1 -2
- package/dist/types/rsc/shell-build-manifest.d.ts +8 -0
- package/dist/types/rsc/shell-capture-constants.d.ts +61 -6
- package/dist/types/rsc/shell-capture.d.ts +151 -19
- package/dist/types/rsc/shell-serve.d.ts +140 -17
- package/dist/types/rsc/ssr-setup.d.ts +6 -6
- package/dist/types/rsc/types.d.ts +17 -0
- package/dist/types/server/context.d.ts +139 -15
- package/dist/types/server/cookie-store.d.ts +21 -0
- package/dist/types/server/handle-store.d.ts +26 -2
- package/dist/types/server/request-context.d.ts +182 -53
- package/dist/types/ssr/index.d.ts +24 -0
- package/dist/types/ssr/ssr-root.d.ts +9 -8
- package/dist/types/static-handler.d.ts +4 -1
- package/dist/types/testing/flight.entry.d.ts +7 -0
- package/dist/types/testing/generated-routes.d.ts +2 -2
- package/dist/types/testing/internal/context.d.ts +1 -1
- package/dist/types/testing/render-route.d.ts +32 -6
- package/dist/types/testing/run-loader.d.ts +18 -3
- package/dist/types/testing/serve-shell-request.d.ts +132 -0
- package/dist/types/testing/shell-status.d.ts +23 -10
- package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +28 -5
- package/dist/types/testing/vitest.d.ts +35 -1
- package/dist/types/theme/ThemeScript.d.ts +3 -3
- package/dist/types/types/cache-types.d.ts +14 -10
- package/dist/types/types/handler-context.d.ts +28 -1
- package/dist/types/types/loader-types.d.ts +8 -6
- package/dist/types/urls/pattern-types.d.ts +22 -18
- package/dist/types/urls/response-types.d.ts +3 -12
- package/dist/types/use-loader.d.ts +12 -3
- package/dist/types/vite/plugins/use-cache-transform.d.ts +33 -2
- package/dist/types/vite/rango.d.ts +1 -1
- package/dist/types/vite/router-discovery.d.ts +29 -2
- package/dist/vite/index.js +1420 -1348
- package/package.json +2 -2
- package/skills/api-client/SKILL.md +22 -10
- package/skills/breadcrumbs/SKILL.md +75 -22
- package/skills/bundle-analysis/SKILL.md +22 -22
- package/skills/cache-guide/SKILL.md +306 -124
- package/skills/caching/SKILL.md +530 -98
- package/skills/catalog.json +16 -16
- package/skills/client-urls/SKILL.md +65 -38
- package/skills/cloudflare/SKILL.md +87 -20
- package/skills/cloudflare/references/d1-and-local-dev.md +15 -2
- package/skills/cloudflare/references/streaming-and-deploy.md +10 -3
- package/skills/cloudflare/references/webhooks-and-crypto.md +9 -2
- package/skills/comparison/SKILL.md +5 -0
- package/skills/comparison/references/framework-comparison.md +75 -57
- package/skills/composability/SKILL.md +38 -29
- package/skills/css/SKILL.md +10 -13
- package/skills/debug-manifest/SKILL.md +74 -31
- package/skills/defer-hydration/SKILL.md +52 -31
- package/skills/deployment-caching/SKILL.md +11 -3
- package/skills/document-cache/SKILL.md +98 -28
- package/skills/fonts/SKILL.md +16 -8
- package/skills/handler-use/SKILL.md +55 -17
- package/skills/hooks/SKILL.md +28 -20
- package/skills/hooks/data.md +23 -3
- package/skills/hooks/handle-and-actions.md +34 -17
- package/skills/hooks/navigation.md +39 -10
- package/skills/hooks/outlets.md +13 -6
- package/skills/hooks/state.md +39 -15
- package/skills/hooks/urls.md +7 -5
- package/skills/host-router/SKILL.md +64 -12
- package/skills/i18n/SKILL.md +60 -34
- package/skills/intercept/SKILL.md +161 -26
- package/skills/layout/SKILL.md +106 -50
- package/skills/links/SKILL.md +51 -19
- package/skills/loader/SKILL.md +386 -128
- package/skills/middleware/SKILL.md +129 -26
- package/skills/migrate-nextjs/SKILL.md +156 -70
- package/skills/migrate-nextjs/backend-host-swap.md +5 -2
- package/skills/migrate-react-router/SKILL.md +51 -39
- package/skills/migrate-react-router/component-migration.md +28 -7
- package/skills/migrate-react-router/data-and-actions.md +21 -6
- package/skills/migrate-react-router/route-mapping.md +19 -10
- package/skills/mime-routes/SKILL.md +12 -7
- package/skills/observability/SKILL.md +92 -14
- package/skills/parallel/SKILL.md +88 -47
- package/skills/ppr/SKILL.md +866 -379
- package/skills/prerender/SKILL.md +210 -108
- package/skills/rango/SKILL.md +115 -65
- package/skills/react-compiler/SKILL.md +6 -5
- package/skills/response-routes/SKILL.md +133 -25
- package/skills/route/SKILL.md +170 -60
- package/skills/router-setup/SKILL.md +420 -240
- package/skills/scripts/SKILL.md +39 -21
- package/skills/server-actions/SKILL.md +231 -59
- package/skills/shell-manifest/SKILL.md +28 -14
- package/skills/streams-and-websockets/SKILL.md +32 -14
- package/skills/tailwind/SKILL.md +37 -33
- package/skills/testing/SKILL.md +73 -33
- package/skills/testing/cache-prerender.md +60 -33
- package/skills/testing/client-components.md +59 -6
- package/skills/testing/e2e-parity.md +12 -2
- package/skills/testing/flight.md +19 -11
- package/skills/testing/handles.md +8 -5
- package/skills/testing/loader.md +26 -6
- package/skills/testing/middleware.md +8 -3
- package/skills/testing/predicates.md +120 -0
- package/skills/testing/render-handler.md +70 -22
- package/skills/testing/response-routes.md +11 -4
- package/skills/testing/reverse-and-types.md +20 -14
- package/skills/testing/serve-shell-request.md +188 -0
- package/skills/testing/server-actions.md +12 -3
- package/skills/testing/server-tree.md +9 -0
- package/skills/testing/setup.md +9 -5
- package/skills/theme/SKILL.md +155 -30
- package/skills/typesafety/SKILL.md +20 -9
- package/skills/typesafety/env-and-bindings.md +137 -50
- package/skills/typesafety/generated-files-and-cli.md +26 -14
- package/skills/typesafety/params-and-search.md +44 -19
- package/skills/typesafety/route-types.md +50 -14
- package/skills/use-cache/SKILL.md +224 -83
- package/skills/vercel/SKILL.md +35 -13
- package/skills/view-transitions/SKILL.md +42 -21
- package/src/__augment-tests__/augmented.check.ts +26 -1
- package/src/browser/cookie-name.ts +23 -0
- package/src/browser/history-state.ts +23 -0
- package/src/browser/index.ts +2 -2
- package/src/browser/navigation-bridge.ts +3 -4
- package/src/browser/navigation-transaction.ts +22 -2
- package/src/browser/partial-update.ts +35 -25
- package/src/browser/react/ScrollRestoration.tsx +6 -6
- package/src/browser/rsc-router.tsx +6 -1
- package/src/browser/scroll-restoration.ts +53 -6
- package/src/cache/cache-exec-scope.ts +37 -4
- package/src/cache/cache-key-utils.ts +23 -8
- package/src/cache/cache-policy.ts +22 -0
- package/src/cache/cache-runtime.ts +264 -68
- package/src/cache/cache-scope.ts +419 -43
- package/src/cache/cache-tag.ts +375 -11
- package/src/cache/cf/cf-base64.ts +36 -4
- package/src/cache/cf/cf-cache-constants.ts +12 -0
- package/src/cache/cf/cf-cache-store.ts +990 -348
- package/src/cache/cf/cf-cache-types.ts +32 -4
- package/src/cache/cf/cf-shell-frame.ts +258 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +143 -39
- package/src/cache/document-cache.ts +15 -0
- package/src/cache/handle-capture.ts +90 -10
- package/src/cache/handle-snapshot.ts +133 -28
- package/src/cache/index.ts +2 -0
- package/src/cache/isolate-tag-memo.ts +308 -0
- package/src/cache/segment-codec.ts +26 -7
- package/src/cache/shell-memo.ts +341 -0
- package/src/cache/shell-snapshot.ts +217 -27
- package/src/cache/tag-invalidation.ts +108 -22
- package/src/cache/taint.ts +1 -1
- package/src/cache/types.ts +225 -44
- package/src/cache/vercel/vercel-cache-store.ts +545 -61
- package/src/client.rsc.tsx +10 -9
- package/src/client.tsx +5 -4
- package/src/components/DefaultDocument.tsx +7 -2
- package/src/context-var.ts +6 -5
- package/src/escape-script.ts +1 -1
- package/src/handles/MetaTags.tsx +13 -11
- package/src/handles/Scripts.tsx +11 -10
- package/src/handles/meta.ts +2 -2
- package/src/handles/script.ts +17 -16
- package/src/href-client.ts +1 -1
- package/src/html.ts +12 -0
- package/src/index.rsc.ts +5 -0
- package/src/index.ts +1 -0
- package/src/loader-store.ts +7 -4
- package/src/prerender/build-shell-capture.ts +73 -22
- package/src/reverse.ts +44 -4
- package/src/route-definition/dsl-helpers.ts +121 -33
- package/src/route-definition/helpers-types.ts +33 -9
- package/src/route-definition/resolve-handler-use.ts +121 -6
- package/src/route-types.ts +0 -3
- package/src/router/debug-manifest.ts +10 -2
- package/src/router/error-handling.ts +51 -15
- package/src/router/handler-context.ts +71 -28
- package/src/router/instrument.ts +54 -2
- package/src/router/intercept-resolution.ts +141 -43
- package/src/router/loader-resolution.ts +115 -39
- package/src/router/match-api.ts +40 -26
- package/src/router/match-handlers.ts +5 -0
- package/src/router/match-middleware/background-revalidation.ts +161 -96
- package/src/router/match-middleware/cache-lookup.ts +110 -10
- package/src/router/match-middleware/cache-store.ts +48 -101
- package/src/router/middleware-types.ts +9 -6
- package/src/router/middleware.ts +75 -13
- package/src/router/prerender-match.ts +59 -19
- package/src/router/route-snapshot.ts +11 -1
- package/src/router/router-context.ts +2 -0
- package/src/router/router-interfaces.ts +25 -2
- package/src/router/router-options.ts +8 -5
- package/src/router/segment-resolution/fresh.ts +62 -21
- package/src/router/segment-resolution/helpers.ts +4 -2
- package/src/router/segment-resolution/loader-cache.ts +407 -76
- package/src/router/segment-resolution/loader-mask.ts +12 -22
- package/src/router/segment-resolution/loader-snapshot.ts +208 -56
- package/src/router/segment-resolution/mask-nested.ts +138 -44
- package/src/router/segment-resolution/revalidation.ts +61 -16
- package/src/router/segment-wrappers.ts +4 -0
- package/src/rsc/full-payload.ts +25 -1
- package/src/rsc/handler.ts +14 -2
- package/src/rsc/progressive-enhancement.ts +3 -2
- package/src/rsc/render-pipeline.ts +3 -0
- package/src/rsc/response-cache-serve.ts +9 -6
- package/src/rsc/response-route-handler.ts +11 -3
- package/src/rsc/rsc-rendering.ts +608 -225
- package/src/rsc/shell-build-manifest.ts +27 -9
- package/src/rsc/shell-capture-constants.ts +73 -6
- package/src/rsc/shell-capture.ts +1068 -296
- package/src/rsc/shell-serve.ts +316 -34
- package/src/rsc/ssr-setup.ts +14 -8
- package/src/rsc/types.ts +18 -0
- package/src/server/context.ts +300 -32
- package/src/server/cookie-store.ts +87 -61
- package/src/server/handle-store.ts +232 -7
- package/src/server/request-context.ts +297 -67
- package/src/ssr/index.tsx +136 -44
- package/src/ssr/ssr-root.tsx +9 -8
- package/src/static-handler.ts +4 -1
- package/src/testing/flight-runtime.d.ts +21 -0
- package/src/testing/flight.entry.ts +14 -0
- package/src/testing/generated-routes.ts +2 -2
- package/src/testing/internal/context.ts +1 -1
- package/src/testing/internal/flight-client-globals.ts +7 -5
- package/src/testing/render-route.tsx +85 -24
- package/src/testing/run-loader.ts +68 -6
- package/src/testing/serve-shell-request.ts +378 -0
- package/src/testing/shell-status.ts +34 -12
- package/src/testing/vitest-stubs/plugin-rsc.ts +123 -20
- package/src/testing/vitest.ts +62 -1
- package/src/theme/ThemeProvider.tsx +7 -6
- package/src/theme/ThemeScript.tsx +3 -3
- package/src/types/cache-types.ts +14 -10
- package/src/types/handler-context.ts +28 -1
- package/src/types/loader-types.ts +8 -6
- package/src/urls/pattern-types.ts +22 -18
- package/src/urls/response-types.ts +3 -23
- package/src/use-loader.tsx +12 -3
- package/src/vite/discovery/shell-prerender-phase.ts +9 -0
- package/src/vite/plugins/use-cache-transform.ts +118 -74
- package/src/vite/rango.ts +7 -3
- package/src/vite/router-discovery.ts +14 -4
|
@@ -82,13 +82,13 @@
|
|
|
82
82
|
* ISOLATION FROM RESPONSE
|
|
83
83
|
* =======================
|
|
84
84
|
*
|
|
85
|
-
* Background revalidation
|
|
86
|
-
*
|
|
85
|
+
* Background revalidation re-renders through rerenderAndCacheRoute (shared
|
|
86
|
+
* with proactive caching in cache-store.ts):
|
|
87
|
+
* - Derived request context with its own handleStore, transition({ when })
|
|
88
|
+
* predicates and no perf metrics (the shared fields are never touched;
|
|
89
|
+
* the foreground is still producing the page)
|
|
87
90
|
* - Fresh handlerContext + loaderPromises (prevents reusing memoized
|
|
88
91
|
* loader results from the foreground pass)
|
|
89
|
-
* - handleStore is saved/restored in try/finally
|
|
90
|
-
*
|
|
91
|
-
* This matches the proactive caching pattern in cache-store.ts.
|
|
92
92
|
*
|
|
93
93
|
*
|
|
94
94
|
* FRESH RESOLUTION (NO REVALIDATION)
|
|
@@ -101,15 +101,163 @@
|
|
|
101
101
|
*/
|
|
102
102
|
import type { ResolvedSegment } from "../../types.js";
|
|
103
103
|
import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
104
|
-
import { getRouterContext } from "../router-context.js";
|
|
104
|
+
import { getRouterContext, type RouterContext } from "../router-context.js";
|
|
105
|
+
import type { CacheScope } from "../../cache/cache-scope.js";
|
|
105
106
|
import type { GeneratorMiddleware } from "./cache-lookup.js";
|
|
106
107
|
import { debugLog, debugWarn, getOrCreateRequestId } from "../logging.js";
|
|
107
108
|
import { INTERNAL_RANGO_DEBUG } from "../../internal-debug.js";
|
|
109
|
+
import { getContext } from "../../server/context.js";
|
|
108
110
|
import {
|
|
111
|
+
createRequestContext,
|
|
109
112
|
runWithRequestContext,
|
|
110
113
|
type RequestContext,
|
|
111
114
|
} from "../../server/request-context.js";
|
|
112
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Re-render a cached route in the background and write it with
|
|
118
|
+
* cacheScope.cacheRoute: the stale-hit refresh below and proactive caching
|
|
119
|
+
* (cache-store.ts). Returns the number of segments written.
|
|
120
|
+
*
|
|
121
|
+
* A render whose status is not 200 (an error or notFound boundary resolved)
|
|
122
|
+
* is not written and returns 0, as a non-200 MISS is not cached
|
|
123
|
+
* (cache-store.ts): the entry it would replace keeps serving until a later
|
|
124
|
+
* refresh succeeds or it expires. Nothing is held in process; a store's own
|
|
125
|
+
* revalidation marker (CFCacheStore's REVALIDATING) re-arms after
|
|
126
|
+
* MAX_REVALIDATION_INTERVAL, as after a refresh that throws.
|
|
127
|
+
*
|
|
128
|
+
* Runs on a DERIVED request context that owns the per-render state the
|
|
129
|
+
* foreground reads while it is still producing the page (a stale HIT re-runs
|
|
130
|
+
* its loaders; a proactive render starts once the Response exists, while its
|
|
131
|
+
* body streams):
|
|
132
|
+
* - _handleStore: read late (loader pushes and aux-lane tracking in
|
|
133
|
+
* loader-resolution.ts, nested cache restores and captures in
|
|
134
|
+
* cache-scope.ts), so a swap sent live pushes into this render.
|
|
135
|
+
* setupLoaderAccess binds the store at setup, so it runs inside the
|
|
136
|
+
* derived context too.
|
|
137
|
+
* - _transitionWhen: fresh resolution appends transition({ when })
|
|
138
|
+
* predicates; the foreground's gateTransitions reads the array after the
|
|
139
|
+
* match, and a stale HIT (which replays the stored transition) must not
|
|
140
|
+
* evaluate this render's predicates.
|
|
141
|
+
* - _metricsStore: undefined, and the DSL store below has `metrics` unset
|
|
142
|
+
* (track() reads that one), so nothing lands on the foreground's perf
|
|
143
|
+
* timeline. ctx.Store.run closes over ctx.Store, so the derived store
|
|
144
|
+
* needs its own run.
|
|
145
|
+
* - response writes (headers, cookies, status, onResponse callbacks) go to
|
|
146
|
+
* a throwaway context (whose status gates the write, above) and are
|
|
147
|
+
* dropped: a layout above the cache() boundary is outside the header
|
|
148
|
+
* guard and an error boundary sets a status, so they would otherwise
|
|
149
|
+
* reach the live response.
|
|
150
|
+
* runWithRequestContext also re-establishes the request ALS, which a waitUntil
|
|
151
|
+
* task on workerd loses; the DSL store is a different ALS (build context).
|
|
152
|
+
*/
|
|
153
|
+
export async function rerenderAndCacheRoute<TEnv>(
|
|
154
|
+
ctx: MatchContext<TEnv>,
|
|
155
|
+
requestCtx: RequestContext<TEnv>,
|
|
156
|
+
cacheScope: CacheScope,
|
|
157
|
+
routerCtx: RouterContext<TEnv>,
|
|
158
|
+
): Promise<number> {
|
|
159
|
+
const handleStore = routerCtx.createHandleStore();
|
|
160
|
+
// Response writes land in a throwaway context nothing merges or drains. Its
|
|
161
|
+
// mutators are closures over its own stub, and they keep the same guards.
|
|
162
|
+
const sink = createRequestContext({
|
|
163
|
+
env: ctx.env,
|
|
164
|
+
request: ctx.request,
|
|
165
|
+
url: ctx.url,
|
|
166
|
+
variables: {},
|
|
167
|
+
themeConfig: requestCtx._themeConfig,
|
|
168
|
+
});
|
|
169
|
+
const renderCtx: RequestContext<TEnv> = Object.assign(
|
|
170
|
+
Object.create(requestCtx, {
|
|
171
|
+
res: Object.getOwnPropertyDescriptor(sink, "res")!,
|
|
172
|
+
}),
|
|
173
|
+
{
|
|
174
|
+
_handleStore: handleStore,
|
|
175
|
+
_transitionWhen: [],
|
|
176
|
+
_metricsStore: undefined,
|
|
177
|
+
_onResponseCallbacks: [],
|
|
178
|
+
header: sink.header,
|
|
179
|
+
setCookie: sink.setCookie,
|
|
180
|
+
deleteCookie: sink.deleteCookie,
|
|
181
|
+
setStatus: sink.setStatus,
|
|
182
|
+
_setStatus: sink._setStatus,
|
|
183
|
+
setTheme: sink.setTheme,
|
|
184
|
+
_rotateStateCookie: sink._rotateStateCookie,
|
|
185
|
+
_setKeepCacheDirective: sink._setKeepCacheDirective,
|
|
186
|
+
},
|
|
187
|
+
);
|
|
188
|
+
const store = Object.assign(Object.create(ctx.Store), { metrics: undefined });
|
|
189
|
+
const runInStore = <T>(fn: () => T): T =>
|
|
190
|
+
getContext().runWithStore(
|
|
191
|
+
store,
|
|
192
|
+
store.namespace || "#router",
|
|
193
|
+
store.parent,
|
|
194
|
+
fn,
|
|
195
|
+
);
|
|
196
|
+
return runWithRequestContext(renderCtx, async () => {
|
|
197
|
+
const handlerContext = routerCtx.createHandlerContext(
|
|
198
|
+
ctx.matched.params,
|
|
199
|
+
ctx.request,
|
|
200
|
+
ctx.url.searchParams,
|
|
201
|
+
ctx.pathname,
|
|
202
|
+
ctx.url,
|
|
203
|
+
ctx.env,
|
|
204
|
+
ctx.routeMap,
|
|
205
|
+
ctx.matched.routeKey,
|
|
206
|
+
ctx.matched.responseType,
|
|
207
|
+
ctx.matched.pt === true,
|
|
208
|
+
);
|
|
209
|
+
const loaderPromises = new Map<string, Promise<any>>();
|
|
210
|
+
routerCtx.setupLoaderAccess(handlerContext, loaderPromises);
|
|
211
|
+
|
|
212
|
+
const segments = await runInStore(() =>
|
|
213
|
+
routerCtx.resolveAllSegments(
|
|
214
|
+
ctx.entries,
|
|
215
|
+
ctx.routeKey,
|
|
216
|
+
ctx.matched.params,
|
|
217
|
+
handlerContext,
|
|
218
|
+
loaderPromises,
|
|
219
|
+
{ skipLoaders: true },
|
|
220
|
+
),
|
|
221
|
+
);
|
|
222
|
+
if (ctx.interceptResult) {
|
|
223
|
+
segments.push(
|
|
224
|
+
...(await runInStore(() =>
|
|
225
|
+
routerCtx.resolveInterceptEntry(
|
|
226
|
+
ctx.interceptResult!.intercept,
|
|
227
|
+
ctx.interceptResult!.entry,
|
|
228
|
+
ctx.matched.params,
|
|
229
|
+
handlerContext,
|
|
230
|
+
true, // belongsToRoute
|
|
231
|
+
undefined, // no revalidationContext: render fresh
|
|
232
|
+
// Skip intercept middleware: the foreground already ran it.
|
|
233
|
+
// Re-running it here would double its side effects, and a
|
|
234
|
+
// short-circuit Response would abort the write.
|
|
235
|
+
{ skipMiddleware: true },
|
|
236
|
+
),
|
|
237
|
+
)),
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
handleStore.seal();
|
|
242
|
+
// Boundaries set 500/404 through _setStatus (catchSegmentError), which
|
|
243
|
+
// lands on the sink.
|
|
244
|
+
if (sink.res.status !== 200) {
|
|
245
|
+
debugLog("backgroundRevalidation", "skipping cache for non-200 render", {
|
|
246
|
+
status: sink.res.status,
|
|
247
|
+
pathname: ctx.pathname,
|
|
248
|
+
});
|
|
249
|
+
return 0;
|
|
250
|
+
}
|
|
251
|
+
await cacheScope.cacheRoute(
|
|
252
|
+
ctx.pathname,
|
|
253
|
+
ctx.matched.params,
|
|
254
|
+
segments,
|
|
255
|
+
ctx.isIntercept,
|
|
256
|
+
);
|
|
257
|
+
return segments.length;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
113
261
|
/**
|
|
114
262
|
* Creates background revalidation middleware
|
|
115
263
|
*
|
|
@@ -137,111 +285,31 @@ export function withBackgroundRevalidation<TEnv>(
|
|
|
137
285
|
return;
|
|
138
286
|
}
|
|
139
287
|
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
createHandleStore,
|
|
143
|
-
createHandlerContext,
|
|
144
|
-
setupLoaderAccess,
|
|
145
|
-
resolveAllSegments,
|
|
146
|
-
resolveInterceptEntry,
|
|
147
|
-
} = getRouterContext<TEnv>();
|
|
148
|
-
|
|
149
|
-
const requestCtx = getRequestContext();
|
|
288
|
+
const routerCtx = getRouterContext<TEnv>();
|
|
289
|
+
const requestCtx = routerCtx.getRequestContext();
|
|
150
290
|
const cacheScope = ctx.cacheScope;
|
|
151
291
|
const reqId = INTERNAL_RANGO_DEBUG
|
|
152
292
|
? getOrCreateRequestId(ctx.request)
|
|
153
293
|
: undefined;
|
|
154
294
|
|
|
155
295
|
requestCtx?.waitUntil(async () => {
|
|
156
|
-
// Prevent background metrics from polluting foreground timeline.
|
|
157
|
-
// The foreground uses its own metricsStore reference directly (via
|
|
158
|
-
// appendMetric), so nulling Store.metrics only affects track() calls
|
|
159
|
-
// inside this background Store.run() scope.
|
|
160
|
-
const savedMetrics = ctx.Store.metrics;
|
|
161
|
-
ctx.Store.metrics = undefined;
|
|
162
|
-
|
|
163
296
|
const start = performance.now();
|
|
164
297
|
debugLog("backgroundRevalidation", "revalidating stale route", {
|
|
165
298
|
pathname: ctx.pathname,
|
|
166
299
|
fullMatch: ctx.isFullMatch,
|
|
167
300
|
});
|
|
168
301
|
|
|
169
|
-
// Save and replace handleStore to avoid polluting the response stream.
|
|
170
|
-
// Restore in finally (same pattern as proactive caching in cache-store).
|
|
171
|
-
const originalHandleStore = requestCtx._handleStore;
|
|
172
|
-
requestCtx._handleStore = createHandleStore();
|
|
173
|
-
|
|
174
302
|
try {
|
|
175
|
-
const
|
|
176
|
-
ctx
|
|
177
|
-
ctx.request,
|
|
178
|
-
ctx.url.searchParams,
|
|
179
|
-
ctx.pathname,
|
|
180
|
-
ctx.url,
|
|
181
|
-
ctx.env,
|
|
182
|
-
ctx.routeMap,
|
|
183
|
-
ctx.matched.routeKey,
|
|
184
|
-
ctx.matched.responseType,
|
|
185
|
-
ctx.matched.pt === true,
|
|
186
|
-
);
|
|
187
|
-
const freshLoaderPromises = new Map<string, Promise<any>>();
|
|
188
|
-
setupLoaderAccess(freshHandlerContext, freshLoaderPromises);
|
|
189
|
-
|
|
190
|
-
// Re-establish the request-context ALS around the re-render. ctx.Store
|
|
191
|
-
// is a different ALS (DSL build context); on workerd a waitUntil task
|
|
192
|
-
// runs detached from the request's I/O context, so a handler/component
|
|
193
|
-
// that reads the ambient getRequestContext() during this background
|
|
194
|
-
// re-render would otherwise throw "called outside of a request context".
|
|
195
|
-
const freshSegments = await runWithRequestContext(
|
|
303
|
+
const count = await rerenderAndCacheRoute(
|
|
304
|
+
ctx,
|
|
196
305
|
requestCtx as RequestContext<TEnv>,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
resolveAllSegments(
|
|
200
|
-
ctx.entries,
|
|
201
|
-
ctx.routeKey,
|
|
202
|
-
ctx.matched.params,
|
|
203
|
-
freshHandlerContext,
|
|
204
|
-
freshLoaderPromises,
|
|
205
|
-
{ skipLoaders: true },
|
|
206
|
-
),
|
|
207
|
-
),
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
let freshInterceptSegments: ResolvedSegment[] = [];
|
|
211
|
-
if (ctx.interceptResult) {
|
|
212
|
-
freshInterceptSegments = await runWithRequestContext(
|
|
213
|
-
requestCtx as RequestContext<TEnv>,
|
|
214
|
-
() =>
|
|
215
|
-
ctx.Store.run(() =>
|
|
216
|
-
resolveInterceptEntry(
|
|
217
|
-
ctx.interceptResult!.intercept,
|
|
218
|
-
ctx.interceptResult!.entry,
|
|
219
|
-
ctx.matched.params,
|
|
220
|
-
freshHandlerContext,
|
|
221
|
-
true,
|
|
222
|
-
undefined,
|
|
223
|
-
// Skip intercept middleware: this is a post-response background
|
|
224
|
-
// re-render to refresh a stale cached route. The foreground
|
|
225
|
-
// already ran the middleware; re-running it would double its
|
|
226
|
-
// side effects and a short-circuit Response would abort the write.
|
|
227
|
-
{ skipMiddleware: true },
|
|
228
|
-
),
|
|
229
|
-
),
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const completeSegments = [...freshSegments, ...freshInterceptSegments];
|
|
234
|
-
requestCtx._handleStore.seal();
|
|
235
|
-
await cacheScope.cacheRoute(
|
|
236
|
-
ctx.pathname,
|
|
237
|
-
ctx.matched.params,
|
|
238
|
-
completeSegments,
|
|
239
|
-
ctx.isIntercept,
|
|
306
|
+
cacheScope,
|
|
307
|
+
routerCtx,
|
|
240
308
|
);
|
|
241
309
|
if (INTERNAL_RANGO_DEBUG) {
|
|
242
310
|
const dur = performance.now() - start;
|
|
243
311
|
console.log(
|
|
244
|
-
`[RSC Background][req:${reqId}] SWR revalidation ${ctx.pathname} (${dur.toFixed(2)}ms) segments=${
|
|
312
|
+
`[RSC Background][req:${reqId}] SWR revalidation ${ctx.pathname} (${dur.toFixed(2)}ms) segments=${count}`,
|
|
245
313
|
);
|
|
246
314
|
}
|
|
247
315
|
debugLog("backgroundRevalidation", "revalidation complete", {
|
|
@@ -258,9 +326,6 @@ export function withBackgroundRevalidation<TEnv>(
|
|
|
258
326
|
pathname: ctx.pathname,
|
|
259
327
|
error: String(error),
|
|
260
328
|
});
|
|
261
|
-
} finally {
|
|
262
|
-
requestCtx._handleStore = originalHandleStore;
|
|
263
|
-
ctx.Store.metrics = savedMetrics;
|
|
264
329
|
}
|
|
265
330
|
});
|
|
266
331
|
};
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
* - Request object
|
|
92
92
|
* - Action context (if POST)
|
|
93
93
|
*/
|
|
94
|
-
import type { ResolvedSegment } from "../../types.js";
|
|
94
|
+
import type { InternalHandlerContext, ResolvedSegment } from "../../types.js";
|
|
95
95
|
import type { EntryData } from "../../server/context.js";
|
|
96
96
|
import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
97
97
|
import { getRouterContext, type RouterContext } from "../router-context.js";
|
|
@@ -103,7 +103,11 @@ import {
|
|
|
103
103
|
_getRequestContext,
|
|
104
104
|
type RequestContext,
|
|
105
105
|
} from "../../server/request-context.js";
|
|
106
|
-
import {
|
|
106
|
+
import {
|
|
107
|
+
createShellImplicitDocScope,
|
|
108
|
+
type CacheScope,
|
|
109
|
+
} from "../../cache/cache-scope.js";
|
|
110
|
+
import { ShellRecordUnavailableError } from "../../cache/shell-snapshot.js";
|
|
107
111
|
import { prerenderStoreShortCircuits } from "../navigation-snapshot.js";
|
|
108
112
|
import { paramsEqual } from "../params-util.js";
|
|
109
113
|
|
|
@@ -160,6 +164,7 @@ async function ensurePrerenderDeps() {
|
|
|
160
164
|
// awaits before reaching this point (workerd can disrupt ALS mid-pipeline).
|
|
161
165
|
async function* resolveFreshLoadersAndYield<TEnv>(
|
|
162
166
|
ctx: MatchContext<TEnv>,
|
|
167
|
+
entries: EntryData[],
|
|
163
168
|
state: MatchPipelineState,
|
|
164
169
|
pipelineStart: number,
|
|
165
170
|
ms: MatchContext<TEnv>["metricsStore"],
|
|
@@ -171,7 +176,7 @@ async function* resolveFreshLoadersAndYield<TEnv>(
|
|
|
171
176
|
if (ctx.isFullMatch) {
|
|
172
177
|
if (resolveLoadersOnly) {
|
|
173
178
|
const loaderSegments = await ctx.Store.run(() =>
|
|
174
|
-
resolveLoadersOnly(
|
|
179
|
+
resolveLoadersOnly(entries, ctx.handlerContext),
|
|
175
180
|
);
|
|
176
181
|
state.matchedIds = state.cachedMatchedIds!;
|
|
177
182
|
for (const segment of loaderSegments) {
|
|
@@ -184,7 +189,7 @@ async function* resolveFreshLoadersAndYield<TEnv>(
|
|
|
184
189
|
if (resolveLoadersOnlyWithRevalidation) {
|
|
185
190
|
const loaderResult = await ctx.Store.run(() =>
|
|
186
191
|
resolveLoadersOnlyWithRevalidation(
|
|
187
|
-
|
|
192
|
+
entries,
|
|
188
193
|
ctx.handlerContext,
|
|
189
194
|
ctx.clientSegmentSet,
|
|
190
195
|
ctx.prevParams,
|
|
@@ -301,6 +306,7 @@ async function* yieldFromStore<TEnv>(
|
|
|
301
306
|
// Resolve loaders fresh (loaders are never pre-rendered/cached).
|
|
302
307
|
yield* resolveFreshLoadersAndYield(
|
|
303
308
|
ctx,
|
|
309
|
+
ctx.entries,
|
|
304
310
|
state,
|
|
305
311
|
pipelineStart,
|
|
306
312
|
ctx.metricsStore,
|
|
@@ -448,6 +454,8 @@ export function withCacheLookup<TEnv>(
|
|
|
448
454
|
buildEntryRevalidateMap,
|
|
449
455
|
resolveLoadersOnlyWithRevalidation,
|
|
450
456
|
resolveLoadersOnly,
|
|
457
|
+
resolveAllSegments,
|
|
458
|
+
resolveAllSegmentsWithRevalidation,
|
|
451
459
|
} = getRouterContext<TEnv>();
|
|
452
460
|
|
|
453
461
|
if (prerenderStoreShortCircuits(ctx.matched.pr, ctx.request)) {
|
|
@@ -501,6 +509,15 @@ export function withCacheLookup<TEnv>(
|
|
|
501
509
|
}
|
|
502
510
|
}
|
|
503
511
|
|
|
512
|
+
// A document HIT tail replays the handler layer through the implicit doc
|
|
513
|
+
// scope and never runs a handler: without that scope (a context that lost
|
|
514
|
+
// the marker before the scope resolved), fail like a lookup miss instead
|
|
515
|
+
// of falling through to the handlers below.
|
|
516
|
+
const tailMarker = pipelineReqCtx?._shellImplicitCache;
|
|
517
|
+
if (tailMarker?.docTail && !ctx.cacheScope?.isShellImplicitDocScope) {
|
|
518
|
+
throw new ShellRecordUnavailableError(tailMarker.fixedDocKey);
|
|
519
|
+
}
|
|
520
|
+
|
|
504
521
|
if (ctx.isAction || !ctx.cacheScope?.enabled) {
|
|
505
522
|
yield* source;
|
|
506
523
|
if (ms) {
|
|
@@ -513,13 +530,20 @@ export function withCacheLookup<TEnv>(
|
|
|
513
530
|
return;
|
|
514
531
|
}
|
|
515
532
|
|
|
533
|
+
// A record's loader-owned handle values claim their loader, so its own
|
|
534
|
+
// cache() HIT does not replay them again (restoreHandles).
|
|
535
|
+
const claimLoaderPushes = (ctx.handlerContext as InternalHandlerContext)
|
|
536
|
+
._claimLoaderPushes;
|
|
516
537
|
const explicitLookup = await ctx.cacheScope.lookupRouteDetailed(
|
|
517
538
|
ctx.pathname,
|
|
518
539
|
ctx.matched.params,
|
|
519
540
|
ctx.isIntercept,
|
|
541
|
+
claimLoaderPushes,
|
|
520
542
|
);
|
|
521
543
|
let cacheResult =
|
|
522
544
|
explicitLookup.status === "hit" ? explicitLookup.result : null;
|
|
545
|
+
// The scope whose record answered decides which entries it covers.
|
|
546
|
+
let hitScope: CacheScope = ctx.cacheScope;
|
|
523
547
|
|
|
524
548
|
// PPR navigation replay composed with a route-derived cache() scope. The
|
|
525
549
|
// explicit tier stays authoritative: its hit serves under its own
|
|
@@ -553,9 +577,13 @@ export function withCacheLookup<TEnv>(
|
|
|
553
577
|
// no-eligible-snapshot path purely for truthful status) inert: a
|
|
554
578
|
// store-less marker minting a doc scope here would resolve the APP
|
|
555
579
|
// store and read the REAL doc: partition — a cross-partition serve.
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
580
|
+
hitScope = createShellImplicitDocScope(replayMarker);
|
|
581
|
+
cacheResult = await hitScope.lookupRoute(
|
|
582
|
+
ctx.pathname,
|
|
583
|
+
ctx.matched.params,
|
|
584
|
+
ctx.isIntercept,
|
|
585
|
+
claimLoaderPushes,
|
|
586
|
+
);
|
|
559
587
|
} else if (explicitLookup.status === "bypass") {
|
|
560
588
|
// condition() refused at lookup time (the gate only pre-decides the
|
|
561
589
|
// static cache(false) case) — report cache-disabled truthfully.
|
|
@@ -567,6 +595,13 @@ export function withCacheLookup<TEnv>(
|
|
|
567
595
|
}
|
|
568
596
|
|
|
569
597
|
if (!cacheResult) {
|
|
598
|
+
// A document shell HIT tail replays the handler layer from the entry's
|
|
599
|
+
// doc record and must never run a handler behind the committed prelude:
|
|
600
|
+
// a record that did not hit (it failed to decode, or the entry lost it)
|
|
601
|
+
// ends the tail here; serveShellHit degrades the response.
|
|
602
|
+
if (replayMarker?.docTail) {
|
|
603
|
+
throw new ShellRecordUnavailableError(replayMarker.fixedDocKey);
|
|
604
|
+
}
|
|
570
605
|
yield* source;
|
|
571
606
|
if (ms) {
|
|
572
607
|
ms.metrics.push({
|
|
@@ -578,11 +613,68 @@ export function withCacheLookup<TEnv>(
|
|
|
578
613
|
return;
|
|
579
614
|
}
|
|
580
615
|
|
|
616
|
+
// Entries above the cache() boundary are not in the record: resolve them
|
|
617
|
+
// fresh, exactly as an uncached render of this request would.
|
|
618
|
+
const boundaryIndex =
|
|
619
|
+
hitScope.boundary === undefined
|
|
620
|
+
? 0
|
|
621
|
+
: Math.max(
|
|
622
|
+
0,
|
|
623
|
+
ctx.entries.findIndex((e) => e.shortCode === hitScope.boundary),
|
|
624
|
+
);
|
|
625
|
+
let liveSegments: ResolvedSegment[] = [];
|
|
626
|
+
let liveMatchedIds: string[] = [];
|
|
627
|
+
if (boundaryIndex > 0) {
|
|
628
|
+
const liveEntries = ctx.entries.slice(0, boundaryIndex);
|
|
629
|
+
const live: { segments: ResolvedSegment[]; matchedIds: string[] } =
|
|
630
|
+
await ctx.Store.run(async () => {
|
|
631
|
+
if (!ctx.isFullMatch) {
|
|
632
|
+
return resolveAllSegmentsWithRevalidation(
|
|
633
|
+
liveEntries,
|
|
634
|
+
ctx.routeKey,
|
|
635
|
+
ctx.matched.params,
|
|
636
|
+
ctx.handlerContext,
|
|
637
|
+
ctx.clientSegmentSet,
|
|
638
|
+
ctx.prevParams,
|
|
639
|
+
ctx.request,
|
|
640
|
+
ctx.prevUrl,
|
|
641
|
+
ctx.url,
|
|
642
|
+
ctx.actionContext,
|
|
643
|
+
ctx.interceptResult,
|
|
644
|
+
ctx.localRouteName,
|
|
645
|
+
ctx.pathname,
|
|
646
|
+
ctx.stale,
|
|
647
|
+
ctx.entries,
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
// The full chain keeps a bare cache() marker, which also sits in
|
|
651
|
+
// its layout's orphan list, out of the live pass: the record
|
|
652
|
+
// supplies it and its subtree (issue #918).
|
|
653
|
+
const segments = await resolveAllSegments(
|
|
654
|
+
liveEntries,
|
|
655
|
+
ctx.routeKey,
|
|
656
|
+
ctx.matched.params,
|
|
657
|
+
ctx.handlerContext,
|
|
658
|
+
ctx.loaderPromises,
|
|
659
|
+
{ chain: ctx.entries },
|
|
660
|
+
);
|
|
661
|
+
return { segments, matchedIds: segments.map((s) => s.id) };
|
|
662
|
+
});
|
|
663
|
+
// The record supplies every covered segment.
|
|
664
|
+
liveSegments = live.segments.filter(
|
|
665
|
+
(s) => !hitScope.covers(s.id, s.namespace),
|
|
666
|
+
);
|
|
667
|
+
liveMatchedIds = live.matchedIds.filter((id) => !hitScope.covers(id));
|
|
668
|
+
}
|
|
669
|
+
|
|
581
670
|
state.cacheHit = true;
|
|
582
671
|
state.cacheSource = "runtime";
|
|
583
672
|
state.shouldRevalidate = cacheResult.shouldRevalidate;
|
|
584
673
|
state.cachedSegments = cacheResult.segments;
|
|
585
|
-
state.cachedMatchedIds =
|
|
674
|
+
state.cachedMatchedIds = [
|
|
675
|
+
...liveMatchedIds,
|
|
676
|
+
...cacheResult.segments.map((s) => s.id),
|
|
677
|
+
];
|
|
586
678
|
const pprTransitionDecisions = pipelineReqCtx?._pprTransitionDecisions;
|
|
587
679
|
|
|
588
680
|
const canCheckSegmentRevalidation =
|
|
@@ -593,6 +685,8 @@ export function withCacheLookup<TEnv>(
|
|
|
593
685
|
? buildEntryRevalidateMap(ctx.entries)
|
|
594
686
|
: undefined;
|
|
595
687
|
|
|
688
|
+
yield* liveSegments;
|
|
689
|
+
|
|
596
690
|
for (const segment of cacheResult.segments) {
|
|
597
691
|
if (!ctx.clientSegmentSet.has(segment.id)) {
|
|
598
692
|
if (isTraceActive()) {
|
|
@@ -708,13 +802,19 @@ export function withCacheLookup<TEnv>(
|
|
|
708
802
|
if (barrierReqCtx._treeHasStreaming === undefined) {
|
|
709
803
|
barrierReqCtx._treeHasStreaming = treeHasStreaming(ctx.entries);
|
|
710
804
|
}
|
|
711
|
-
barrierReqCtx._resolveRenderBarrier(
|
|
805
|
+
barrierReqCtx._resolveRenderBarrier(
|
|
806
|
+
liveSegments.length > 0
|
|
807
|
+
? [...liveSegments, ...cacheResult.segments]
|
|
808
|
+
: cacheResult.segments,
|
|
809
|
+
);
|
|
712
810
|
}
|
|
713
811
|
|
|
714
812
|
// Resolve loaders fresh (loaders are never cached). Shared with the
|
|
715
|
-
// prerender-store path via resolveFreshLoadersAndYield.
|
|
813
|
+
// prerender-store path via resolveFreshLoadersAndYield. The live pass
|
|
814
|
+
// already resolved the loaders of the entries above the boundary.
|
|
716
815
|
yield* resolveFreshLoadersAndYield(
|
|
717
816
|
ctx,
|
|
817
|
+
ctx.entries.slice(boundaryIndex),
|
|
718
818
|
state,
|
|
719
819
|
pipelineStart,
|
|
720
820
|
ms,
|