vinext 1.0.1 → 1.2.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 +93 -10
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/client-build-config.d.ts +10 -0
- package/dist/build/client-build-config.js +18 -2
- package/dist/build/pages-client-assets-module.d.ts +8 -0
- package/dist/build/pages-client-assets-module.js +21 -1
- package/dist/build/prerender-paths.js +8 -81
- package/dist/build/prerender.js +33 -8
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/build/ssr-manifest.d.ts +2 -0
- package/dist/build/ssr-manifest.js +6 -2
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/check.js +7 -6
- package/dist/cli.js +2 -1
- package/dist/client/client-redirect-matcher.d.ts +14 -0
- package/dist/client/client-redirect-matcher.js +37 -0
- package/dist/client/client-redirects.d.ts +27 -0
- package/dist/client/client-redirects.js +28 -0
- package/dist/client/client-rewrites.d.ts +2 -1
- package/dist/client/client-rewrites.js +1 -1
- package/dist/client/navigation-runtime.d.ts +11 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.d.ts +26 -11
- package/dist/config/config-matchers.js +81 -82
- package/dist/config/destination-params.d.ts +47 -0
- package/dist/config/destination-params.js +116 -0
- package/dist/config/next-config.d.ts +14 -0
- package/dist/config/next-config.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +6 -0
- package/dist/entries/app-rsc-entry.js +84 -49
- package/dist/entries/pages-client-entry.js +3 -1
- package/dist/entries/pages-server-entry.js +13 -37
- package/dist/index.d.ts +7 -2
- package/dist/index.js +193 -73
- package/dist/init-cloudflare.d.ts +9 -0
- package/dist/init-cloudflare.js +107 -31
- package/dist/init-platform.d.ts +4 -0
- package/dist/init-platform.js +27 -2
- package/dist/init.d.ts +1 -0
- package/dist/init.js +67 -3
- package/dist/plugins/ast-scope.d.ts +7 -0
- package/dist/plugins/ast-scope.js +59 -3
- 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/dynamic-preload-metadata.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +9 -8
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +3 -4
- package/dist/plugins/middleware-server-only.d.ts +5 -4
- package/dist/plugins/middleware-server-only.js +8 -5
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
- package/dist/plugins/rsc-scan-glob-imports.js +50 -0
- package/dist/plugins/strip-server-exports.js +262 -98
- package/dist/plugins/transform-result.d.ts +9 -5
- package/dist/plugins/transitive-externals.js +1 -1
- package/dist/plugins/typeof-window.d.ts +2 -2
- package/dist/plugins/use-cache-callable.js +8 -2
- package/dist/plugins/worker-server-only-imports.d.ts +20 -0
- package/dist/plugins/worker-server-only-imports.js +31 -0
- package/dist/plugins/worker-use-server.d.ts +25 -0
- package/dist/plugins/worker-use-server.js +129 -0
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.d.ts +1 -0
- package/dist/server/api-handler.js +19 -8
- package/dist/server/app-browser-action-result.d.ts +1 -1
- package/dist/server/app-browser-action-result.js +9 -2
- package/dist/server/app-browser-entry.js +11 -7
- 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-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-server-action-client.js +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 -0
- package/dist/server/app-history-state.js +7 -0
- package/dist/server/app-middleware.d.ts +11 -0
- package/dist/server/app-middleware.js +19 -3
- 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 +63 -43
- package/dist/server/app-page-cache.d.ts +6 -1
- package/dist/server/app-page-cache.js +28 -8
- package/dist/server/app-page-dispatch.d.ts +12 -2
- package/dist/server/app-page-dispatch.js +51 -33
- 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-ppr-runtime.js +1 -1
- 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 +3 -3
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -119
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +54 -17
- 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 +57 -35
- 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-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +6 -0
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +2 -3
- package/dist/server/app-prerender-endpoints.js +9 -6
- package/dist/server/app-request-stage-dispatch.js +7 -3
- package/dist/server/app-request-stage-independent-entry.js +29 -9
- 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-response-stage-entry.js +10 -2
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +1 -0
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +6 -3
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +4 -1
- package/dist/server/app-route-handler-runtime.js +45 -24
- package/dist/server/app-router-entry.js +27 -8
- package/dist/server/app-rsc-cache-busting.js +1 -1
- package/dist/server/app-rsc-errors.js +20 -16
- package/dist/server/app-rsc-handler.d.ts +11 -0
- package/dist/server/app-rsc-handler.js +291 -125
- package/dist/server/app-rsc-request-normalization.d.ts +3 -1
- package/dist/server/app-rsc-request-normalization.js +4 -2
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +10 -6
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +36 -19
- package/dist/server/app-segment-config.d.ts +2 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +62 -23
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +8 -5
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +34 -15
- package/dist/server/app-worker-stages.d.ts +7 -2
- package/dist/server/app-worker-stages.js +4 -4
- package/dist/server/cacheability-request.js +11 -7
- package/dist/server/client-build-files.d.ts +16 -0
- package/dist/server/client-build-files.js +36 -0
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/config-headers.js +2 -0
- package/dist/server/dev-server.js +50 -29
- package/dist/server/dev-stack-sourcemap.js +18 -23
- package/dist/server/document-initial-head.d.ts +0 -11
- package/dist/server/document-initial-head.js +1 -1
- package/dist/server/forwarded-middleware-context.d.ts +5 -0
- package/dist/server/forwarded-middleware-context.js +22 -0
- package/dist/server/headers.d.ts +18 -1
- package/dist/server/headers.js +19 -2
- package/dist/server/http-conditional.d.ts +11 -0
- package/dist/server/http-conditional.js +10 -1
- package/dist/server/http-error-responses.d.ts +1 -1
- package/dist/server/image-optimization.d.ts +54 -0
- package/dist/server/image-optimization.js +118 -9
- package/dist/server/isr-cache.d.ts +10 -0
- package/dist/server/isr-cache.js +43 -8
- package/dist/server/metadata-route-response.js +9 -8
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-matcher.d.ts +2 -0
- package/dist/server/middleware-matcher.js +23 -2
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +33 -20
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +3 -1
- package/dist/server/multi-stage.d.ts +19 -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/normalize-path.d.ts +0 -13
- package/dist/server/normalize-path.js +1 -34
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-api-route.d.ts +3 -2
- package/dist/server/pages-api-route.js +4 -3
- package/dist/server/pages-cache-tag.d.ts +12 -0
- package/dist/server/pages-cache-tag.js +19 -0
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-data-route.d.ts +10 -0
- package/dist/server/pages-data-route.js +19 -2
- package/dist/server/pages-document-asset-props.d.ts +5 -1
- package/dist/server/pages-document-asset-props.js +13 -5
- package/dist/server/pages-document-splice.d.ts +19 -0
- package/dist/server/pages-document-splice.js +55 -0
- package/dist/server/pages-i18n.d.ts +12 -1
- package/dist/server/pages-i18n.js +18 -4
- package/dist/server/pages-node-compat.d.ts +16 -5
- package/dist/server/pages-node-compat.js +20 -12
- package/dist/server/pages-page-data.d.ts +32 -24
- package/dist/server/pages-page-data.js +50 -120
- package/dist/server/pages-page-handler.d.ts +0 -6
- package/dist/server/pages-page-handler.js +209 -130
- package/dist/server/pages-page-response.d.ts +12 -6
- package/dist/server/pages-page-response.js +41 -34
- package/dist/server/pages-request-pipeline.d.ts +10 -2
- package/dist/server/pages-request-pipeline.js +37 -18
- package/dist/server/pages-request-stage-entry.d.ts +6 -0
- package/dist/server/pages-request-stage-entry.js +79 -16
- package/dist/server/pages-response-stage-entry.js +4 -0
- package/dist/server/pages-revalidate.js +1 -1
- package/dist/server/pages-router-entry.js +4 -3
- package/dist/server/prerender-manifest.d.ts +3 -3
- package/dist/server/prerender-manifest.js +4 -3
- package/dist/server/prerender-work-unit-setup.js +4 -0
- package/dist/server/prod-server.d.ts +20 -7
- package/dist/server/prod-server.js +343 -129
- package/dist/server/proper-error.d.ts +4 -0
- package/dist/server/proper-error.js +31 -0
- package/dist/server/request-pipeline.d.ts +24 -9
- package/dist/server/request-pipeline.js +24 -9
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/revalidation-request.d.ts +1 -0
- package/dist/server/revalidation-request.js +1 -1
- package/dist/server/rsc-stream-hints.js +31 -2
- package/dist/server/seed-cache.d.ts +1 -0
- package/dist/server/seed-cache.js +15 -11
- package/dist/server/server-reference-loader.d.ts +4 -0
- package/dist/server/server-reference-loader.js +29 -0
- package/dist/server/socket-error-backstop.d.ts +23 -1
- package/dist/server/socket-error-backstop.js +69 -17
- package/dist/server/static-file-signal.d.ts +15 -4
- package/dist/server/static-file-signal.js +46 -12
- package/dist/server/worker-image-optimization.d.ts +34 -0
- package/dist/server/worker-image-optimization.js +86 -0
- package/dist/server/worker-stages.d.ts +1 -1
- package/dist/server/worker-stages.js +2 -2
- package/dist/server/worker-utils.d.ts +8 -3
- package/dist/server/worker-utils.js +12 -7
- package/dist/shims/app-router-scroll.js +4 -1
- package/dist/shims/app-router-tree-context.d.ts +5 -0
- package/dist/shims/app-router-tree-context.js +27 -0
- 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 +6 -42
- package/dist/shims/cache-callable-runtime.js +65 -174
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-handler.js +1 -9
- package/dist/shims/cache-request-state.d.ts +15 -0
- package/dist/shims/cache-request-state.js +31 -8
- package/dist/shims/cache-runtime.d.ts +12 -20
- package/dist/shims/cache-runtime.js +166 -225
- package/dist/shims/cache.d.ts +4 -4
- package/dist/shims/cache.js +44 -16
- package/dist/shims/cacheability-classification.d.ts +7 -0
- package/dist/shims/cdn-cache.d.ts +8 -0
- package/dist/shims/cdn-cache.js +17 -1
- package/dist/shims/disable-smooth-scroll.d.ts +3 -0
- package/dist/shims/disable-smooth-scroll.js +36 -0
- package/dist/shims/document-placeholders.d.ts +19 -0
- package/dist/shims/document-placeholders.js +45 -0
- package/dist/shims/document.js +21 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
- package/dist/shims/dynamic-preload-chunks.js +13 -9
- package/dist/shims/dynamic.d.ts +1 -1
- package/dist/shims/dynamic.js +60 -8
- 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/fetch-cache-state.d.ts +66 -0
- package/dist/shims/fetch-cache-state.js +92 -0
- package/dist/shims/fetch-cache.d.ts +3 -61
- package/dist/shims/fetch-cache.js +161 -108
- package/dist/shims/form.js +1 -1
- package/dist/shims/head.d.ts +10 -6
- package/dist/shims/head.js +15 -13
- package/dist/shims/headers.d.ts +13 -0
- package/dist/shims/headers.js +47 -4
- package/dist/shims/image.js +2 -1
- 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/headers-state.d.ts +0 -1
- package/dist/shims/internal/work-store-scope.d.ts +5 -0
- package/dist/shims/internal/work-store-scope.js +24 -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 +45 -9
- package/dist/shims/request-context.d.ts +11 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/router.js +12 -20
- package/dist/shims/server.d.ts +16 -0
- package/dist/shims/server.js +24 -4
- 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/shims/url-utils.d.ts +2 -0
- package/dist/shims/url-utils.js +3 -1
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/hash.d.ts +7 -0
- package/dist/utils/hash.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/package-name.d.ts +6 -0
- package/dist/utils/package-name.js +12 -1
- package/dist/utils/plugin-rsc-version.d.ts +4 -0
- package/dist/utils/plugin-rsc-version.js +15 -0
- package/dist/utils/prerender-output-paths.js +15 -4
- package/dist/utils/public-file-path.d.ts +10 -2
- package/dist/utils/public-file-path.js +13 -9
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.d.ts +3 -0
- package/dist/utils/react-version.js +1 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/package.json +9 -5
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
//#region src/shims/cache-adapter-instantiate.ts
|
|
2
|
+
const REQUIREMENTS = {
|
|
3
|
+
data: {
|
|
4
|
+
methods: [
|
|
5
|
+
"get",
|
|
6
|
+
"set",
|
|
7
|
+
"revalidateTag"
|
|
8
|
+
],
|
|
9
|
+
booleans: [],
|
|
10
|
+
description: "A data cache adapter implements get, set and revalidateTag."
|
|
11
|
+
},
|
|
12
|
+
cdn: {
|
|
13
|
+
methods: [
|
|
14
|
+
"get",
|
|
15
|
+
"set",
|
|
16
|
+
"revalidateTag",
|
|
17
|
+
"buildResponseHeaders"
|
|
18
|
+
],
|
|
19
|
+
booleans: ["ownsBackgroundRevalidation"],
|
|
20
|
+
description: "A CDN cache adapter implements get, set, revalidateTag and buildResponseHeaders, and sets ownsBackgroundRevalidation to a boolean."
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Whether `value` has a [[Construct]] internal method. A Proxy is
|
|
25
|
+
* constructible exactly when its target is; its no-op `construct` trap
|
|
26
|
+
* answers without running the export or reading any of its properties.
|
|
27
|
+
*/
|
|
28
|
+
function isConstructor(value) {
|
|
29
|
+
if (typeof value !== "function") return false;
|
|
30
|
+
try {
|
|
31
|
+
new new Proxy(value, { construct: () => ({}) })();
|
|
32
|
+
return true;
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const CLASS_SOURCE = /^class\b/;
|
|
38
|
+
/**
|
|
39
|
+
* Whether an export is class syntax and must be invoked with `new`. The
|
|
40
|
+
* [[Construct]] check excludes methods named `class`, whose source text
|
|
41
|
+
* also starts with that word.
|
|
42
|
+
*/
|
|
43
|
+
function isClassExport(value) {
|
|
44
|
+
if (!isConstructor(value)) return false;
|
|
45
|
+
try {
|
|
46
|
+
return CLASS_SOURCE.test(Function.prototype.toString.call(value));
|
|
47
|
+
} catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function describeValue(value) {
|
|
52
|
+
if (value === null) return "null";
|
|
53
|
+
if (Array.isArray(value)) return "an array";
|
|
54
|
+
if (typeof value === "object") return "an object";
|
|
55
|
+
return typeof value === "undefined" ? "undefined" : `a ${typeof value}`;
|
|
56
|
+
}
|
|
57
|
+
const ignore = () => {};
|
|
58
|
+
/**
|
|
59
|
+
* Attach a no-op rejection handler with the intrinsic `Promise.prototype.then`,
|
|
60
|
+
* which throws on a non-Promise before reading anything from it. Returns the
|
|
61
|
+
* derived promise, which a Promise subclass's species constructor chooses.
|
|
62
|
+
*/
|
|
63
|
+
function handleRejection(promise) {
|
|
64
|
+
return Promise.prototype.then.call(promise, void 0, ignore);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Whether `value` is a Promise, judged by its internal slot or this realm's
|
|
68
|
+
* Promise prototype chain, never by a `then` member: adapter contracts are
|
|
69
|
+
* structural and do not reserve `then`, so an adapter's own `then` method is
|
|
70
|
+
* never read or invoked.
|
|
71
|
+
*
|
|
72
|
+
* A Promise from any realm passes the intrinsic `then`'s brand check, which
|
|
73
|
+
* also attaches a no-op rejection handler, so the discarded result cannot
|
|
74
|
+
* become an unhandled rejection. The derived promise that call returns is
|
|
75
|
+
* handled too, since a subclass's species constructor may return a rejected
|
|
76
|
+
* one.
|
|
77
|
+
*
|
|
78
|
+
* Known limitation: when a Promise subclass's `constructor` or
|
|
79
|
+
* `Symbol.species` lookup throws, that call fails after the brand check, and
|
|
80
|
+
* no handler can be attached (every way of observing a Promise goes through
|
|
81
|
+
* that lookup or its `then`). Such a Promise is still rejected when it comes
|
|
82
|
+
* from this realm, the one adapter modules are evaluated in; one from another
|
|
83
|
+
* realm is judged by its members like any other value.
|
|
84
|
+
*/
|
|
85
|
+
function markHandledIfPromise(value) {
|
|
86
|
+
let derived;
|
|
87
|
+
try {
|
|
88
|
+
derived = handleRejection(value);
|
|
89
|
+
} catch {
|
|
90
|
+
try {
|
|
91
|
+
return value instanceof Promise;
|
|
92
|
+
} catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
handleRejection(derived);
|
|
98
|
+
} catch {}
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
function instantiateCacheAdapter(exported, args, slot) {
|
|
102
|
+
const label = `cache.${slot} adapter`;
|
|
103
|
+
const requirements = REQUIREMENTS[slot];
|
|
104
|
+
if (typeof exported !== "function") {
|
|
105
|
+
const hint = exported !== null && typeof exported === "object" ? " To use an adapter object directly, export a factory that returns it: `export default () => adapter`." : exported === void 0 ? " Check that the module has a default export." : "";
|
|
106
|
+
throw new TypeError(`${label}: the module's default export must be a factory function or a class that receives { env, options }, got ${describeValue(exported)}.${hint}`);
|
|
107
|
+
}
|
|
108
|
+
const adapter = isClassExport(exported) ? new exported(args) : exported(args);
|
|
109
|
+
const isObjectLike = adapter !== null && typeof adapter === "object" || typeof adapter === "function";
|
|
110
|
+
if (isObjectLike && markHandledIfPromise(adapter)) throw new TypeError(`${label}: the default export returned a Promise. Adapter factories must return the adapter synchronously; defer async setup to the adapter's methods.`);
|
|
111
|
+
if (!isObjectLike) throw new TypeError(`${label}: the default export must produce an adapter object, got ${describeValue(adapter)}. ${requirements.description}`);
|
|
112
|
+
const record = adapter;
|
|
113
|
+
const problems = [...requirements.methods.filter((method) => typeof record[method] !== "function").map((method) => `method ${method}`), ...requirements.booleans.filter((property) => typeof record[property] !== "boolean").map((property) => `boolean ${property}`)];
|
|
114
|
+
if (problems.length > 0) throw new TypeError(`${label}: the adapter produced by the default export is missing ${problems.join(", ")}. ${requirements.description}`);
|
|
115
|
+
return adapter;
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
export { instantiateCacheAdapter, isClassExport, isConstructor };
|
|
@@ -4,48 +4,12 @@ import { RegisterCachedFunctionOptions } from "./cache-runtime.js";
|
|
|
4
4
|
declare const CACHE_CAPTURE_TYPE = "use-cache-captures";
|
|
5
5
|
type CacheCaptureEnvelope = {
|
|
6
6
|
type: typeof CACHE_CAPTURE_TYPE;
|
|
7
|
-
encrypted:
|
|
7
|
+
encrypted: Promise<string>;
|
|
8
8
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
type EncodedCacheArguments = {
|
|
16
|
-
args: unknown[];
|
|
17
|
-
thenableObjects: EncodedThenableObject[];
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* Flight writes each object once, so `promise` decodes to the same promise as
|
|
21
|
-
* every other reference to it, including ones inside resolved values, and the
|
|
22
|
-
* fields share references with the arguments. The fields build the cache key;
|
|
23
|
-
* the resolved value can differ: the params proxy hides params named like
|
|
24
|
-
* promise or React fields (`value`, `status`) from its own keys but still
|
|
25
|
-
* resolves to them.
|
|
26
|
-
*/
|
|
27
|
-
type EncodedThenableObject = {
|
|
28
|
-
fields: Record<string, unknown>;
|
|
29
|
-
promise: PromiseLike<unknown>;
|
|
30
|
-
};
|
|
31
|
-
export declare function encryptCacheCaptures(captures: unknown[]): CacheCaptureEnvelope;
|
|
32
|
-
/**
|
|
33
|
-
* What to do when a read would run a getter: `reject` throws
|
|
34
|
-
* `UnreplayableCacheArgumentsError`, `skip` leaves the getter unread.
|
|
35
|
-
*/
|
|
36
|
-
type GetterHandling = "reject" | "skip";
|
|
37
|
-
/**
|
|
38
|
-
* Collect the own fields of every promise-augmented object in the arguments,
|
|
39
|
-
* including ones inside resolved promise values. The arguments are passed to
|
|
40
|
-
* Flight as they are, so Flight keeps their shared references and cycles.
|
|
41
|
-
* With `getters: "reject"`, throws `UnreplayableCacheArgumentsError` when the
|
|
42
|
-
* arguments hold a getter; with `"skip"`, promise fields behind a getter are
|
|
43
|
-
* not recorded.
|
|
44
|
-
*/
|
|
45
|
-
export declare function encodeCacheArguments(args: unknown[], getters?: GetterHandling): Promise<EncodedCacheArguments>;
|
|
46
|
-
/** Restore the promise fields that `encodeCacheArguments` captured before Flight encoding. */
|
|
47
|
-
export declare function decodeCacheArguments(value: unknown): unknown[];
|
|
48
|
-
export declare function registerCachedFunction<TArgs extends unknown[], TResult>(fn: (...args: TArgs) => Promise<TResult>, id: string, variant: string, options: RegisterCachedFunctionOptions): (...args: TArgs) => Promise<TResult>;
|
|
49
|
-
/** Load and invoke one transformed cache function through its server-reference identity. */
|
|
9
|
+
export declare function encryptCacheCaptures(referenceId: string, captures: unknown[]): CacheCaptureEnvelope;
|
|
10
|
+
export declare function registerCachedFunction<TArgs extends unknown[], TResult>(fn: (...args: TArgs) => Promise<TResult>, id: string, variant: string, { captureCount, ...options }: RegisterCachedFunctionOptions & {
|
|
11
|
+
captureCount?: number;
|
|
12
|
+
}): (...args: TArgs) => Promise<TResult>;
|
|
13
|
+
/** Replay the persisted payload without re-reading or re-encoding caller objects. */
|
|
50
14
|
export declare function invokeCacheFunction(invocation: VinextCacheFunctionInvocation, loadServerAction: (id: string) => Promise<unknown>): Promise<void>;
|
|
51
15
|
//#endregion
|
|
@@ -1,190 +1,81 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { restoreFlightReply, snapshotFlightReply } from "./cache-flight-arguments.js";
|
|
2
|
+
import { isUseCacheFunction, memoizeInCacheScope, registerCachedFunction as registerCachedFunction$1, replayCachedFunction } from "./cache-runtime.js";
|
|
2
3
|
import { decryptActionBoundArgs, encryptActionBoundArgs } from "@vitejs/plugin-rsc/utils/encryption-runtime";
|
|
4
|
+
import { createFromReadableStream, renderToReadableStream } from "@vitejs/plugin-rsc/react/rsc";
|
|
3
5
|
//#region src/shims/cache-callable-runtime.ts
|
|
4
6
|
const CACHE_CAPTURE_TYPE = "use-cache-captures";
|
|
5
|
-
function
|
|
6
|
-
return
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (
|
|
13
|
-
return
|
|
14
|
-
}
|
|
15
|
-
async function encryptCaptures(captures) {
|
|
16
|
-
return encryptActionBoundArgs(await encodeCacheArguments(captures, "skip"));
|
|
17
|
-
}
|
|
18
|
-
async function encryptCacheArguments(args) {
|
|
19
|
-
return encryptActionBoundArgs(await encodeCacheArguments(args));
|
|
20
|
-
}
|
|
21
|
-
async function decryptCacheArguments(encrypted) {
|
|
22
|
-
return decodeCacheArguments(await decryptActionBoundArgs(Promise.resolve(encrypted)));
|
|
23
|
-
}
|
|
24
|
-
function isThenable(value) {
|
|
25
|
-
return "then" in value && typeof value.then === "function";
|
|
26
|
-
}
|
|
27
|
-
function isPlainRecord(value) {
|
|
28
|
-
const prototype = Object.getPrototypeOf(value);
|
|
29
|
-
return (prototype === Object.prototype || prototype === null) && !("$$typeof" in value);
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* The arguments hold a getter. Flight reads it again while serializing, and a
|
|
33
|
-
* getter can return a different value, such as a new promise, on every read,
|
|
34
|
-
* so the recorded promise fields may not match what Flight serializes.
|
|
35
|
-
*/
|
|
36
|
-
var UnreplayableCacheArgumentsError = class extends Error {
|
|
37
|
-
constructor() {
|
|
38
|
-
super("Cache function arguments with getters cannot be replayed");
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* The own entries of `value` that Flight serializes: every index below an
|
|
43
|
-
* array's `length`, including holes and non-enumerable indices, as
|
|
44
|
-
* `JSON.stringify` reads them, and the enumerable own keys of anything else.
|
|
45
|
-
* A getter, own or inherited through an array hole, is never run.
|
|
46
|
-
*/
|
|
47
|
-
function ownEntries(value, getters) {
|
|
48
|
-
const keys = Array.isArray(value) ? Array.from({ length: value.length }, (_, index) => String(index)) : Object.keys(value);
|
|
49
|
-
const entries = [];
|
|
50
|
-
for (const key of keys) {
|
|
51
|
-
if (readsGetter(value, key)) {
|
|
52
|
-
if (getters === "reject") throw new UnreplayableCacheArgumentsError();
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
entries.push([key, Reflect.get(value, key)]);
|
|
56
|
-
}
|
|
57
|
-
return entries;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Whether reading `key` from `value` runs a getter. An array hole reads
|
|
61
|
-
* through the prototype chain, which can hold an indexed data property or
|
|
62
|
-
* accessor. A setter-only accessor reads as `undefined` without running code.
|
|
63
|
-
*/
|
|
64
|
-
function readsGetter(value, key) {
|
|
65
|
-
for (let target = value; target !== null; target = Reflect.getPrototypeOf(target)) {
|
|
66
|
-
const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
|
|
67
|
-
if (descriptor) return typeof descriptor.get === "function";
|
|
68
|
-
}
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
/** Members of the values Flight serializes recursively, which can hold params. */
|
|
72
|
-
function flightMembers(value, getters) {
|
|
73
|
-
if (value instanceof Map) return [...value].flat();
|
|
74
|
-
if (value instanceof Set) return [...value];
|
|
75
|
-
if (isThenableObject(value) || Array.isArray(value) || isPlainRecord(value)) return ownEntries(value, getters).map(([, member]) => member);
|
|
76
|
-
return [];
|
|
7
|
+
async function encryptArguments(value) {
|
|
8
|
+
return encryptActionBoundArgs(JSON.stringify(value));
|
|
9
|
+
}
|
|
10
|
+
async function decryptArguments(encrypted) {
|
|
11
|
+
const serialized = await decryptActionBoundArgs(Promise.resolve(encrypted));
|
|
12
|
+
if (typeof serialized !== "string") throw new Error("Invalid cache function arguments");
|
|
13
|
+
const value = JSON.parse(serialized);
|
|
14
|
+
if (value?.version !== 1) throw new Error("Invalid cache function arguments");
|
|
15
|
+
return value;
|
|
77
16
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (typeof value !== "object" || value === null || visited.has(value)) continue;
|
|
96
|
-
visited.add(value);
|
|
97
|
-
const children = flightMembers(value, getters);
|
|
98
|
-
if (isThenableObject(value)) {
|
|
99
|
-
const fields = Object.fromEntries(ownEntries(value, getters));
|
|
100
|
-
thenableObjects.push({
|
|
101
|
-
fields,
|
|
102
|
-
promise: value
|
|
103
|
-
});
|
|
17
|
+
function encryptCacheCaptures(referenceId, captures) {
|
|
18
|
+
return memoizedCaptureEnvelope(referenceId, ...captures);
|
|
19
|
+
}
|
|
20
|
+
const memoizedCaptureEnvelope = memoizeInCacheScope((referenceId, ...captures) => ({
|
|
21
|
+
type: CACHE_CAPTURE_TYPE,
|
|
22
|
+
encrypted: encryptCaptures(referenceId, captures)
|
|
23
|
+
}));
|
|
24
|
+
async function encryptCaptures(referenceId, captures) {
|
|
25
|
+
const files = new FormData();
|
|
26
|
+
let nextFileId = 0;
|
|
27
|
+
const temporaryReferences = new class extends WeakMap {
|
|
28
|
+
get(value) {
|
|
29
|
+
let id = super.get(value);
|
|
30
|
+
if (id === void 0 && value instanceof File) {
|
|
31
|
+
id = String(nextFileId++);
|
|
32
|
+
super.set(value, id);
|
|
33
|
+
files.append(id, value);
|
|
104
34
|
}
|
|
105
|
-
|
|
106
|
-
const result = settled.get(value);
|
|
107
|
-
if (!result) unsettled.push(value);
|
|
108
|
-
else if (result.status === "fulfilled") children.push(result.value);
|
|
109
|
-
}
|
|
110
|
-
for (const child of children) pending.push(child);
|
|
35
|
+
return id;
|
|
111
36
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
for (const thenableObject of value.thenableObjects) {
|
|
125
|
-
if (!isEncodedThenableObject(thenableObject)) throw new Error("Invalid cache function arguments");
|
|
126
|
-
Object.assign(thenableObject.promise, thenableObject.fields);
|
|
127
|
-
}
|
|
128
|
-
return value.args;
|
|
129
|
-
}
|
|
130
|
-
function isEncodedThenableObject(value) {
|
|
131
|
-
if (typeof value !== "object" || value === null || !isPlainRecord(value)) return false;
|
|
132
|
-
const { fields, promise } = value;
|
|
133
|
-
return typeof fields === "object" && fields !== null && isPlainRecord(fields) && promise instanceof Promise;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Flight decodes promises as React chunks whose own fields are React's
|
|
137
|
-
* internal state. Adopt them into native promises, which have no own fields,
|
|
138
|
-
* so key serialization sees a promise exactly as the original call did.
|
|
139
|
-
* Flight shares one chunk between references to the same promise, so each
|
|
140
|
-
* chunk is adopted once, including references inside resolved values.
|
|
141
|
-
*/
|
|
142
|
-
function adoptFlightThenables(value, adopted = /* @__PURE__ */ new WeakMap()) {
|
|
143
|
-
if (typeof value !== "object" || value === null) return value;
|
|
144
|
-
if (adopted.has(value)) return adopted.get(value);
|
|
145
|
-
if (isThenable(value)) {
|
|
146
|
-
const promise = Promise.resolve(value).then((resolved) => adoptFlightThenables(resolved, adopted));
|
|
147
|
-
promise.catch(() => {});
|
|
148
|
-
adopted.set(value, promise);
|
|
149
|
-
return promise;
|
|
150
|
-
}
|
|
151
|
-
if (value instanceof Map) {
|
|
152
|
-
adopted.set(value, value);
|
|
153
|
-
const entries = [...value];
|
|
154
|
-
value.clear();
|
|
155
|
-
for (const [key, item] of entries) value.set(adoptFlightThenables(key, adopted), adoptFlightThenables(item, adopted));
|
|
156
|
-
return value;
|
|
157
|
-
}
|
|
158
|
-
if (value instanceof Set) {
|
|
159
|
-
adopted.set(value, value);
|
|
160
|
-
const items = [...value];
|
|
161
|
-
value.clear();
|
|
162
|
-
for (const item of items) value.add(adoptFlightThenables(item, adopted));
|
|
163
|
-
return value;
|
|
164
|
-
}
|
|
165
|
-
if (!Array.isArray(value) && !isPlainRecord(value)) return value;
|
|
166
|
-
adopted.set(value, value);
|
|
167
|
-
for (const key of Object.keys(value)) Reflect.set(value, key, adoptFlightThenables(Reflect.get(value, key), adopted));
|
|
168
|
-
return value;
|
|
169
|
-
}
|
|
170
|
-
function isCacheCaptureEnvelope(value) {
|
|
171
|
-
if (typeof value !== "object" || value === null) return false;
|
|
172
|
-
if (!("type" in value) || value.type !== CACHE_CAPTURE_TYPE || !("encrypted" in value)) return false;
|
|
37
|
+
}();
|
|
38
|
+
const stream = renderToReadableStream(captures, { temporaryReferences });
|
|
39
|
+
const bytes = await new Response(stream).arrayBuffer();
|
|
40
|
+
return encryptActionBoundArgs(JSON.stringify({
|
|
41
|
+
version: 1,
|
|
42
|
+
referenceId,
|
|
43
|
+
result: Buffer.from(bytes).toString("base64"),
|
|
44
|
+
files: await snapshotFlightReply(files)
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
async function decryptCacheCaptures(value, referenceId, captureCount) {
|
|
48
|
+
if (typeof value !== "object" || value === null || !("type" in value) || value.type !== CACHE_CAPTURE_TYPE || !("encrypted" in value)) throw new Error("Invalid cache capture arguments");
|
|
173
49
|
const encrypted = value.encrypted;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
50
|
+
if (typeof encrypted !== "string" && !(typeof encrypted === "object" && encrypted !== null && "then" in encrypted && typeof encrypted.then === "function")) throw new Error("Invalid cache capture arguments");
|
|
51
|
+
const serialized = await decryptActionBoundArgs(Promise.resolve(encrypted));
|
|
52
|
+
if (typeof serialized !== "string") throw new Error("Invalid cache capture arguments");
|
|
53
|
+
const payload = JSON.parse(serialized);
|
|
54
|
+
if (payload.version !== 1 || payload.referenceId !== referenceId) throw new Error("Invalid cache capture arguments");
|
|
55
|
+
const files = restoreFlightReply(payload.files);
|
|
56
|
+
if (typeof files === "string") throw new Error("Invalid cache capture files");
|
|
57
|
+
const captures = await createFromReadableStream(new Response(Buffer.from(payload.result, "base64")).body, { temporaryReferences: new Map([...files].map(([id, file]) => [`$${id}`, file])) }, { preserveServerReferences: true });
|
|
58
|
+
if (!Array.isArray(captures) || captures.length !== captureCount) throw new Error("Invalid cache capture arguments");
|
|
59
|
+
return captures;
|
|
60
|
+
}
|
|
61
|
+
function registerCachedFunction(fn, id, variant, { captureCount, ...options }) {
|
|
62
|
+
let decryptCaptures;
|
|
63
|
+
if (captureCount !== void 0) {
|
|
64
|
+
const referenceId = options.serverReferenceId;
|
|
65
|
+
if (referenceId === void 0) throw new Error(`Cache function ${id} has captures but no server reference`);
|
|
66
|
+
decryptCaptures = (value) => decryptCacheCaptures(value, referenceId, captureCount);
|
|
67
|
+
}
|
|
177
68
|
return registerCachedFunction$1(fn, id, variant, {
|
|
178
69
|
...options,
|
|
179
|
-
decryptCaptures:
|
|
180
|
-
|
|
70
|
+
...decryptCaptures ? { decryptCaptures } : {},
|
|
71
|
+
encodeInvocation: encryptArguments
|
|
181
72
|
});
|
|
182
73
|
}
|
|
183
|
-
/**
|
|
74
|
+
/** Replay the persisted payload without re-reading or re-encoding caller objects. */
|
|
184
75
|
async function invokeCacheFunction(invocation, loadServerAction) {
|
|
185
76
|
const fn = await loadServerAction(invocation.referenceId);
|
|
186
77
|
if (!isUseCacheFunction(fn)) throw new Error(`Server reference ${invocation.referenceId} is not a cache function`);
|
|
187
|
-
await fn
|
|
78
|
+
await replayCachedFunction(fn, await decryptArguments(invocation.encryptedArgs));
|
|
188
79
|
}
|
|
189
80
|
//#endregion
|
|
190
|
-
export {
|
|
81
|
+
export { encryptCacheCaptures, invokeCacheFunction, registerCachedFunction };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/shims/cache-flight-arguments.d.ts
|
|
2
|
+
/** The persisted argument transport. React owns the object graph and wire protocol. */
|
|
3
|
+
export type CacheFlightArguments = {
|
|
4
|
+
version: 1;
|
|
5
|
+
reply: string | ([string, string] | [string, string, string, number, string])[];
|
|
6
|
+
pagePropsIndex?: number;
|
|
7
|
+
layoutPropsIndex?: number;
|
|
8
|
+
};
|
|
9
|
+
/** Snapshot only the multipart transport, never traverse user arguments. */
|
|
10
|
+
export declare function snapshotFlightReply(reply: string | FormData, pagePropsIndex?: number): Promise<CacheFlightArguments>;
|
|
11
|
+
export declare function restoreFlightReply(args: CacheFlightArguments): string | FormData;
|
|
12
|
+
/**
|
|
13
|
+
* Like Next.js (use-cache-wrapper.ts, `encodeFormData`), a binary entry is keyed
|
|
14
|
+
* by its bytes alone. Its name, type, and timestamp are replayed but not keyed:
|
|
15
|
+
* native FormData gives each Blob wrapper a wall-clock timestamp.
|
|
16
|
+
*
|
|
17
|
+
* Hashed synchronously, as Next.js derives its key without leaving the task: a
|
|
18
|
+
* cache hit must resolve before React flushes the shell, and an async digest
|
|
19
|
+
* waits for a later event-loop turn.
|
|
20
|
+
*/
|
|
21
|
+
export declare function flightArgumentsKey(args: CacheFlightArguments): string;
|
|
22
|
+
//#endregion
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
//#region src/shims/cache-flight-arguments.ts
|
|
3
|
+
const blobType = Object.getOwnPropertyDescriptor(Blob.prototype, "type").get;
|
|
4
|
+
const fileName = Object.getOwnPropertyDescriptor(File.prototype, "name").get;
|
|
5
|
+
const fileTime = Object.getOwnPropertyDescriptor(File.prototype, "lastModified").get;
|
|
6
|
+
/** Snapshot only the multipart transport, never traverse user arguments. */
|
|
7
|
+
async function snapshotFlightReply(reply, pagePropsIndex) {
|
|
8
|
+
if (typeof reply === "string") return {
|
|
9
|
+
version: 1,
|
|
10
|
+
reply,
|
|
11
|
+
pagePropsIndex
|
|
12
|
+
};
|
|
13
|
+
const entries = [];
|
|
14
|
+
for (const [name, value] of reply) entries.push(typeof value === "string" ? [name, value] : [
|
|
15
|
+
name,
|
|
16
|
+
Buffer.from(await Blob.prototype.arrayBuffer.call(value)).toString("base64"),
|
|
17
|
+
fileName.call(value),
|
|
18
|
+
fileTime.call(value),
|
|
19
|
+
blobType.call(value)
|
|
20
|
+
]);
|
|
21
|
+
return {
|
|
22
|
+
version: 1,
|
|
23
|
+
reply: entries,
|
|
24
|
+
pagePropsIndex
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function restoreFlightReply(args) {
|
|
28
|
+
if (typeof args.reply === "string") return args.reply;
|
|
29
|
+
const reply = new FormData();
|
|
30
|
+
for (const entry of args.reply) {
|
|
31
|
+
const [name, data] = entry;
|
|
32
|
+
reply.append(name, entry.length === 2 ? data : new File([Buffer.from(data, "base64")], entry[2], {
|
|
33
|
+
lastModified: entry[3],
|
|
34
|
+
type: entry[4]
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
return reply;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Like Next.js (use-cache-wrapper.ts, `encodeFormData`), a binary entry is keyed
|
|
41
|
+
* by its bytes alone. Its name, type, and timestamp are replayed but not keyed:
|
|
42
|
+
* native FormData gives each Blob wrapper a wall-clock timestamp.
|
|
43
|
+
*
|
|
44
|
+
* Hashed synchronously, as Next.js derives its key without leaving the task: a
|
|
45
|
+
* cache hit must resolve before React flushes the shell, and an async digest
|
|
46
|
+
* waits for a later event-loop turn.
|
|
47
|
+
*/
|
|
48
|
+
function flightArgumentsKey(args) {
|
|
49
|
+
const reply = typeof args.reply === "string" ? args.reply : args.reply.map((entry) => entry.length === 2 ? entry : [entry[0], { bytes: entry[1] }]);
|
|
50
|
+
return createHash("sha256").update(JSON.stringify({
|
|
51
|
+
...args,
|
|
52
|
+
reply
|
|
53
|
+
})).digest("base64url");
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { flightArgumentsKey, restoreFlightReply, snapshotFlightReply };
|
|
@@ -8,7 +8,6 @@ var NoOpCacheHandler = class {
|
|
|
8
8
|
async revalidateTag(_tags, _durations) {}
|
|
9
9
|
};
|
|
10
10
|
const DEFAULT_MEMORY_CACHE_MAX_SIZE = 52428800;
|
|
11
|
-
const MAX_REVALIDATED_TAG_ENTRIES = 1e4;
|
|
12
11
|
function estimateStringMapSize(map) {
|
|
13
12
|
if (!map) return 0;
|
|
14
13
|
let size = 0;
|
|
@@ -151,14 +150,7 @@ var MemoryCacheHandler = class {
|
|
|
151
150
|
async revalidateTag(tags) {
|
|
152
151
|
const tagList = Array.isArray(tags) ? tags : [tags];
|
|
153
152
|
const now = Date.now();
|
|
154
|
-
for (const tag of tagList)
|
|
155
|
-
this.tagRevalidatedAt.set(tag, now);
|
|
156
|
-
while (this.tagRevalidatedAt.size > MAX_REVALIDATED_TAG_ENTRIES) {
|
|
157
|
-
const oldest = this.tagRevalidatedAt.keys().next().value;
|
|
158
|
-
if (oldest === void 0) break;
|
|
159
|
-
this.tagRevalidatedAt.delete(oldest);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
153
|
+
for (const tag of tagList) this.tagRevalidatedAt.set(tag, now);
|
|
162
154
|
}
|
|
163
155
|
resetRequestCache() {}
|
|
164
156
|
};
|
|
@@ -15,8 +15,17 @@ export type UnstableCacheObservation = Readonly<{
|
|
|
15
15
|
tagCount: number;
|
|
16
16
|
tagHash: string | null;
|
|
17
17
|
}>;
|
|
18
|
+
/**
|
|
19
|
+
* Collects the cacheLife claims made anywhere below the scope that installed
|
|
20
|
+
* it, including nested scopes that reset `requestScopedCacheLife`. Shallow
|
|
21
|
+
* scope clones share it by reference.
|
|
22
|
+
*/
|
|
23
|
+
export type CacheLifeSink = {
|
|
24
|
+
cacheLife: CacheLifeConfig | null;
|
|
25
|
+
};
|
|
18
26
|
export type CacheState = {
|
|
19
27
|
actionRevalidationKind: ActionRevalidationKind;
|
|
28
|
+
cacheLifeSink: CacheLifeSink | null;
|
|
20
29
|
pendingRevalidatedTags: Set<string>;
|
|
21
30
|
pendingRevalidations: Set<Promise<void>>;
|
|
22
31
|
requestScopedCacheLife: CacheLifeConfig | null;
|
|
@@ -70,6 +79,12 @@ export declare function _captureRequestScopedCacheLifeAccessors(): {
|
|
|
70
79
|
};
|
|
71
80
|
export declare function recordUnstableCacheObservation(observation: UnstableCacheObservation): void;
|
|
72
81
|
export declare function _peekUnstableCacheObservations(): UnstableCacheObservation[];
|
|
82
|
+
/**
|
|
83
|
+
* Run `fn` with the request's cache settings, including its revalidation mode,
|
|
84
|
+
* but its own record of cache lives and unstable_cache observations, so work
|
|
85
|
+
* done on the request's behalf after the fact leaves the request untouched.
|
|
86
|
+
*/
|
|
87
|
+
export declare function runWithDetachedCacheObservations<T>(fn: () => Promise<T>): Promise<T>;
|
|
73
88
|
export declare function shouldServeStaleUnstableCacheEntry(): boolean;
|
|
74
89
|
//#endregion
|
|
75
90
|
export { _recordUseCacheRootParamRead, _registerCacheContextAccessor, getRegisteredCacheContext };
|
|
@@ -47,6 +47,7 @@ const ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC = 1;
|
|
|
47
47
|
const ACTION_DID_REVALIDATE_DYNAMIC_ONLY = 2;
|
|
48
48
|
const fallbackState = globalState[FALLBACK_KEY] ??= {
|
|
49
49
|
actionRevalidationKind: ACTION_DID_NOT_REVALIDATE,
|
|
50
|
+
cacheLifeSink: null,
|
|
50
51
|
pendingRevalidatedTags: /* @__PURE__ */ new Set(),
|
|
51
52
|
pendingRevalidations: /* @__PURE__ */ new Set(),
|
|
52
53
|
requestScopedCacheLife: null,
|
|
@@ -60,12 +61,14 @@ function getCacheState() {
|
|
|
60
61
|
function _runWithCacheState(fn) {
|
|
61
62
|
if (isInsideUnifiedScope()) return runWithUnifiedStateMutation((context) => {
|
|
62
63
|
context.actionRevalidationKind = ACTION_DID_NOT_REVALIDATE;
|
|
64
|
+
context.cacheLifeSink = null;
|
|
63
65
|
context.requestScopedCacheLife = null;
|
|
64
66
|
context.unstableCacheObservations = /* @__PURE__ */ new Map();
|
|
65
67
|
context.unstableCacheRevalidation = "foreground";
|
|
66
68
|
}, fn);
|
|
67
69
|
const state = {
|
|
68
70
|
actionRevalidationKind: ACTION_DID_NOT_REVALIDATE,
|
|
71
|
+
cacheLifeSink: null,
|
|
69
72
|
pendingRevalidatedTags: /* @__PURE__ */ new Set(),
|
|
70
73
|
pendingRevalidations: /* @__PURE__ */ new Set(),
|
|
71
74
|
requestScopedCacheLife: null,
|
|
@@ -146,15 +149,17 @@ async function _drainPendingRevalidations() {
|
|
|
146
149
|
}
|
|
147
150
|
if (didReject) throw firstRejection;
|
|
148
151
|
}
|
|
152
|
+
function mergeCacheLife(current, config) {
|
|
153
|
+
if (current === null) return { ...config };
|
|
154
|
+
if (config.stale !== void 0) current.stale = current.stale !== void 0 ? Math.min(current.stale, config.stale) : config.stale;
|
|
155
|
+
if (config.revalidate !== void 0) current.revalidate = current.revalidate !== void 0 ? Math.min(current.revalidate, config.revalidate) : config.revalidate;
|
|
156
|
+
if (config.expire !== void 0) current.expire = current.expire !== void 0 ? Math.min(current.expire, config.expire) : config.expire;
|
|
157
|
+
return current;
|
|
158
|
+
}
|
|
149
159
|
function _setRequestScopedCacheLife(config) {
|
|
150
160
|
const state = getCacheState();
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
if (config.stale !== void 0) state.requestScopedCacheLife.stale = state.requestScopedCacheLife.stale !== void 0 ? Math.min(state.requestScopedCacheLife.stale, config.stale) : config.stale;
|
|
156
|
-
if (config.revalidate !== void 0) state.requestScopedCacheLife.revalidate = state.requestScopedCacheLife.revalidate !== void 0 ? Math.min(state.requestScopedCacheLife.revalidate, config.revalidate) : config.revalidate;
|
|
157
|
-
if (config.expire !== void 0) state.requestScopedCacheLife.expire = state.requestScopedCacheLife.expire !== void 0 ? Math.min(state.requestScopedCacheLife.expire, config.expire) : config.expire;
|
|
161
|
+
state.requestScopedCacheLife = mergeCacheLife(state.requestScopedCacheLife, config);
|
|
162
|
+
if (state.cacheLifeSink) state.cacheLifeSink.cacheLife = mergeCacheLife(state.cacheLifeSink.cacheLife, config);
|
|
158
163
|
}
|
|
159
164
|
function _peekRequestScopedCacheLife() {
|
|
160
165
|
const config = getCacheState().requestScopedCacheLife;
|
|
@@ -193,8 +198,26 @@ function recordUnstableCacheObservation(observation) {
|
|
|
193
198
|
function _peekUnstableCacheObservations() {
|
|
194
199
|
return [...getCacheState().unstableCacheObservations.values()].sort((a, b) => a.keyHash.localeCompare(b.keyHash));
|
|
195
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Run `fn` with the request's cache settings, including its revalidation mode,
|
|
203
|
+
* but its own record of cache lives and unstable_cache observations, so work
|
|
204
|
+
* done on the request's behalf after the fact leaves the request untouched.
|
|
205
|
+
*/
|
|
206
|
+
function runWithDetachedCacheObservations(fn) {
|
|
207
|
+
if (isInsideUnifiedScope()) return runWithUnifiedStateMutation((context) => {
|
|
208
|
+
context.cacheLifeSink = null;
|
|
209
|
+
context.requestScopedCacheLife = null;
|
|
210
|
+
context.unstableCacheObservations = /* @__PURE__ */ new Map();
|
|
211
|
+
}, fn);
|
|
212
|
+
return cacheAls.run({
|
|
213
|
+
...getCacheState(),
|
|
214
|
+
cacheLifeSink: null,
|
|
215
|
+
requestScopedCacheLife: null,
|
|
216
|
+
unstableCacheObservations: /* @__PURE__ */ new Map()
|
|
217
|
+
}, fn);
|
|
218
|
+
}
|
|
196
219
|
function shouldServeStaleUnstableCacheEntry() {
|
|
197
220
|
return getCacheState().unstableCacheRevalidation === "background";
|
|
198
221
|
}
|
|
199
222
|
//#endregion
|
|
200
|
-
export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _recordUseCacheRootParamRead, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry };
|
|
223
|
+
export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingRevalidation, _recordUseCacheRootParamRead, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry };
|