vinext 1.0.0 → 1.1.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 +72 -1
- package/THIRD_PARTY_LICENSES.md +26 -0
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/lifecycle.js +10 -10
- package/dist/build/pages-client-assets-module.js +6 -1
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender-paths.js +6 -85
- package/dist/build/prerender.d.ts +8 -1
- package/dist/build/prerender.js +167 -46
- package/dist/build/run-prerender.js +4 -3
- package/dist/build/server-entry.d.ts +2 -0
- package/dist/build/server-entry.js +7 -1
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/client/browser-globals.d.ts +4 -0
- package/dist/client/browser-globals.js +5 -0
- package/dist/client/navigation-runtime.d.ts +11 -1
- package/dist/client/navigation-runtime.js +3 -3
- package/dist/config/config-matchers.js +3 -1
- package/dist/config/dotenv.js +14 -3
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +18 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +67 -45
- package/dist/index.d.ts +4 -1
- package/dist/index.js +200 -100
- package/dist/init-cloudflare.d.ts +1 -1
- package/dist/init-cloudflare.js +6 -6
- package/dist/init-platform.js +1 -1
- package/dist/init.js +4 -2
- package/dist/plugins/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/commonjs-syntax.d.ts +16 -0
- package/dist/plugins/commonjs-syntax.js +22 -0
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +54 -3
- package/dist/plugins/import-meta-url.js +6 -6
- package/dist/plugins/og-asset-ownership.d.ts +2 -0
- package/dist/plugins/og-asset-ownership.js +24 -13
- package/dist/plugins/og-assets.d.ts +18 -0
- package/dist/plugins/og-assets.js +50 -8
- package/dist/plugins/og-harfbuzz.js +38 -27
- package/dist/plugins/optimize-imports.js +2 -1
- package/dist/plugins/require-context.d.ts +1 -0
- package/dist/plugins/require-context.js +28 -1
- package/dist/plugins/scan-build-css.d.ts +12 -0
- package/dist/plugins/scan-build-css.js +39 -0
- package/dist/plugins/strip-server-exports.d.ts +2 -0
- package/dist/plugins/strip-server-exports.js +3 -1
- package/dist/plugins/transform-result.d.ts +18 -0
- package/dist/plugins/transform-result.js +23 -2
- package/dist/plugins/typeof-window.d.ts +10 -0
- package/dist/plugins/typeof-window.js +33 -9
- package/dist/routing/app-route-graph.d.ts +0 -1
- package/dist/routing/app-route-graph.js +2 -4
- package/dist/routing/app-route-ids.d.ts +3 -0
- package/dist/routing/app-route-ids.js +6 -0
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.js +17 -7
- package/dist/server/app-bfcache-id.d.ts +1 -0
- package/dist/server/app-bfcache-id.js +7 -1
- package/dist/server/app-bfcache-identity.js +1 -2
- package/dist/server/app-browser-entry.js +15 -9
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-hydration.d.ts +1 -1
- package/dist/server/app-browser-hydration.js +2 -2
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +94 -11
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-stream.d.ts +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -1
- package/dist/server/app-history-state.js +9 -5
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +65 -44
- package/dist/server/app-page-cache.d.ts +5 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +47 -30
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +2 -2
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -118
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +1 -2
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +55 -33
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-search-params-observation.js +1 -1
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +7 -1
- package/dist/server/app-page-tracing.js +2 -1
- package/dist/server/app-pages-bridge.js +3 -2
- package/dist/server/app-render-abort-error.d.ts +3 -0
- package/dist/server/app-render-abort-error.js +8 -0
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +8 -11
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- package/dist/server/app-route-handler-cache.d.ts +2 -1
- package/dist/server/app-route-handler-cache.js +11 -7
- package/dist/server/app-route-handler-dispatch.js +11 -4
- package/dist/server/app-route-handler-execution.d.ts +9 -1
- package/dist/server/app-route-handler-execution.js +28 -13
- package/dist/server/app-route-handler-policy.js +2 -2
- package/dist/server/app-route-handler-response.d.ts +1 -1
- package/dist/server/app-route-handler-response.js +14 -5
- package/dist/server/app-router-entry.d.ts +2 -1
- package/dist/server/app-router-entry.js +8 -12
- package/dist/server/app-rsc-errors.d.ts +0 -1
- package/dist/server/app-rsc-errors.js +2 -6
- package/dist/server/app-rsc-handler.d.ts +5 -0
- package/dist/server/app-rsc-handler.js +229 -102
- package/dist/server/app-rsc-request-normalization.d.ts +4 -2
- package/dist/server/app-rsc-request-normalization.js +7 -4
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +6 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +37 -20
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +9 -7
- package/dist/server/app-ssr-search-params-gate.js +1 -1
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +35 -16
- package/dist/server/app-worker-stages.d.ts +2 -2
- package/dist/server/app-worker-stages.js +3 -3
- package/dist/server/cache-control.js +3 -11
- package/dist/server/cacheability-request.js +56 -52
- package/dist/server/config-headers.js +3 -1
- package/dist/server/dev-server.js +23 -5
- package/dist/server/headers.d.ts +16 -0
- package/dist/server/headers.js +19 -1
- package/dist/server/http-error-responses.js +1 -0
- package/dist/server/image-optimization.d.ts +16 -0
- package/dist/server/image-optimization.js +26 -6
- package/dist/server/isr-cache.d.ts +2 -0
- package/dist/server/isr-cache.js +8 -3
- package/dist/server/metadata-route-response.js +94 -37
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/multi-stage.d.ts +8 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-api-route.js +8 -2
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +73 -22
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-page-data.d.ts +6 -1
- package/dist/server/pages-page-data.js +71 -65
- package/dist/server/pages-page-handler.js +50 -15
- package/dist/server/pages-page-response.js +3 -1
- package/dist/server/pages-request-pipeline.d.ts +2 -1
- package/dist/server/pages-request-pipeline.js +20 -5
- package/dist/server/pages-request-stage-entry.js +14 -8
- package/dist/server/prerender-manifest.d.ts +6 -0
- package/dist/server/prerender-manifest.js +1 -1
- package/dist/server/prod-server.d.ts +8 -7
- package/dist/server/prod-server.js +152 -78
- package/dist/server/request-pipeline.d.ts +20 -8
- package/dist/server/request-pipeline.js +21 -7
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/response-stage-cacheability.js +1 -1
- package/dist/server/seed-cache.js +10 -7
- package/dist/server/socket-error-backstop.d.ts +14 -0
- package/dist/server/socket-error-backstop.js +27 -4
- package/dist/server/worker-revalidation-context.d.ts +2 -1
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/server/workers-tracing.d.ts +17 -0
- package/dist/server/workers-tracing.js +48 -8
- package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +2 -40
- package/dist/shims/cache-callable-runtime.js +50 -168
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-request-state.d.ts +18 -14
- package/dist/shims/cache-request-state.js +33 -21
- package/dist/shims/cache-runtime.d.ts +6 -19
- package/dist/shims/cache-runtime.js +168 -226
- package/dist/shims/cache.d.ts +3 -2
- package/dist/shims/cache.js +8 -5
- package/dist/shims/cacheability-classification.d.ts +8 -1
- package/dist/shims/cacheability-classification.js +2 -2
- package/dist/shims/cdn-cache.d.ts +10 -1
- package/dist/shims/cdn-cache.js +16 -9
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- package/dist/shims/error.d.ts +4 -18
- package/dist/shims/error.js +17 -10
- package/dist/shims/error.react-server.d.ts +4 -6
- package/dist/shims/error.react-server.js +4 -1
- package/dist/shims/fetch-cache.d.ts +6 -0
- package/dist/shims/fetch-cache.js +23 -4
- package/dist/shims/form.js +1 -1
- package/dist/shims/headers.d.ts +19 -69
- package/dist/shims/headers.js +82 -183
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
- package/dist/shims/internal/cache-context-accessor.js +15 -0
- package/dist/shims/internal/headers-state.d.ts +73 -0
- package/dist/shims/internal/headers-state.js +157 -0
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +16 -6
- package/dist/shims/request-context.d.ts +9 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/root-params.js +1 -1
- package/dist/shims/server.js +52 -2
- package/dist/shims/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/encode-cache-tag.d.ts +1 -0
- package/dist/utils/encode-cache-tag.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/dist/utils/vite-cli-invocation.js +8 -1
- package/package.json +8 -4
- package/dist/server/metadata-route-cache-policy.d.ts +0 -5
- package/dist/server/metadata-route-cache-policy.js +0 -6
|
@@ -6,12 +6,16 @@ import { isRouteCacheabilityProbe, recordRouteCacheabilityProbeBailout } from ".
|
|
|
6
6
|
import { getDataCacheHandler } from "./cache-handler.js";
|
|
7
7
|
import { suppressHangingPromiseAbortRejections } from "./internal/make-hanging-promise.js";
|
|
8
8
|
import { createPprFallbackShellSuspensePromise, trackPprFallbackShellCacheTask } from "./ppr-fallback-shell.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
9
|
+
import { markDynamicUsage, throwIfInsideCacheScope } from "./internal/headers-state.js";
|
|
10
|
+
import { isDraftModeEnabled } from "./headers.js";
|
|
11
|
+
import { _registerCacheContextAccessor } from "./internal/cache-context-accessor.js";
|
|
12
|
+
import { _hasPendingRevalidatedTag, _setRequestScopedCacheLife, cacheLifeProfiles, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
|
|
13
|
+
import { addCollectedRequestTags, getCurrentFetchSoftTags, runWithDetachedFetchObservations } from "./fetch-cache.js";
|
|
14
|
+
import { hasUseCacheLayoutMarker, hasUseCachePageMarker, isUseCacheFunctionReference, withoutUseCacheSegmentMarker } from "./internal/app-page-props-cache-key.js";
|
|
15
|
+
import { getFallbackParamsSnapshot, makeThenableParams, restoreThenableParams } from "./thenable-params.js";
|
|
14
16
|
import { getCurrentRootParams } from "./root-params.js";
|
|
17
|
+
import { flightArgumentsKey, restoreFlightReply, snapshotFlightReply } from "./cache-flight-arguments.js";
|
|
18
|
+
import { cache } from "react";
|
|
15
19
|
//#region src/shims/cache-runtime.ts
|
|
16
20
|
/**
|
|
17
21
|
* "use cache" runtime
|
|
@@ -34,14 +38,17 @@ import { getCurrentRootParams } from "./root-params.js";
|
|
|
34
38
|
* and all RSC-serializable types — unlike JSON.stringify which silently
|
|
35
39
|
* drops $$typeof Symbols and function values.
|
|
36
40
|
*
|
|
37
|
-
* When RSC APIs are unavailable (e.g. in unit tests), falls back to
|
|
38
|
-
* JSON.stringify/parse with the same stableStringify cache key generation.
|
|
39
|
-
*
|
|
40
41
|
* Cache variants:
|
|
41
42
|
* - "use cache" — shared cache (default profile)
|
|
42
43
|
* - "use cache: remote" — shared cache (explicit)
|
|
43
44
|
* - "use cache: private" — per-request cache (not shared across requests)
|
|
44
45
|
*/
|
|
46
|
+
const replayableFunctions = /* @__PURE__ */ new WeakMap();
|
|
47
|
+
function replayCachedFunction(fn, args) {
|
|
48
|
+
const replay = replayableFunctions.get(fn);
|
|
49
|
+
if (!replay || args.version !== 1) throw new Error("Invalid cache function arguments");
|
|
50
|
+
return replay(args);
|
|
51
|
+
}
|
|
45
52
|
/** Threshold below which expire is considered "dynamic" (5 minutes in seconds). */
|
|
46
53
|
const DYNAMIC_EXPIRE = 300;
|
|
47
54
|
/**
|
|
@@ -122,16 +129,9 @@ function buildUseCacheKey(id, keySeed, argsKey) {
|
|
|
122
129
|
const scopedId = keySeed ? `build:${encodeURIComponent(keySeed)}:${id}` : id;
|
|
123
130
|
return argsKey === void 0 ? `use-cache:${scopedId}` : `use-cache:${scopedId}:${argsKey}`;
|
|
124
131
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (_rscModule !== NOT_LOADED) return _rscModule;
|
|
129
|
-
try {
|
|
130
|
-
_rscModule = await import("@vitejs/plugin-rsc/react/rsc");
|
|
131
|
-
} catch {
|
|
132
|
-
_rscModule = null;
|
|
133
|
-
}
|
|
134
|
-
return _rscModule;
|
|
132
|
+
let _rscModule;
|
|
133
|
+
function getRscModule() {
|
|
134
|
+
return _rscModule ??= import("@vitejs/plugin-rsc/react/rsc");
|
|
135
135
|
}
|
|
136
136
|
/** Collect a ReadableStream<Uint8Array> into a single Uint8Array. */
|
|
137
137
|
async function collectStream(stream) {
|
|
@@ -169,55 +169,22 @@ function uint8ToStream(bytes) {
|
|
|
169
169
|
} });
|
|
170
170
|
}
|
|
171
171
|
async function serializeCacheResult(result, rsc) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
throw serializationError?.value ?? error;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
const body = JSON.stringify(result);
|
|
191
|
-
return body === void 0 ? null : {
|
|
192
|
-
result,
|
|
193
|
-
cacheEntry: {
|
|
194
|
-
body,
|
|
195
|
-
headers: {}
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Convert an encodeReply result (string | FormData) to a cache key string.
|
|
201
|
-
* For FormData (binary args), produces a deterministic SHA-256 hash over
|
|
202
|
-
* the sorted entries. We can't hash `new Response(formData).arrayBuffer()`
|
|
203
|
-
* because multipart boundaries are non-deterministic across serializations.
|
|
204
|
-
*
|
|
205
|
-
* Exported for testing.
|
|
206
|
-
*/
|
|
207
|
-
async function replyToCacheKey(reply) {
|
|
208
|
-
if (typeof reply === "string") return reply;
|
|
209
|
-
const entries = [...reply.entries()];
|
|
210
|
-
const valStr = (v) => typeof v === "string" ? v : v.name;
|
|
211
|
-
entries.sort((a, b) => a[0].localeCompare(b[0]) || valStr(a[1]).localeCompare(valStr(b[1])));
|
|
212
|
-
const parts = [];
|
|
213
|
-
for (const [name, value] of entries) if (typeof value === "string") parts.push(`${name}=s:${value}`);
|
|
214
|
-
else {
|
|
215
|
-
const bytes = new Uint8Array(await value.arrayBuffer());
|
|
216
|
-
parts.push(`${name}=b:${value.type}:${value.size}:${Buffer.from(bytes).toString("base64")}`);
|
|
172
|
+
let serializationError;
|
|
173
|
+
const [returnStream, savedStream] = rsc.renderToReadableStream(result, { onError(error) {
|
|
174
|
+
serializationError ??= { value: error };
|
|
175
|
+
} }).tee();
|
|
176
|
+
try {
|
|
177
|
+
const [deserializedResult, bytes] = await Promise.all([rsc.createFromReadableStream(returnStream, {}, { preserveServerReferences: true }), collectStream(savedStream)]);
|
|
178
|
+
return {
|
|
179
|
+
result: deserializedResult,
|
|
180
|
+
cacheEntry: serializationError ? null : {
|
|
181
|
+
body: uint8ToBase64(bytes),
|
|
182
|
+
headers: { [VINEXT_RSC_MARKER_HEADER]: "1" }
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
} catch (error) {
|
|
186
|
+
throw serializationError?.value ?? error;
|
|
217
187
|
}
|
|
218
|
-
const payload = new TextEncoder().encode(parts.join("\0"));
|
|
219
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", payload);
|
|
220
|
-
return Buffer.from(new Uint8Array(hashBuffer)).toString("base64url");
|
|
221
188
|
}
|
|
222
189
|
/**
|
|
223
190
|
* Resolve collected cacheLife configs into a single effective config.
|
|
@@ -299,6 +266,17 @@ function propagateRootParamNamesToParent(names) {
|
|
|
299
266
|
if (!parent || parent.variant === "private") return;
|
|
300
267
|
for (const name of names) parent.readRootParamNames?.add(name);
|
|
301
268
|
}
|
|
269
|
+
function isServableCacheState(cacheState) {
|
|
270
|
+
if (cacheState === "expired") return false;
|
|
271
|
+
if (cacheState !== "stale") return true;
|
|
272
|
+
return shouldServeStaleUnstableCacheEntry() && process.env.VINEXT_PRERENDER !== "1" && !isRouteCacheabilityProbe();
|
|
273
|
+
}
|
|
274
|
+
function regenerateInBackground(id, regenerate) {
|
|
275
|
+
const regeneration = runWithDetachedCacheObservations(() => runWithDetachedFetchObservations(() => cacheContextStorage.exit(regenerate))).then(() => void 0, (error) => {
|
|
276
|
+
console.error(`[vinext] use cache: background regeneration failed for ${id}:`, error);
|
|
277
|
+
});
|
|
278
|
+
if (isInsideUnifiedScope()) getRequestContext().executionContext?.waitUntil(regeneration);
|
|
279
|
+
}
|
|
302
280
|
/**
|
|
303
281
|
* Register a function as a cached function. This is called by the Vite
|
|
304
282
|
* transform for each "use cache" function.
|
|
@@ -313,7 +291,7 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
313
291
|
const omitAppPageSearchParams = cacheVariant !== "private";
|
|
314
292
|
const cacheFunctionId = options.serverReferenceId ? JSON.stringify([id, options.serverReferenceId]) : id;
|
|
315
293
|
const isDev = typeof process !== "undefined" && process.env.NODE_ENV === "development";
|
|
316
|
-
const
|
|
294
|
+
const invoke = (args, replay) => {
|
|
317
295
|
if (cacheVariant === "private") {
|
|
318
296
|
const parentCtx = cacheContextStorage.getStore();
|
|
319
297
|
if (parentCtx && parentCtx.variant !== "private") throwPrivateUseCacheInsidePublicUseCacheError();
|
|
@@ -344,40 +322,60 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
344
322
|
}
|
|
345
323
|
}
|
|
346
324
|
return trackPprFallbackShellCacheTask(async () => {
|
|
347
|
-
const
|
|
325
|
+
const codec = await getRscModule();
|
|
326
|
+
const clientReferences = codec.createClientTemporaryReferenceSet();
|
|
327
|
+
const serverReferences = codec.createTemporaryReferenceSet();
|
|
328
|
+
const rsc = {
|
|
329
|
+
...codec,
|
|
330
|
+
renderToReadableStream: (value, options) => codec.renderToReadableStream(value, {
|
|
331
|
+
...options,
|
|
332
|
+
temporaryReferences: serverReferences
|
|
333
|
+
}),
|
|
334
|
+
createFromReadableStream: (stream, options, context) => codec.createFromReadableStream(stream, {
|
|
335
|
+
...options,
|
|
336
|
+
temporaryReferences: clientReferences
|
|
337
|
+
}, context)
|
|
338
|
+
};
|
|
348
339
|
const keySeed = getUseCacheKeySeed();
|
|
349
|
-
const captures = options.decryptCaptures ? await options.decryptCaptures(args[0]) : void 0;
|
|
340
|
+
const captures = !replay && options.decryptCaptures ? await options.decryptCaptures(args[0]) : void 0;
|
|
350
341
|
const hasCaptureEnvelope = captures !== void 0;
|
|
351
|
-
const
|
|
342
|
+
const limitedArgs = options.argumentCount === void 0 ? args : hasCaptureEnvelope ? [args[0], ...args.slice(1, 1 + options.argumentCount)] : args.slice(0, options.argumentCount);
|
|
343
|
+
const pagePropsArgIndex = replay?.pagePropsIndex ?? limitedArgs.findIndex(hasUseCachePageMarker);
|
|
344
|
+
const layoutPropsArgIndex = replay?.layoutPropsIndex ?? limitedArgs.findIndex(hasUseCacheLayoutMarker);
|
|
352
345
|
const isPageInvocation = pagePropsArgIndex !== -1;
|
|
353
|
-
const
|
|
354
|
-
const admittedArgs =
|
|
346
|
+
const segmentPropsIndex = isPageInvocation ? pagePropsArgIndex : layoutPropsArgIndex;
|
|
347
|
+
const admittedArgs = segmentPropsIndex !== -1 && !replay ? replaceArgument(limitedArgs, segmentPropsIndex, withoutUseCacheSegmentMarker(limitedArgs[segmentPropsIndex], isPageInvocation)) : limitedArgs;
|
|
355
348
|
const executionArgs = hasCaptureEnvelope ? [captures, ...admittedArgs.slice(1)] : admittedArgs;
|
|
349
|
+
const outerParams = !replay && segmentPropsIndex !== -1 ? executionArgs[segmentPropsIndex].params : void 0;
|
|
350
|
+
const fallbackParams = getFallbackParamsSnapshot(outerParams);
|
|
351
|
+
const serializationArgs = fallbackParams ? replaceArgument(executionArgs, segmentPropsIndex, {
|
|
352
|
+
...executionArgs[segmentPropsIndex],
|
|
353
|
+
params: fallbackParams
|
|
354
|
+
}) : executionArgs;
|
|
356
355
|
const pagePropsIndex = omitAppPageSearchParams && isPageInvocation ? pagePropsArgIndex : void 0;
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const argsKey = processedArgs.length > 0 ? stableStringify(processedArgs) : void 0;
|
|
370
|
-
cacheKey = buildUseCacheKey(cacheFunctionId, keySeed, argsKey);
|
|
371
|
-
}
|
|
372
|
-
} catch {
|
|
373
|
-
return (await executeWithContext(fn, callArgs, cacheVariant)).result;
|
|
356
|
+
const keyArgs = pagePropsIndex === void 0 ? serializationArgs : toReplayablePageArgs(serializationArgs, pagePropsIndex);
|
|
357
|
+
const flightArguments = replay ?? await snapshotFlightReply(await rsc.encodeReply(keyArgs, { temporaryReferences: clientReferences }), isPageInvocation ? pagePropsArgIndex : void 0);
|
|
358
|
+
if (!replay && layoutPropsArgIndex !== -1) flightArguments.layoutPropsIndex = layoutPropsArgIndex;
|
|
359
|
+
let cacheKey = buildUseCacheKey(cacheFunctionId, keySeed, flightArgumentsKey(flightArguments));
|
|
360
|
+
let callArgs = await rsc.decodeReply(restoreFlightReply(flightArguments), { temporaryReferences: serverReferences });
|
|
361
|
+
if (segmentPropsIndex !== -1) {
|
|
362
|
+
const props = callArgs[segmentPropsIndex];
|
|
363
|
+
callArgs = replaceArgument(callArgs, segmentPropsIndex, {
|
|
364
|
+
...props,
|
|
365
|
+
params: restoreThenableParams(await props.params, outerParams)
|
|
366
|
+
});
|
|
367
|
+
if (pagePropsIndex !== void 0) callArgs = withErroringPageSearchParams(callArgs, pagePropsIndex);
|
|
374
368
|
}
|
|
369
|
+
if (fallbackParams) return (await executeWithContext(fn, callArgs, cacheVariant, rsc)).result;
|
|
375
370
|
if (cacheVariant === "private") {
|
|
376
371
|
const privateCache = _getPrivateState()._privateCache;
|
|
377
372
|
const privateHit = privateCache.get(cacheKey);
|
|
378
|
-
if (privateHit !== void 0)
|
|
373
|
+
if (privateHit !== void 0) {
|
|
374
|
+
if (privateHit.serialized) return rsc.createFromReadableStream(uint8ToStream(base64ToUint8(privateHit.serialized.body)), {}, { preserveServerReferences: true });
|
|
375
|
+
return privateHit.result;
|
|
376
|
+
}
|
|
379
377
|
const execution = await executeWithContext(fn, callArgs, cacheVariant, rsc);
|
|
380
|
-
if (execution.cacheable) privateCache.set(cacheKey, execution
|
|
378
|
+
if (execution.cacheable) privateCache.set(cacheKey, execution);
|
|
381
379
|
return execution.result;
|
|
382
380
|
}
|
|
383
381
|
if (isDev || isDraftModeEnabled()) return (await executeWithContext(fn, callArgs, cacheVariant, rsc)).result;
|
|
@@ -397,7 +395,7 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
397
395
|
console.error("[vinext] use cache: handler.get failed; treating as a cache miss:", error);
|
|
398
396
|
}
|
|
399
397
|
const redirectValue = existing?.value;
|
|
400
|
-
if (isRootParamRedirect(existing) && existing?.cacheState
|
|
398
|
+
if (isRootParamRedirect(existing) && isServableCacheState(existing?.cacheState) && rootParams && redirectValue?.kind === "FETCH" && !_hasPendingRevalidatedTag([...redirectValue.tags ?? [], ...softTags])) {
|
|
401
399
|
cacheKey = coarseCacheKey + computeRootParamsCacheKeySuffix(rootParams, addKnownRootParamNames(id, rootParamNamesFromTags(redirectValue.tags)));
|
|
402
400
|
try {
|
|
403
401
|
existing = await handler.get(cacheKey, {
|
|
@@ -409,78 +407,80 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
409
407
|
existing = null;
|
|
410
408
|
}
|
|
411
409
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
if (
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
recordRequestScopedCacheControl(existing.cacheControl);
|
|
419
|
-
return result;
|
|
410
|
+
const generate = async (propagate) => {
|
|
411
|
+
const { result, ctx, effectiveLife, collectedResult } = await runCachedFunctionWithContext(fn, callArgs, cacheVariant, (value) => serializeCacheResult(value, rsc));
|
|
412
|
+
const rootParamNames = ctx.readRootParamNames && ctx.readRootParamNames.size > 0 ? addKnownRootParamNames(id, ctx.readRootParamNames) : knownRootParamsByFunctionId.get(id);
|
|
413
|
+
if (propagate) {
|
|
414
|
+
recordRequestScopedCacheLife(effectiveLife);
|
|
415
|
+
propagateCacheTagsToRequest(ctx.tags);
|
|
420
416
|
}
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
encryptedArgs: await options.encodeInvocationArgs(pagePropsIndex === void 0 ? admittedArgs : toReplayablePageArgs(admittedArgs, pagePropsIndex)),
|
|
435
|
-
referenceId: options.serverReferenceId,
|
|
436
|
-
rootParams: Object.fromEntries(Object.entries(rootParams ?? {}).filter((entry) => entry[1] !== void 0)),
|
|
437
|
-
softTags
|
|
438
|
-
};
|
|
439
|
-
} catch {}
|
|
440
|
-
const serialized = collectedResult.cacheEntry;
|
|
441
|
-
const cacheValue = {
|
|
442
|
-
kind: "FETCH",
|
|
443
|
-
data: {
|
|
444
|
-
headers: serialized.headers,
|
|
445
|
-
body: serialized.body,
|
|
446
|
-
url: cacheKey
|
|
447
|
-
},
|
|
448
|
-
tags: ctx.tags,
|
|
449
|
-
revalidate: revalidateSeconds
|
|
450
|
-
};
|
|
451
|
-
const cacheContext = {
|
|
452
|
-
fetchCache: true,
|
|
453
|
-
tags: ctx.tags,
|
|
454
|
-
...cacheFunctionInvocation ? { cacheFunctionInvocation } : {},
|
|
455
|
-
cacheControl: {
|
|
456
|
-
revalidate: revalidateSeconds,
|
|
457
|
-
expire: effectiveLife.expire,
|
|
458
|
-
stale: effectiveLife.stale
|
|
459
|
-
}
|
|
460
|
-
};
|
|
461
|
-
if (rootParamNames && rootParamNames.size > 0 && rootParams) {
|
|
462
|
-
const specificCacheKey = coarseCacheKey + computeRootParamsCacheKeySuffix(rootParams, rootParamNames);
|
|
463
|
-
const redirectTags = [...ctx.tags, ...[...rootParamNames].map((name) => ROOT_PARAM_TAG_PREFIX + name)];
|
|
464
|
-
await handler.set(coarseCacheKey, {
|
|
417
|
+
const revalidateSeconds = effectiveLife.revalidate ?? cacheLifeProfiles.default.revalidate ?? 900;
|
|
418
|
+
if (collectedResult?.cacheEntry) try {
|
|
419
|
+
let cacheFunctionInvocation;
|
|
420
|
+
if (options.serverReferenceId && options.encodeInvocation) try {
|
|
421
|
+
cacheFunctionInvocation = {
|
|
422
|
+
encryptedArgs: await options.encodeInvocation(flightArguments),
|
|
423
|
+
referenceId: options.serverReferenceId,
|
|
424
|
+
rootParams: Object.fromEntries(Object.entries(rootParams ?? {}).filter((entry) => entry[1] !== void 0)),
|
|
425
|
+
softTags
|
|
426
|
+
};
|
|
427
|
+
} catch {}
|
|
428
|
+
const serialized = collectedResult.cacheEntry;
|
|
429
|
+
const cacheValue = {
|
|
465
430
|
kind: "FETCH",
|
|
466
431
|
data: {
|
|
467
|
-
headers:
|
|
468
|
-
body:
|
|
469
|
-
url:
|
|
432
|
+
headers: serialized.headers,
|
|
433
|
+
body: serialized.body,
|
|
434
|
+
url: cacheKey
|
|
470
435
|
},
|
|
471
|
-
tags:
|
|
436
|
+
tags: ctx.tags,
|
|
472
437
|
revalidate: revalidateSeconds
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
438
|
+
};
|
|
439
|
+
const cacheContext = {
|
|
440
|
+
fetchCache: true,
|
|
441
|
+
tags: ctx.tags,
|
|
442
|
+
...cacheFunctionInvocation ? { cacheFunctionInvocation } : {},
|
|
443
|
+
cacheControl: {
|
|
444
|
+
revalidate: revalidateSeconds,
|
|
445
|
+
expire: effectiveLife.expire,
|
|
446
|
+
stale: effectiveLife.stale
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
if (rootParamNames && rootParamNames.size > 0 && rootParams) {
|
|
450
|
+
const specificCacheKey = coarseCacheKey + computeRootParamsCacheKeySuffix(rootParams, rootParamNames);
|
|
451
|
+
const redirectTags = [...ctx.tags, ...[...rootParamNames].map((name) => ROOT_PARAM_TAG_PREFIX + name)];
|
|
452
|
+
await handler.set(coarseCacheKey, {
|
|
453
|
+
kind: "FETCH",
|
|
454
|
+
data: {
|
|
455
|
+
headers: { [ROOT_PARAM_REDIRECT_HEADER]: "1" },
|
|
456
|
+
body: "",
|
|
457
|
+
url: coarseCacheKey
|
|
458
|
+
},
|
|
459
|
+
tags: redirectTags,
|
|
460
|
+
revalidate: revalidateSeconds
|
|
461
|
+
}, {
|
|
462
|
+
...cacheContext,
|
|
463
|
+
tags: redirectTags
|
|
464
|
+
});
|
|
465
|
+
cacheValue.data.url = specificCacheKey;
|
|
466
|
+
await handler.set(specificCacheKey, cacheValue, cacheContext);
|
|
467
|
+
} else await handler.set(cacheKey, cacheValue, cacheContext);
|
|
468
|
+
} catch {}
|
|
469
|
+
return collectedResult ? collectedResult.result : result;
|
|
470
|
+
};
|
|
471
|
+
if (existing?.value && existing.value.kind === "FETCH" && existing.value.data.headers["x-vinext-rsc"] === "1" && isServableCacheState(existing.cacheState) && !_hasPendingRevalidatedTag([...existing.value.tags ?? [], ...softTags])) try {
|
|
472
|
+
propagateRootParamNamesToParent(knownRootParamsByFunctionId.get(id));
|
|
473
|
+
propagateCacheTagsToRequest(existing.value.tags);
|
|
474
|
+
const result = await rsc.createFromReadableStream(uint8ToStream(base64ToUint8(existing.value.data.body)), {}, { preserveServerReferences: true });
|
|
475
|
+
recordRequestScopedCacheControl(existing.cacheControl);
|
|
476
|
+
if (existing.cacheState === "stale") regenerateInBackground(id, () => generate(false));
|
|
477
|
+
return result;
|
|
480
478
|
} catch {}
|
|
481
|
-
return
|
|
479
|
+
return generate(true);
|
|
482
480
|
}, cacheVariant);
|
|
483
481
|
};
|
|
482
|
+
const cachedFn = memoizeInCacheScope((...args) => invoke(args));
|
|
483
|
+
replayableFunctions.set(cachedFn, (data) => invoke([], data));
|
|
484
484
|
Object.defineProperty(cachedFn, "length", {
|
|
485
485
|
value: fn.length,
|
|
486
486
|
configurable: true
|
|
@@ -489,6 +489,11 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
489
489
|
if (options.acceptsSecondArgument !== void 0) Reflect.set(cachedFn, USE_CACHE_ACCEPTS_SECOND_ARGUMENT_SYMBOL, options.acceptsSecondArgument);
|
|
490
490
|
return cachedFn;
|
|
491
491
|
}
|
|
492
|
+
/** Memoize in one React render without skipping cache guards or scoped serialization. */
|
|
493
|
+
function memoizeInCacheScope(fn) {
|
|
494
|
+
const memoized = cache((_parent, _workUnit, _unstable, ...args) => fn(...args));
|
|
495
|
+
return (...args) => memoized(cacheContextStorage.getStore(), workUnitAsyncStorage.getStore(), unstableCacheContextStorage.getStore() === true, ...args);
|
|
496
|
+
}
|
|
492
497
|
/** @internal Symbol used to identify "use cache" wrapper functions. */
|
|
493
498
|
const USE_CACHE_FUNCTION_SYMBOL = Symbol.for("vinext.useCacheFunction");
|
|
494
499
|
/** @internal Symbol carrying transform-derived cached function argument metadata. */
|
|
@@ -553,11 +558,12 @@ function propagateCacheTagsToRequest(tags) {
|
|
|
553
558
|
addCollectedRequestTags(tags);
|
|
554
559
|
}
|
|
555
560
|
async function executeWithContext(fn, args, variant, rsc) {
|
|
556
|
-
const { result, ctx: _ctx, effectiveLife, collectedResult } = await runCachedFunctionWithContext(fn, args, variant,
|
|
561
|
+
const { result, ctx: _ctx, effectiveLife, collectedResult } = await runCachedFunctionWithContext(fn, args, variant, (value) => serializeCacheResult(value, rsc));
|
|
557
562
|
recordRequestScopedCacheLife(effectiveLife);
|
|
558
563
|
return {
|
|
559
564
|
result: collectedResult ? collectedResult.result : result,
|
|
560
|
-
cacheable: collectedResult?.cacheEntry !== null
|
|
565
|
+
cacheable: collectedResult?.cacheEntry !== null,
|
|
566
|
+
serialized: collectedResult?.cacheEntry
|
|
561
567
|
};
|
|
562
568
|
}
|
|
563
569
|
async function runCachedFunctionWithContext(fn, args, variant, collectResult) {
|
|
@@ -603,31 +609,6 @@ async function runCachedFunctionWithContext(fn, args, variant, collectResult) {
|
|
|
603
609
|
collectedResult
|
|
604
610
|
};
|
|
605
611
|
}
|
|
606
|
-
function unwrapThenableObjects(value, options) {
|
|
607
|
-
if (value === null || value === void 0 || typeof value !== "object") return value;
|
|
608
|
-
const childOptions = { omitMarkedAppPageSearchParams: options.omitMarkedAppPageSearchParams };
|
|
609
|
-
if (Array.isArray(value)) return value.map((item) => unwrapThenableObjects(item, childOptions));
|
|
610
|
-
if (isThenableObject(value)) {
|
|
611
|
-
const plain = {};
|
|
612
|
-
for (const key of Object.keys(value)) plain[key] = unwrapThenableObjects(value[key], childOptions);
|
|
613
|
-
return plain;
|
|
614
|
-
}
|
|
615
|
-
if (typeof value.then === "function") return value;
|
|
616
|
-
const result = {};
|
|
617
|
-
for (const key of Object.keys(value)) {
|
|
618
|
-
if (key === "searchParams" && (options.omitAppPageSearchParamsAtRoot || options.omitMarkedAppPageSearchParams && isMarkedAppPagePropsObject(value))) continue;
|
|
619
|
-
result[key] = unwrapThenableObjects(value[key], childOptions);
|
|
620
|
-
}
|
|
621
|
-
return result;
|
|
622
|
-
}
|
|
623
|
-
/**
|
|
624
|
-
* A thenable (not an array) with own enumerable properties — the
|
|
625
|
-
* `Object.assign(Promise.resolve(obj), obj)` pattern Next.js params use. The
|
|
626
|
-
* cache key is built from its fields instead of the promise.
|
|
627
|
-
*/
|
|
628
|
-
function isThenableObject(value) {
|
|
629
|
-
return !Array.isArray(value) && "then" in value && typeof value.then === "function" && Object.keys(value).length > 0;
|
|
630
|
-
}
|
|
631
612
|
function isPagePropsObject(value) {
|
|
632
613
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
633
614
|
}
|
|
@@ -636,26 +617,17 @@ function replaceArgument(args, index, value) {
|
|
|
636
617
|
result[index] = value;
|
|
637
618
|
return result;
|
|
638
619
|
}
|
|
639
|
-
/** Remove the `$$isPage` invocation marker before props reach the key or user code. */
|
|
640
|
-
function withoutUseCachePageMarker(props) {
|
|
641
|
-
const { [APP_PAGE_USE_CACHE_MARKER]: _marker, ...pageProps } = props;
|
|
642
|
-
return isMarkedAppPagePropsObject(props) ? markAppPagePropsForUseCache(pageProps) : pageProps;
|
|
643
|
-
}
|
|
644
620
|
/**
|
|
645
621
|
* Response Store replay args for a public page cache: drop `searchParams` from
|
|
646
622
|
* the page props at `index` (after a capture envelope, if any), as Next.js does
|
|
647
|
-
* for the serialized arguments (use-cache-wrapper.ts, `isPageSegmentFunction`)
|
|
648
|
-
*
|
|
649
|
-
* the erroring searchParams fallback.
|
|
623
|
+
* for the serialized arguments (use-cache-wrapper.ts, `isPageSegmentFunction`).
|
|
624
|
+
* The replay regains page semantics from `CacheFlightArguments.pagePropsIndex`.
|
|
650
625
|
*/
|
|
651
626
|
function toReplayablePageArgs(args, index) {
|
|
652
627
|
const props = args[index];
|
|
653
628
|
if (!isPagePropsObject(props)) return [...args];
|
|
654
629
|
const { searchParams: _searchParams, ...pageProps } = props;
|
|
655
|
-
return replaceArgument(args, index,
|
|
656
|
-
...pageProps,
|
|
657
|
-
[APP_PAGE_USE_CACHE_MARKER]: true
|
|
658
|
-
});
|
|
630
|
+
return replaceArgument(args, index, pageProps);
|
|
659
631
|
}
|
|
660
632
|
/**
|
|
661
633
|
* Give page props at `index` without `searchParams` (a Response Store replay of
|
|
@@ -671,35 +643,5 @@ function withErroringPageSearchParams(args, index) {
|
|
|
671
643
|
searchParams: makeThenableParams({}, { observeParamAccess: () => throwIfInsideCacheScope("searchParams") })
|
|
672
644
|
});
|
|
673
645
|
}
|
|
674
|
-
function unwrapThenableObjectArray(values, options) {
|
|
675
|
-
return values.map((value, index) => unwrapThenableObjects(value, {
|
|
676
|
-
omitAppPageSearchParamsAtRoot: index === options.pagePropsIndex,
|
|
677
|
-
omitMarkedAppPageSearchParams: options.omitMarkedAppPageSearchParams
|
|
678
|
-
}));
|
|
679
|
-
}
|
|
680
|
-
function stableStringify(value, seen) {
|
|
681
|
-
if (value === void 0) return "undefined";
|
|
682
|
-
if (value === null) return "null";
|
|
683
|
-
if (typeof value === "function") throw new Error("Cannot serialize function");
|
|
684
|
-
if (typeof value === "symbol") throw new Error("Cannot serialize symbol");
|
|
685
|
-
if (Array.isArray(value)) {
|
|
686
|
-
if (!seen) seen = /* @__PURE__ */ new Set();
|
|
687
|
-
if (seen.has(value)) throw new Error("Circular reference");
|
|
688
|
-
seen.add(value);
|
|
689
|
-
const result = "[" + value.map((v) => stableStringify(v, seen)).join(",") + "]";
|
|
690
|
-
seen.delete(value);
|
|
691
|
-
return result;
|
|
692
|
-
}
|
|
693
|
-
if (typeof value === "object" && value !== null) {
|
|
694
|
-
if (value instanceof Date) return `Date(${value.getTime()})`;
|
|
695
|
-
if (!seen) seen = /* @__PURE__ */ new Set();
|
|
696
|
-
if (seen.has(value)) throw new Error("Circular reference");
|
|
697
|
-
seen.add(value);
|
|
698
|
-
const result = "{" + Object.keys(value).sort().map((k) => `${JSON.stringify(k)}:${stableStringify(value[k], seen)}`).join(",") + "}";
|
|
699
|
-
seen.delete(value);
|
|
700
|
-
return result;
|
|
701
|
-
}
|
|
702
|
-
return JSON.stringify(value);
|
|
703
|
-
}
|
|
704
646
|
//#endregion
|
|
705
|
-
export { NestedDynamicUseCacheError, buildUseCacheKey, cacheContextStorage, clearPrivateCache, getCacheContext,
|
|
647
|
+
export { NestedDynamicUseCacheError, buildUseCacheKey, cacheContextStorage, clearPrivateCache, getCacheContext, isUseCacheFunction, memoizeInCacheScope, registerCachedFunction, replayCachedFunction, runWithPrivateCache };
|
package/dist/shims/cache.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ExecutionContextLike, getRequestExecutionContext, runWithExecutionContext } from "./request-context.js";
|
|
2
|
-
import {
|
|
2
|
+
import { _recordUseCacheRootParamRead, _registerCacheContextAccessor, getRegisteredCacheContext } from "./internal/cache-context-accessor.js";
|
|
3
|
+
import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheLifeConfig, CacheLifeSink, CacheState, UnstableCacheObservation, UnstableCacheRevalidationMode, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, markActionRevalidation, recordUnstableCacheObservation, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
|
|
3
4
|
import { CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getCacheHandler, getDataCacheHandler, registerDataCacheHandler, registerLazyDataCacheHandler, setCacheHandler, setDataCacheHandler } from "./cache-handler.js";
|
|
4
5
|
//#region src/shims/cache.d.ts
|
|
5
6
|
/**
|
|
@@ -141,4 +142,4 @@ type UnstableCacheOptions = {
|
|
|
141
142
|
*/
|
|
142
143
|
export declare function unstable_cache<T extends (...args: any[]) => Promise<any>>(fn: T, keyParts?: string[], options?: UnstableCacheOptions): T;
|
|
143
144
|
//#endregion
|
|
144
|
-
export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CacheLifeConfig, CacheState, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, type ExecutionContextLike, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, UnstableCacheObservation, UnstableCacheRevalidationMode, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _recordUseCacheRootParamRead, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, markActionRevalidation, unstable_noStore as noStore, recordUnstableCacheObservation, registerDataCacheHandler, registerLazyDataCacheHandler, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry };
|
|
145
|
+
export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CacheLifeConfig, CacheLifeSink, CacheState, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, type ExecutionContextLike, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, UnstableCacheObservation, UnstableCacheRevalidationMode, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _recordUseCacheRootParamRead, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, markActionRevalidation, unstable_noStore as noStore, recordUnstableCacheObservation, registerDataCacheHandler, registerLazyDataCacheHandler, runWithDetachedCacheObservations, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry };
|
package/dist/shims/cache.js
CHANGED
|
@@ -8,9 +8,11 @@ import { fnv1a64 } from "../utils/hash.js";
|
|
|
8
8
|
import { MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getCacheHandler, getDataCacheHandler, registerDataCacheHandler, registerLazyDataCacheHandler, setCacheHandler, setDataCacheHandler } from "./cache-handler.js";
|
|
9
9
|
import { encodeCacheTag, encodeCacheTags } from "../utils/encode-cache-tag.js";
|
|
10
10
|
import { makeHangingPromise } from "./internal/make-hanging-promise.js";
|
|
11
|
-
import { getHeadersAccessPhase,
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
11
|
+
import { getHeadersAccessPhase, markDynamicUsage } from "./internal/headers-state.js";
|
|
12
|
+
import { isDraftModeEnabled } from "./headers.js";
|
|
13
|
+
import { _recordUseCacheRootParamRead, _registerCacheContextAccessor, getRegisteredCacheContext } from "./internal/cache-context-accessor.js";
|
|
14
|
+
import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, markActionRevalidation, recordUnstableCacheObservation, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
|
|
15
|
+
import { addCollectedRequestTags, getCurrentFetchSoftTags, runWithDetachedFetchObservations } from "./fetch-cache.js";
|
|
14
16
|
//#region src/shims/cache.ts
|
|
15
17
|
/**
|
|
16
18
|
* next/cache shim
|
|
@@ -320,6 +322,7 @@ const UNSTABLE_CACHE_KEY_PREFIX = "unstable_cache:v2";
|
|
|
320
322
|
* a direct import (avoiding circular dependencies).
|
|
321
323
|
*/
|
|
322
324
|
const _unstableCacheAls = getOrCreateAls("vinext.unstableCache.als");
|
|
325
|
+
const _useCacheContextAls = getOrCreateAls("vinext.cacheRuntime.contextAls");
|
|
323
326
|
function serializeUnstableCacheResult(value) {
|
|
324
327
|
return JSON.stringify(value === void 0 ? { undef: true } : { v: value });
|
|
325
328
|
}
|
|
@@ -360,7 +363,7 @@ function waitUntilUnstableCacheRevalidation(promise) {
|
|
|
360
363
|
function scheduleUnstableCacheBackgroundRevalidation(cacheKey, refresh) {
|
|
361
364
|
const pending = getPendingUnstableCacheRevalidations();
|
|
362
365
|
if (pending.has(cacheKey)) return;
|
|
363
|
-
const trackedRevalidation =
|
|
366
|
+
const trackedRevalidation = runWithDetachedCacheObservations(() => runWithDetachedFetchObservations(() => _useCacheContextAls.exit(refresh))).then(() => void 0).catch((err) => {
|
|
364
367
|
console.error(`[vinext] unstable_cache background revalidation failed for ${cacheKey}:`, err);
|
|
365
368
|
}).finally(() => {
|
|
366
369
|
if (pending.get(cacheKey) === trackedRevalidation) pending.delete(cacheKey);
|
|
@@ -434,4 +437,4 @@ function unstable_cache(fn, keyParts, options) {
|
|
|
434
437
|
return cachedFn;
|
|
435
438
|
}
|
|
436
439
|
//#endregion
|
|
437
|
-
export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, MemoryCacheHandler, NoOpCacheHandler, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _recordUseCacheRootParamRead, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLife, cacheLifeProfiles, cacheTag, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, io, isInsideUnstableCacheScope, markActionRevalidation, unstable_noStore as noStore, unstable_noStore, recordUnstableCacheObservation, refresh, registerDataCacheHandler, registerLazyDataCacheHandler, revalidatePath, revalidateTag, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry, unstable_cache, unstable_cacheLife, unstable_cacheTag, unstable_io, updateTag };
|
|
440
|
+
export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, MemoryCacheHandler, NoOpCacheHandler, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _recordUseCacheRootParamRead, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLife, cacheLifeProfiles, cacheTag, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, io, isInsideUnstableCacheScope, markActionRevalidation, unstable_noStore as noStore, unstable_noStore, recordUnstableCacheObservation, refresh, registerDataCacheHandler, registerLazyDataCacheHandler, revalidatePath, revalidateTag, runWithDetachedCacheObservations, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry, unstable_cache, unstable_cacheLife, unstable_cacheTag, unstable_io, updateTag };
|
|
@@ -10,6 +10,13 @@ export type RouteCacheabilityOutcome = {
|
|
|
10
10
|
searchParamsUnread?: true;
|
|
11
11
|
/** A transient classification failure that may succeed on another bounded attempt. */
|
|
12
12
|
retryable?: true;
|
|
13
|
+
/**
|
|
14
|
+
* App page RSC: the status and headers that replace the streamed 200 of a
|
|
15
|
+
* render whose special error rejected its document's shell, once the
|
|
16
|
+
* response is complete.
|
|
17
|
+
*/
|
|
18
|
+
status?: number;
|
|
19
|
+
headers?: Readonly<Record<string, string>>;
|
|
13
20
|
tags?: readonly string[];
|
|
14
21
|
};
|
|
15
22
|
export type RouteCacheabilityState = {
|
|
@@ -86,7 +93,7 @@ export declare function markRouteCacheabilityExplicitConfigPolicy(): void;
|
|
|
86
93
|
export declare function markRouteCacheabilityConfigCdnCachePolicy(name: string, value: string): void;
|
|
87
94
|
/** Record a next.config cache policy header with the value a response carries. */
|
|
88
95
|
export declare function recordConfigCdnCachePolicyHeader(state: RouteCacheabilityState, name: string, value: string): void;
|
|
89
|
-
/** Record
|
|
96
|
+
/** Record an explicit cache policy supplied by the Route Handler itself. */
|
|
90
97
|
export declare function markRouteCacheabilityExplicitResponsePolicy(): void;
|
|
91
98
|
/** Record that the response body reached clean EOF and is now a replay stream. */
|
|
92
99
|
export declare function markRouteCacheabilityResponseBodyComplete(): void;
|
|
@@ -84,10 +84,10 @@ function recordConfigCdnCachePolicyHeader(state, name, value) {
|
|
|
84
84
|
const applied = new Headers([[name, value]]).get(name) ?? value;
|
|
85
85
|
(state.configCdnCachePolicy ??= /* @__PURE__ */ new Map()).set(name.toLowerCase(), applied);
|
|
86
86
|
}
|
|
87
|
-
/** Record
|
|
87
|
+
/** Record an explicit cache policy supplied by the Route Handler itself. */
|
|
88
88
|
function markRouteCacheabilityExplicitResponsePolicy() {
|
|
89
89
|
const state = readRouteCacheabilityState();
|
|
90
|
-
if (!state
|
|
90
|
+
if (!state) return;
|
|
91
91
|
state.explicitResponseCachePolicy = true;
|
|
92
92
|
}
|
|
93
93
|
/** Record that the response body reached clean EOF and is now a replay stream. */
|