vinext 1.3.1 → 1.4.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 +5 -2
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +1 -1
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +1 -1
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay.js +1 -1
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/next-config.d.ts +19 -0
- package/dist/config/next-config.js +64 -1
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
- package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
- package/dist/entries/app-rsc-entry.js +17 -48
- package/dist/entries/app-rsc-manifest.js +3 -4
- package/dist/entries/app-ssr-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +33 -8
- package/dist/index.js +83 -70
- package/dist/init-cloudflare.d.ts +1 -3
- package/dist/init-cloudflare.js +10 -48
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +4 -0
- package/dist/plugins/extensionless-dynamic-import.js +6 -2
- package/dist/plugins/next-intl-catalog.d.ts +12 -0
- package/dist/plugins/next-intl-catalog.js +85 -0
- package/dist/plugins/pages-node-externals.d.ts +1 -0
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/use-cache-callable.d.ts +1 -1
- package/dist/plugins/use-cache-callable.js +136 -94
- package/dist/routing/app-route-graph.d.ts +6 -0
- package/dist/routing/app-route-graph.js +9 -1
- package/dist/server/api-handler.js +19 -4
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +79 -63
- package/dist/server/app-browser-history-controller.d.ts +5 -4
- package/dist/server/app-browser-history-controller.js +93 -15
- package/dist/server/app-browser-navigation-controller.d.ts +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -2
- package/dist/server/app-browser-rsc-redirect.js +4 -4
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +4 -3
- package/dist/server/app-browser-state.d.ts +2 -4
- package/dist/server/app-browser-state.js +9 -4
- package/dist/server/app-browser-supplemental-refresh.js +16 -1
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-browser-visible-commit.js +2 -12
- package/dist/server/app-elements-wire.d.ts +6 -38
- package/dist/server/app-elements-wire.js +4 -41
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-history-state.d.ts +2 -2
- package/dist/server/app-history-state.js +5 -2
- package/dist/server/app-mounted-layouts.d.ts +21 -0
- package/dist/server/app-mounted-layouts.js +67 -0
- package/dist/server/app-optimistic-routing.d.ts +19 -1
- package/dist/server/app-optimistic-routing.js +42 -2
- package/dist/server/app-page-boundary-render.js +7 -6
- package/dist/server/app-page-boundary.js +2 -2
- package/dist/server/app-page-cache-finalizer.d.ts +12 -1
- package/dist/server/app-page-cache-finalizer.js +70 -29
- package/dist/server/app-page-cache.d.ts +13 -1
- package/dist/server/app-page-cache.js +31 -9
- package/dist/server/app-page-dispatch.d.ts +5 -10
- package/dist/server/app-page-dispatch.js +84 -154
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +10 -9
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +99 -95
- package/dist/server/app-page-head.d.ts +13 -0
- package/dist/server/app-page-head.js +44 -16
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
- package/dist/server/app-page-layout-gate.d.ts +35 -0
- package/dist/server/app-page-layout-gate.js +50 -0
- package/dist/server/app-page-params.d.ts +0 -1
- package/dist/server/app-page-params.js +1 -14
- package/dist/server/app-page-probe.d.ts +3 -21
- package/dist/server/app-page-probe.js +4 -37
- package/dist/server/app-page-render.d.ts +2 -12
- package/dist/server/app-page-render.js +89 -220
- package/dist/server/app-page-request.d.ts +1 -3
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-response.js +3 -3
- package/dist/server/app-page-route-wiring.d.ts +13 -6
- package/dist/server/app-page-route-wiring.js +67 -61
- package/dist/server/app-page-rsc-render-status.d.ts +27 -1
- package/dist/server/app-page-rsc-render-status.js +121 -13
- package/dist/server/app-page-stream.d.ts +2 -0
- package/dist/server/app-page-stream.js +2 -2
- package/dist/server/app-pages-bridge.d.ts +4 -0
- package/dist/server/app-pages-bridge.js +7 -3
- package/dist/server/app-render-dependency.d.ts +11 -4
- package/dist/server/app-render-dependency.js +86 -38
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-route-handler-cache.js +2 -2
- package/dist/server/app-route-handler-dispatch.js +14 -9
- package/dist/server/app-route-handler-execution.js +8 -3
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-handler-runtime.js +17 -4
- package/dist/server/app-rsc-cache-busting.d.ts +2 -2
- package/dist/server/app-rsc-cache-busting.js +4 -4
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +9 -1
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +8 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +30 -24
- package/dist/server/app-rsc-request-normalization.d.ts +0 -4
- package/dist/server/app-rsc-request-normalization.js +1 -4
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +5 -3
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +7 -4
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +9 -8
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/app-visited-response-cache.d.ts +36 -1
- package/dist/server/app-visited-response-cache.js +46 -5
- package/dist/server/app-worker-stages.d.ts +25 -3
- package/dist/server/app-worker-stages.js +45 -6
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-server.js +4 -3
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +26 -1
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/multi-stage.d.ts +52 -11
- package/dist/server/multi-stage.js +13 -1
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/pages-api-route.js +28 -19
- package/dist/server/pages-media-type.d.ts +21 -1
- package/dist/server/pages-media-type.js +69 -5
- package/dist/server/pages-node-compat.js +52 -27
- package/dist/server/pages-page-handler.js +11 -20
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +2 -2
- package/dist/server/pages-request-stage-entry.js +14 -12
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/prod-server.js +5 -1
- package/dist/server/request-pipeline.d.ts +6 -0
- package/dist/server/request-pipeline.js +21 -1
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- package/dist/server/worker-stages.d.ts +16 -3
- package/dist/server/worker-stages.js +23 -4
- package/dist/shims/cache-handler.js +2 -2
- package/dist/shims/cache-request-state.d.ts +17 -20
- package/dist/shims/cache-request-state.js +16 -21
- package/dist/shims/cache-runtime.js +27 -11
- package/dist/shims/cache.d.ts +8 -7
- package/dist/shims/cache.js +17 -19
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- package/dist/shims/client-page-root.js +2 -2
- package/dist/shims/dynamic.js +9 -6
- package/dist/shims/error-boundary.js +2 -2
- package/dist/shims/fetch-cache-state.d.ts +5 -1
- package/dist/shims/fetch-cache-state.js +1 -3
- package/dist/shims/fetch-cache.d.ts +2 -1
- package/dist/shims/fetch-cache.js +34 -24
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +8 -23
- package/dist/shims/headers.js +17 -67
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +3 -1
- package/dist/shims/metadata.d.ts +23 -21
- package/dist/shims/metadata.js +62 -24
- package/dist/shims/navigation-server.js +1 -1
- package/dist/shims/navigation.d.ts +74 -7
- package/dist/shims/navigation.js +183 -29
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +2 -2
- package/dist/shims/slot.d.ts +12 -0
- package/dist/shims/slot.js +37 -9
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +2 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- package/dist/utils/project.d.ts +2 -2
- package/dist/utils/project.js +3 -16
- package/dist/utils/regex.d.ts +5 -0
- package/dist/utils/regex.js +11 -1
- package/dist/utils/text-stream.d.ts +10 -5
- package/dist/utils/text-stream.js +6 -6
- package/package.json +2 -1
- package/dist/build/layout-classification-types.d.ts +0 -60
- package/dist/build/layout-classification-types.js +0 -1
- package/dist/build/layout-classification.d.ts +0 -62
- package/dist/build/layout-classification.js +0 -98
- package/dist/build/route-classification-injector.d.ts +0 -33
- package/dist/build/route-classification-injector.js +0 -59
- package/dist/build/route-classification-manifest.d.ts +0 -54
- package/dist/build/route-classification-manifest.js +0 -143
- package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
- package/dist/server/app-browser-client-reuse-manifest.js +0 -101
- package/dist/server/app-layout-param-observation.d.ts +0 -42
- package/dist/server/app-layout-param-observation.js +0 -168
- package/dist/server/client-reuse-manifest.d.ts +0 -103
- package/dist/server/client-reuse-manifest.js +0 -209
- package/dist/server/skip-cache-proof.d.ts +0 -60
- package/dist/server/skip-cache-proof.js +0 -168
- package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
- package/dist/server/static-layout-client-reuse-proof.js +0 -33
- package/dist/utils/sorted-array.d.ts +0 -8
- package/dist/utils/sorted-array.js +0 -20
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
import { fnv1a64 } from "../utils/hash.js";
|
|
2
|
-
import { evaluateArtifactCompatibility } from "./artifact-compatibility.js";
|
|
3
|
-
import { findSortedStringPosition } from "../utils/sorted-array.js";
|
|
4
2
|
//#region src/server/cache-proof.ts
|
|
5
3
|
const CACHE_PROOF_MODEL_SCHEMA_VERSION = 1;
|
|
6
|
-
const DEFAULT_CACHE_VARIANT_BUDGET = {
|
|
7
|
-
maxDimensionCount: 8,
|
|
8
|
-
maxDimensionNameLength: 64,
|
|
9
|
-
maxDimensionValueLength: 256,
|
|
10
|
-
maxEncodedLength: 1024,
|
|
11
|
-
maxValuesPerDimension: 8,
|
|
12
|
-
maxVariantsPerRoute: 64
|
|
13
|
-
};
|
|
14
4
|
const ALL_RENDER_REQUEST_API_KINDS = [
|
|
15
5
|
"connection",
|
|
16
6
|
"cookies",
|
|
@@ -19,13 +9,6 @@ const ALL_RENDER_REQUEST_API_KINDS = [
|
|
|
19
9
|
"params",
|
|
20
10
|
"searchParams"
|
|
21
11
|
];
|
|
22
|
-
const PUBLIC_UNSAFE_DIMENSION_SOURCES = /* @__PURE__ */ new Set([
|
|
23
|
-
"auth",
|
|
24
|
-
"cookie",
|
|
25
|
-
"draft-mode",
|
|
26
|
-
"header",
|
|
27
|
-
"session"
|
|
28
|
-
]);
|
|
29
12
|
function buildBreakerFallback(code, fields = {}, mode = "renderFresh", scope = "affectedOutput") {
|
|
30
13
|
return {
|
|
31
14
|
kind: "breakerFallback",
|
|
@@ -38,332 +21,15 @@ function buildBreakerFallback(code, fields = {}, mode = "renderFresh", scope = "
|
|
|
38
21
|
function sortedUnique(values) {
|
|
39
22
|
return [...new Set(values)].sort();
|
|
40
23
|
}
|
|
41
|
-
function normalizeDimensionName(name) {
|
|
42
|
-
return name.trim().toLowerCase();
|
|
43
|
-
}
|
|
44
24
|
function redactValue(value) {
|
|
45
25
|
return `h:${fnv1a64(value)}`;
|
|
46
26
|
}
|
|
47
27
|
function sortedUniqueRedacted(values) {
|
|
48
28
|
return sortedUnique(sortedUnique(values).map(redactValue));
|
|
49
29
|
}
|
|
50
|
-
function encodeParts(parts) {
|
|
51
|
-
return JSON.stringify(parts);
|
|
52
|
-
}
|
|
53
|
-
function compareDimensions(a, b) {
|
|
54
|
-
return a.source.localeCompare(b.source) || a.name.localeCompare(b.name) || a.privacy.localeCompare(b.privacy);
|
|
55
|
-
}
|
|
56
|
-
function encodeNullable(value) {
|
|
57
|
-
return value;
|
|
58
|
-
}
|
|
59
30
|
function assertNever(value) {
|
|
60
31
|
throw new Error(`Unhandled cache proof variant: ${String(value)}`);
|
|
61
32
|
}
|
|
62
|
-
function encodeOutputScope(output) {
|
|
63
|
-
switch (output.kind) {
|
|
64
|
-
case "app-html": return encodeParts([
|
|
65
|
-
output.kind,
|
|
66
|
-
output.routeId,
|
|
67
|
-
encodeNullable(output.rootBoundaryId),
|
|
68
|
-
encodeNullable(output.renderEpoch)
|
|
69
|
-
]);
|
|
70
|
-
case "app-rsc": return encodeParts([
|
|
71
|
-
output.kind,
|
|
72
|
-
output.routeId,
|
|
73
|
-
encodeNullable(output.rootBoundaryId),
|
|
74
|
-
encodeNullable(output.renderEpoch),
|
|
75
|
-
encodeNullable(output.mountedSlotsFingerprint)
|
|
76
|
-
]);
|
|
77
|
-
case "layout": return encodeParts([
|
|
78
|
-
output.kind,
|
|
79
|
-
output.routeId,
|
|
80
|
-
output.layoutId,
|
|
81
|
-
encodeNullable(output.rootBoundaryId)
|
|
82
|
-
]);
|
|
83
|
-
case "page": return encodeParts([
|
|
84
|
-
output.kind,
|
|
85
|
-
output.routeId,
|
|
86
|
-
output.pageId,
|
|
87
|
-
encodeNullable(output.rootBoundaryId)
|
|
88
|
-
]);
|
|
89
|
-
case "route-handler": return encodeParts([
|
|
90
|
-
output.kind,
|
|
91
|
-
output.routeId,
|
|
92
|
-
output.routeHandlerId
|
|
93
|
-
]);
|
|
94
|
-
case "slot": return encodeParts([
|
|
95
|
-
output.kind,
|
|
96
|
-
output.routeId,
|
|
97
|
-
output.slotId,
|
|
98
|
-
encodeNullable(output.rootBoundaryId)
|
|
99
|
-
]);
|
|
100
|
-
case "template": return encodeParts([
|
|
101
|
-
output.kind,
|
|
102
|
-
output.routeId,
|
|
103
|
-
output.templateId,
|
|
104
|
-
encodeNullable(output.rootBoundaryId)
|
|
105
|
-
]);
|
|
106
|
-
default: return assertNever(output);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
function validateBudgetNumber(name, value) {
|
|
110
|
-
if (Number.isInteger(value) && value >= 0) return null;
|
|
111
|
-
return buildBreakerFallback("CP_INVALID_VARIANT_BUDGET", { budgetField: name });
|
|
112
|
-
}
|
|
113
|
-
function validateBudget(budget) {
|
|
114
|
-
return validateBudgetNumber("maxDimensionCount", budget.maxDimensionCount) ?? validateBudgetNumber("maxDimensionNameLength", budget.maxDimensionNameLength) ?? validateBudgetNumber("maxDimensionValueLength", budget.maxDimensionValueLength) ?? validateBudgetNumber("maxEncodedLength", budget.maxEncodedLength) ?? validateBudgetNumber("maxValuesPerDimension", budget.maxValuesPerDimension) ?? validateBudgetNumber("maxVariantsPerRoute", budget.maxVariantsPerRoute);
|
|
115
|
-
}
|
|
116
|
-
function buildDimension(input, budget) {
|
|
117
|
-
const name = normalizeDimensionName(input.name);
|
|
118
|
-
if (name.length === 0) return buildBreakerFallback("CP_DIMENSION_NAME_MISSING", { source: input.source });
|
|
119
|
-
if (name.length > budget.maxDimensionNameLength) return buildBreakerFallback("CP_DIMENSION_NAME_TOO_LONG", {
|
|
120
|
-
maxLength: budget.maxDimensionNameLength,
|
|
121
|
-
nameHash: redactValue(name),
|
|
122
|
-
source: input.source
|
|
123
|
-
});
|
|
124
|
-
if (input.privacy === "public" && PUBLIC_UNSAFE_DIMENSION_SOURCES.has(input.source)) return buildBreakerFallback("CP_UNSAFE_PUBLIC_DIMENSION", {
|
|
125
|
-
name,
|
|
126
|
-
source: input.source
|
|
127
|
-
}, "privateUncacheable");
|
|
128
|
-
const values = sortedUnique(input.values);
|
|
129
|
-
if (values.length === 0) return buildBreakerFallback("CP_DIMENSION_VALUES_MISSING", {
|
|
130
|
-
name,
|
|
131
|
-
source: input.source
|
|
132
|
-
});
|
|
133
|
-
if (values.length > budget.maxValuesPerDimension) return buildBreakerFallback("CP_DIMENSION_VALUE_COUNT_EXCEEDED", {
|
|
134
|
-
maxValues: budget.maxValuesPerDimension,
|
|
135
|
-
name,
|
|
136
|
-
source: input.source,
|
|
137
|
-
valueCount: values.length
|
|
138
|
-
});
|
|
139
|
-
for (const value of values) if (value.length > budget.maxDimensionValueLength) return buildBreakerFallback("CP_DIMENSION_VALUE_TOO_LONG", {
|
|
140
|
-
maxLength: budget.maxDimensionValueLength,
|
|
141
|
-
name,
|
|
142
|
-
source: input.source,
|
|
143
|
-
valueHash: redactValue(value)
|
|
144
|
-
});
|
|
145
|
-
const valueHashes = values.map(redactValue);
|
|
146
|
-
return {
|
|
147
|
-
encoded: encodeParts([
|
|
148
|
-
input.source,
|
|
149
|
-
input.privacy,
|
|
150
|
-
name,
|
|
151
|
-
valueHashes
|
|
152
|
-
]),
|
|
153
|
-
name,
|
|
154
|
-
privacy: input.privacy,
|
|
155
|
-
source: input.source,
|
|
156
|
-
valueCount: valueHashes.length,
|
|
157
|
-
valueHashes
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
function isCacheProofBreakerFallback(value) {
|
|
161
|
-
return "code" in value;
|
|
162
|
-
}
|
|
163
|
-
function getDimensionBucket(bySource, source, privacy) {
|
|
164
|
-
const existingByPrivacy = bySource.get(source);
|
|
165
|
-
const byPrivacy = existingByPrivacy ?? /* @__PURE__ */ new Map();
|
|
166
|
-
if (!existingByPrivacy) bySource.set(source, byPrivacy);
|
|
167
|
-
const existingByName = byPrivacy.get(privacy);
|
|
168
|
-
const byName = existingByName ?? /* @__PURE__ */ new Map();
|
|
169
|
-
if (!existingByName) byPrivacy.set(privacy, byName);
|
|
170
|
-
return byName;
|
|
171
|
-
}
|
|
172
|
-
function mergeDimensionInputs(dimensions) {
|
|
173
|
-
const bySource = /* @__PURE__ */ new Map();
|
|
174
|
-
const orderedDimensions = [];
|
|
175
|
-
for (const dimension of dimensions) {
|
|
176
|
-
const name = normalizeDimensionName(dimension.name);
|
|
177
|
-
const bucket = getDimensionBucket(bySource, dimension.source, dimension.privacy);
|
|
178
|
-
const existing = bucket.get(name);
|
|
179
|
-
if (existing) {
|
|
180
|
-
existing.values.push(...dimension.values);
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
const accumulator = {
|
|
184
|
-
name,
|
|
185
|
-
privacy: dimension.privacy,
|
|
186
|
-
source: dimension.source,
|
|
187
|
-
values: [...dimension.values]
|
|
188
|
-
};
|
|
189
|
-
bucket.set(name, accumulator);
|
|
190
|
-
orderedDimensions.push(accumulator);
|
|
191
|
-
}
|
|
192
|
-
return orderedDimensions;
|
|
193
|
-
}
|
|
194
|
-
function createAppRouteCacheProofGraphScope(route) {
|
|
195
|
-
return {
|
|
196
|
-
routeId: route.ids.route,
|
|
197
|
-
pageId: route.ids.page,
|
|
198
|
-
routeHandlerId: route.ids.routeHandler,
|
|
199
|
-
layoutIds: [...route.ids.layouts],
|
|
200
|
-
templateIds: [...route.ids.templates],
|
|
201
|
-
slotIds: sortedUnique(Object.values(route.ids.slots))
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
function buildCacheVariant(input) {
|
|
205
|
-
const budgetFallback = validateBudget(input.budget);
|
|
206
|
-
if (budgetFallback) return {
|
|
207
|
-
kind: "breakerFallback",
|
|
208
|
-
fallback: budgetFallback
|
|
209
|
-
};
|
|
210
|
-
const dimensionInputs = mergeDimensionInputs(input.dimensions);
|
|
211
|
-
if (dimensionInputs.length > input.budget.maxDimensionCount) return {
|
|
212
|
-
kind: "breakerFallback",
|
|
213
|
-
fallback: buildBreakerFallback("CP_DIMENSION_COUNT_EXCEEDED", {
|
|
214
|
-
dimensionCount: dimensionInputs.length,
|
|
215
|
-
maxDimensionCount: input.budget.maxDimensionCount,
|
|
216
|
-
routeId: input.output.routeId
|
|
217
|
-
})
|
|
218
|
-
};
|
|
219
|
-
const dimensions = [];
|
|
220
|
-
for (const dimensionInput of dimensionInputs) {
|
|
221
|
-
const dimension = buildDimension(dimensionInput, input.budget);
|
|
222
|
-
if (isCacheProofBreakerFallback(dimension)) return {
|
|
223
|
-
kind: "breakerFallback",
|
|
224
|
-
fallback: dimension
|
|
225
|
-
};
|
|
226
|
-
dimensions.push(dimension);
|
|
227
|
-
}
|
|
228
|
-
dimensions.sort(compareDimensions);
|
|
229
|
-
const encoded = [
|
|
230
|
-
`schema:1`,
|
|
231
|
-
encodeOutputScope(input.output),
|
|
232
|
-
...dimensions.map((dimension) => dimension.encoded)
|
|
233
|
-
].join("|");
|
|
234
|
-
if (encoded.length > input.budget.maxEncodedLength) return {
|
|
235
|
-
kind: "breakerFallback",
|
|
236
|
-
fallback: buildBreakerFallback("CP_ENCODED_VARIANT_TOO_LONG", {
|
|
237
|
-
encodedHash: redactValue(encoded),
|
|
238
|
-
encodedLength: encoded.length,
|
|
239
|
-
maxEncodedLength: input.budget.maxEncodedLength,
|
|
240
|
-
routeId: input.output.routeId
|
|
241
|
-
})
|
|
242
|
-
};
|
|
243
|
-
return {
|
|
244
|
-
kind: "variant",
|
|
245
|
-
variant: {
|
|
246
|
-
schemaVersion: 1,
|
|
247
|
-
cacheKey: `cp1:${fnv1a64(encoded)}`,
|
|
248
|
-
output: input.output,
|
|
249
|
-
dimensions,
|
|
250
|
-
encodedLength: encoded.length,
|
|
251
|
-
budget: { ...input.budget }
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
function normalizeRouteBudget(input) {
|
|
256
|
-
return {
|
|
257
|
-
routeId: input.routeId,
|
|
258
|
-
variantCacheKeys: sortedUnique(input.variantCacheKeys)
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
function buildRouteVariantCeilingFallback(variant, existingVariantCount) {
|
|
262
|
-
return buildBreakerFallback("CP_ROUTE_VARIANT_CEILING_EXCEEDED", {
|
|
263
|
-
existingVariantCount,
|
|
264
|
-
maxVariantsPerRoute: variant.budget.maxVariantsPerRoute,
|
|
265
|
-
routeId: variant.output.routeId
|
|
266
|
-
}, "privateUncacheable", "route");
|
|
267
|
-
}
|
|
268
|
-
function enforceCacheVariantRouteBudget(input) {
|
|
269
|
-
if (input.routeBudget && input.routeBudget.routeId !== input.variant.output.routeId) return {
|
|
270
|
-
kind: "breakerFallback",
|
|
271
|
-
routeBudget: normalizeRouteBudget(input.routeBudget),
|
|
272
|
-
fallback: buildBreakerFallback("CP_ROUTE_VARIANT_BUDGET_ROUTE_MISMATCH", {
|
|
273
|
-
budgetRouteId: input.routeBudget.routeId,
|
|
274
|
-
routeId: input.variant.output.routeId
|
|
275
|
-
}, "privateUncacheable", "route")
|
|
276
|
-
};
|
|
277
|
-
const routeBudget = normalizeRouteBudget(input.routeBudget ?? {
|
|
278
|
-
routeId: input.variant.output.routeId,
|
|
279
|
-
variantCacheKeys: []
|
|
280
|
-
});
|
|
281
|
-
const existingVariantCount = routeBudget.variantCacheKeys.length;
|
|
282
|
-
const variantKeyPosition = findSortedStringPosition(routeBudget.variantCacheKeys, input.variant.cacheKey);
|
|
283
|
-
if (existingVariantCount > input.variant.budget.maxVariantsPerRoute) return {
|
|
284
|
-
kind: "breakerFallback",
|
|
285
|
-
routeBudget,
|
|
286
|
-
fallback: buildRouteVariantCeilingFallback(input.variant, existingVariantCount)
|
|
287
|
-
};
|
|
288
|
-
if (variantKeyPosition.found) return {
|
|
289
|
-
kind: "variant",
|
|
290
|
-
variant: input.variant,
|
|
291
|
-
routeBudget,
|
|
292
|
-
didConsumeRouteVariantBudget: false
|
|
293
|
-
};
|
|
294
|
-
if (existingVariantCount >= input.variant.budget.maxVariantsPerRoute) return {
|
|
295
|
-
kind: "breakerFallback",
|
|
296
|
-
routeBudget,
|
|
297
|
-
fallback: buildRouteVariantCeilingFallback(input.variant, existingVariantCount)
|
|
298
|
-
};
|
|
299
|
-
return {
|
|
300
|
-
kind: "variant",
|
|
301
|
-
variant: input.variant,
|
|
302
|
-
routeBudget: {
|
|
303
|
-
routeId: routeBudget.routeId,
|
|
304
|
-
variantCacheKeys: [
|
|
305
|
-
...routeBudget.variantCacheKeys.slice(0, variantKeyPosition.index),
|
|
306
|
-
input.variant.cacheKey,
|
|
307
|
-
...routeBudget.variantCacheKeys.slice(variantKeyPosition.index)
|
|
308
|
-
]
|
|
309
|
-
},
|
|
310
|
-
didConsumeRouteVariantBudget: true
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
function buildCacheVariantWithRouteBudget(input) {
|
|
314
|
-
const variantResult = buildCacheVariant({
|
|
315
|
-
budget: input.budget,
|
|
316
|
-
dimensions: input.dimensions,
|
|
317
|
-
output: input.output
|
|
318
|
-
});
|
|
319
|
-
if (variantResult.kind === "breakerFallback") return {
|
|
320
|
-
kind: "breakerFallback",
|
|
321
|
-
routeBudget: input.routeBudget ? normalizeRouteBudget(input.routeBudget) : null,
|
|
322
|
-
fallback: variantResult.fallback
|
|
323
|
-
};
|
|
324
|
-
return enforceCacheVariantRouteBudget({
|
|
325
|
-
routeBudget: input.routeBudget,
|
|
326
|
-
variant: variantResult.variant
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
function boundaryOutcomesMatch(expected, candidate) {
|
|
330
|
-
switch (expected.kind) {
|
|
331
|
-
case "error": return candidate.kind === "error" && (expected.digest ?? "") === (candidate.digest ?? "");
|
|
332
|
-
case "forbidden": return candidate.kind === "forbidden";
|
|
333
|
-
case "globalError": return candidate.kind === "globalError" && (expected.digest ?? "") === (candidate.digest ?? "");
|
|
334
|
-
case "notFound": return candidate.kind === "notFound";
|
|
335
|
-
case "redirect": return candidate.kind === "redirect" && expected.status === candidate.status && expected.location === candidate.location;
|
|
336
|
-
case "success": return candidate.kind === "success";
|
|
337
|
-
case "unauthorized": return candidate.kind === "unauthorized";
|
|
338
|
-
case "unknown": return false;
|
|
339
|
-
default: return assertNever(expected);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
function buildBoundaryOutcomeCompatibility(input) {
|
|
343
|
-
if (input.expected.kind === "unknown" || input.candidate.kind === "unknown") return {
|
|
344
|
-
kind: "incompatible",
|
|
345
|
-
expected: input.expected,
|
|
346
|
-
candidate: input.candidate,
|
|
347
|
-
fallback: buildBreakerFallback("CP_BOUNDARY_OUTCOME_UNKNOWN", {
|
|
348
|
-
candidateKind: input.candidate.kind,
|
|
349
|
-
expectedKind: input.expected.kind
|
|
350
|
-
})
|
|
351
|
-
};
|
|
352
|
-
if (boundaryOutcomesMatch(input.expected, input.candidate)) return {
|
|
353
|
-
kind: "compatible",
|
|
354
|
-
outcome: input.candidate,
|
|
355
|
-
reason: "CP_BOUNDARY_OUTCOME_MATCH"
|
|
356
|
-
};
|
|
357
|
-
return {
|
|
358
|
-
kind: "incompatible",
|
|
359
|
-
expected: input.expected,
|
|
360
|
-
candidate: input.candidate,
|
|
361
|
-
fallback: buildBreakerFallback("CP_BOUNDARY_OUTCOME_MISMATCH", {
|
|
362
|
-
candidateKind: input.candidate.kind,
|
|
363
|
-
expectedKind: input.expected.kind
|
|
364
|
-
})
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
33
|
function requestApiStatusRank(status) {
|
|
368
34
|
switch (status) {
|
|
369
35
|
case "notObserved": return 0;
|
|
@@ -447,47 +113,6 @@ function classifyObservedRequestApiDowngrade(kind) {
|
|
|
447
113
|
default: return assertNever(kind);
|
|
448
114
|
}
|
|
449
115
|
}
|
|
450
|
-
function classifyCacheVariantDimensionDowngrade(input) {
|
|
451
|
-
switch (input.source) {
|
|
452
|
-
case "auth": return {
|
|
453
|
-
code: "CP_DOWNGRADE_PRIVATE_DIMENSION",
|
|
454
|
-
inputClass: "auth",
|
|
455
|
-
source: "auth",
|
|
456
|
-
target: "private"
|
|
457
|
-
};
|
|
458
|
-
case "cookie": return {
|
|
459
|
-
code: "CP_DOWNGRADE_PRIVATE_DIMENSION",
|
|
460
|
-
inputClass: "private",
|
|
461
|
-
source: "cookie",
|
|
462
|
-
target: "private"
|
|
463
|
-
};
|
|
464
|
-
case "draft-mode": return {
|
|
465
|
-
code: "CP_DOWNGRADE_PRIVATE_DIMENSION",
|
|
466
|
-
inputClass: "draft",
|
|
467
|
-
source: "draft-mode",
|
|
468
|
-
target: "privateUncacheable"
|
|
469
|
-
};
|
|
470
|
-
case "header": return {
|
|
471
|
-
code: "CP_DOWNGRADE_PRIVATE_DIMENSION",
|
|
472
|
-
inputClass: "private",
|
|
473
|
-
source: "header",
|
|
474
|
-
target: "private"
|
|
475
|
-
};
|
|
476
|
-
case "session": return {
|
|
477
|
-
code: "CP_DOWNGRADE_PRIVATE_DIMENSION",
|
|
478
|
-
inputClass: "session",
|
|
479
|
-
source: "session",
|
|
480
|
-
target: "private"
|
|
481
|
-
};
|
|
482
|
-
case "custom":
|
|
483
|
-
case "interception":
|
|
484
|
-
case "mounted-slots":
|
|
485
|
-
case "params":
|
|
486
|
-
case "route":
|
|
487
|
-
case "search": return null;
|
|
488
|
-
default: return assertNever(input.source);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
116
|
function classifyRenderObservationDowngrade(input) {
|
|
492
117
|
const reasons = [];
|
|
493
118
|
let target = "public";
|
|
@@ -602,164 +227,6 @@ function hasCompleteNegativeRequestApiProof(observation, requiredApis) {
|
|
|
602
227
|
function hasQueryInvariantRenderProof(observation) {
|
|
603
228
|
return observation !== void 0 && hasCompleteNegativeRequestApiProof(observation, ["searchParams"]);
|
|
604
229
|
}
|
|
605
|
-
function isStaticLayoutOutputScope(output) {
|
|
606
|
-
return output.kind === "layout";
|
|
607
|
-
}
|
|
608
|
-
function rejectStaticLayoutReuseProof(code, fields, mode = "renderFresh") {
|
|
609
|
-
return {
|
|
610
|
-
kind: "rejected",
|
|
611
|
-
fallback: buildBreakerFallback(code, fields, mode)
|
|
612
|
-
};
|
|
613
|
-
}
|
|
614
|
-
function getRequestApiStatus(observations, kind) {
|
|
615
|
-
let status = null;
|
|
616
|
-
for (const requestApi of observations) {
|
|
617
|
-
if (requestApi.kind !== kind) continue;
|
|
618
|
-
if (status === null || requestApiStatusRank(requestApi.status) > requestApiStatusRank(status)) status = requestApi.status;
|
|
619
|
-
}
|
|
620
|
-
return status ?? "missing";
|
|
621
|
-
}
|
|
622
|
-
function createStaticLayoutDowngradeFallback(downgrade) {
|
|
623
|
-
const mode = downgrade.target === "privateUncacheable" ? "privateUncacheable" : "renderFresh";
|
|
624
|
-
return buildBreakerFallback("CP_STATIC_LAYOUT_PRIVATE_DYNAMIC_DOWNGRADE", {
|
|
625
|
-
reasonCodes: downgrade.reasons.map((reason) => reason.code),
|
|
626
|
-
target: downgrade.target
|
|
627
|
-
}, mode);
|
|
628
|
-
}
|
|
629
|
-
function outputFieldMismatch(candidate, observation) {
|
|
630
|
-
if (candidate.layoutId !== observation.layoutId) return "layoutId";
|
|
631
|
-
if (candidate.rootBoundaryId !== observation.rootBoundaryId) return "rootBoundaryId";
|
|
632
|
-
if (candidate.routeId !== observation.routeId) return "routeId";
|
|
633
|
-
return null;
|
|
634
|
-
}
|
|
635
|
-
function buildStaticLayoutReuseProof(input) {
|
|
636
|
-
if (!isStaticLayoutOutputScope(input.currentOutput)) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_CURRENT_OUTPUT_KIND", { currentOutputKind: input.currentOutput.kind });
|
|
637
|
-
if (!isStaticLayoutOutputScope(input.candidateVariant.output)) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_CANDIDATE_OUTPUT_KIND", { candidateOutputKind: input.candidateVariant.output.kind });
|
|
638
|
-
if (!isStaticLayoutOutputScope(input.candidateObservation.output)) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_KIND", { observationOutputKind: input.candidateObservation.output.kind });
|
|
639
|
-
const currentOutput = input.currentOutput;
|
|
640
|
-
const candidateOutput = input.candidateVariant.output;
|
|
641
|
-
const observationOutput = input.candidateObservation.output;
|
|
642
|
-
const requestApis = normalizeRequestApiObservations(input.candidateObservation.requestApis);
|
|
643
|
-
const candidateObservation = {
|
|
644
|
-
...input.candidateObservation,
|
|
645
|
-
requestApis,
|
|
646
|
-
downgrade: classifyRenderObservationDowngrade({
|
|
647
|
-
cacheability: input.candidateObservation.cacheability,
|
|
648
|
-
completeness: input.candidateObservation.completeness,
|
|
649
|
-
dynamicFetches: input.candidateObservation.dynamicFetches,
|
|
650
|
-
requestApis
|
|
651
|
-
})
|
|
652
|
-
};
|
|
653
|
-
const observedOutputMismatch = outputFieldMismatch(candidateOutput, observationOutput);
|
|
654
|
-
if (observedOutputMismatch) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_MISMATCH", {
|
|
655
|
-
candidateLayoutId: candidateOutput.layoutId,
|
|
656
|
-
candidateRootBoundaryId: candidateOutput.rootBoundaryId,
|
|
657
|
-
candidateRouteId: candidateOutput.routeId,
|
|
658
|
-
field: observedOutputMismatch,
|
|
659
|
-
observationLayoutId: observationOutput.layoutId,
|
|
660
|
-
observationRootBoundaryId: observationOutput.rootBoundaryId,
|
|
661
|
-
observationRouteId: observationOutput.routeId
|
|
662
|
-
});
|
|
663
|
-
if (currentOutput.layoutId !== candidateOutput.layoutId) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_ID_MISMATCH", {
|
|
664
|
-
candidateLayoutId: candidateOutput.layoutId,
|
|
665
|
-
currentLayoutId: currentOutput.layoutId
|
|
666
|
-
});
|
|
667
|
-
if (currentOutput.rootBoundaryId === null || candidateOutput.rootBoundaryId === null) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_ROOT_BOUNDARY_UNKNOWN", {
|
|
668
|
-
candidateRootBoundaryId: candidateOutput.rootBoundaryId,
|
|
669
|
-
currentRootBoundaryId: currentOutput.rootBoundaryId
|
|
670
|
-
});
|
|
671
|
-
if (currentOutput.rootBoundaryId !== candidateOutput.rootBoundaryId) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_ROOT_BOUNDARY_MISMATCH", {
|
|
672
|
-
candidateRootBoundaryId: candidateOutput.rootBoundaryId,
|
|
673
|
-
currentRootBoundaryId: currentOutput.rootBoundaryId
|
|
674
|
-
});
|
|
675
|
-
const boundaryCompatibility = buildBoundaryOutcomeCompatibility({
|
|
676
|
-
candidate: candidateObservation.boundaryOutcome,
|
|
677
|
-
expected: { kind: "success" }
|
|
678
|
-
});
|
|
679
|
-
if (boundaryCompatibility.kind === "incompatible") return {
|
|
680
|
-
kind: "rejected",
|
|
681
|
-
fallback: boundaryCompatibility.fallback
|
|
682
|
-
};
|
|
683
|
-
if (input.candidateVariant.dimensions.length > 0) return rejectStaticLayoutReuseProof("CP_STATIC_LAYOUT_VARIANT_DIMENSION_UNPROVEN", {
|
|
684
|
-
dimensionCount: input.candidateVariant.dimensions.length,
|
|
685
|
-
sources: sortedUnique(input.candidateVariant.dimensions.map((dimension) => dimension.source))
|
|
686
|
-
});
|
|
687
|
-
if (!candidateObservation.downgrade.isPublicCacheCandidate) return {
|
|
688
|
-
kind: "rejected",
|
|
689
|
-
fallback: createStaticLayoutDowngradeFallback(candidateObservation.downgrade)
|
|
690
|
-
};
|
|
691
|
-
const requiredNegativeRequestApis = ALL_RENDER_REQUEST_API_KINDS;
|
|
692
|
-
for (const api of requiredNegativeRequestApis) {
|
|
693
|
-
const status = getRequestApiStatus(candidateObservation.requestApis, api);
|
|
694
|
-
if (status === "notObserved") continue;
|
|
695
|
-
return rejectStaticLayoutReuseProof(status === "missing" ? "CP_STATIC_LAYOUT_REQUEST_API_UNKNOWN" : "CP_STATIC_LAYOUT_REQUEST_API_OBSERVED", {
|
|
696
|
-
requestApi: api,
|
|
697
|
-
status
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
return {
|
|
701
|
-
kind: "proof",
|
|
702
|
-
proof: {
|
|
703
|
-
authorizesRuntimeReuse: true,
|
|
704
|
-
candidateOutput,
|
|
705
|
-
code: "CP_STATIC_LAYOUT_REUSE_PROVEN",
|
|
706
|
-
currentOutput,
|
|
707
|
-
fields: {
|
|
708
|
-
candidateRouteId: candidateOutput.routeId,
|
|
709
|
-
currentRouteId: currentOutput.routeId,
|
|
710
|
-
layoutId: currentOutput.layoutId,
|
|
711
|
-
rootBoundaryId: currentOutput.rootBoundaryId
|
|
712
|
-
},
|
|
713
|
-
observation: candidateObservation,
|
|
714
|
-
requiredNegativeRequestApis: [...requiredNegativeRequestApis],
|
|
715
|
-
reuseClass: "static-layout",
|
|
716
|
-
variant: input.candidateVariant
|
|
717
|
-
}
|
|
718
|
-
};
|
|
719
|
-
}
|
|
720
|
-
function createCacheProofHotPathMetric(outcome, code, fields) {
|
|
721
|
-
return {
|
|
722
|
-
name: "vinext.cache.static_layout_artifact_reuse",
|
|
723
|
-
outcome,
|
|
724
|
-
code,
|
|
725
|
-
fields
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
function createStaticLayoutArtifactReuseFallback(fallback) {
|
|
729
|
-
return {
|
|
730
|
-
kind: "fallback",
|
|
731
|
-
canReuse: false,
|
|
732
|
-
fallback,
|
|
733
|
-
metric: createCacheProofHotPathMetric("fallback", fallback.code, fallback.fields)
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
function createStaticLayoutArtifactReuseDecision(input) {
|
|
737
|
-
if (input.candidateVariant.kind === "breakerFallback") return createStaticLayoutArtifactReuseFallback(input.candidateVariant.fallback);
|
|
738
|
-
const artifactCompatibility = evaluateArtifactCompatibility(input.currentArtifactCompatibility, input.candidateArtifactCompatibility, { compatibilityMap: input.compatibilityMap });
|
|
739
|
-
if (artifactCompatibility.kind === "unknown") return createStaticLayoutArtifactReuseFallback(buildBreakerFallback("CP_ARTIFACT_COMPATIBILITY_UNKNOWN", {
|
|
740
|
-
compatibilityFallback: artifactCompatibility.fallback,
|
|
741
|
-
reason: artifactCompatibility.reason
|
|
742
|
-
}));
|
|
743
|
-
if (artifactCompatibility.kind === "incompatible") return createStaticLayoutArtifactReuseFallback(buildBreakerFallback("CP_ARTIFACT_COMPATIBILITY_INCOMPATIBLE", {
|
|
744
|
-
compatibilityFallback: artifactCompatibility.fallback,
|
|
745
|
-
reason: artifactCompatibility.reason
|
|
746
|
-
}));
|
|
747
|
-
const proof = buildStaticLayoutReuseProof({
|
|
748
|
-
candidateObservation: input.candidateObservation,
|
|
749
|
-
candidateVariant: input.candidateVariant.variant,
|
|
750
|
-
currentOutput: input.currentOutput
|
|
751
|
-
});
|
|
752
|
-
if (proof.kind === "rejected") return createStaticLayoutArtifactReuseFallback(proof.fallback);
|
|
753
|
-
return {
|
|
754
|
-
kind: "reuse",
|
|
755
|
-
canReuse: true,
|
|
756
|
-
proof: {
|
|
757
|
-
...proof.proof,
|
|
758
|
-
candidateArtifactCompatibility: { ...input.candidateArtifactCompatibility }
|
|
759
|
-
},
|
|
760
|
-
metric: createCacheProofHotPathMetric("reuse", proof.proof.code, proof.proof.fields)
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
230
|
function createCacheEntryReuseProof(decision) {
|
|
764
231
|
if (decision === null) return {
|
|
765
232
|
kind: "runtime-cache-entry",
|
|
@@ -788,15 +255,5 @@ function createCacheEntryReuseProof(decision) {
|
|
|
788
255
|
default: return assertNever(decision);
|
|
789
256
|
}
|
|
790
257
|
}
|
|
791
|
-
function createDisabledCacheProofDecision(input) {
|
|
792
|
-
return {
|
|
793
|
-
kind: "disabled",
|
|
794
|
-
canReuse: false,
|
|
795
|
-
variant: input.variant,
|
|
796
|
-
observation: input.observation,
|
|
797
|
-
...input.staticLayoutProof ? { staticLayoutProof: input.staticLayoutProof } : {},
|
|
798
|
-
fallback: buildBreakerFallback("CP_MODEL_DISABLED")
|
|
799
|
-
};
|
|
800
|
-
}
|
|
801
258
|
//#endregion
|
|
802
|
-
export { ALL_RENDER_REQUEST_API_KINDS, CACHE_PROOF_MODEL_SCHEMA_VERSION,
|
|
259
|
+
export { ALL_RENDER_REQUEST_API_KINDS, CACHE_PROOF_MODEL_SCHEMA_VERSION, buildRenderObservation, buildRenderRequestApiObservations, classifyRenderObservationDowngrade, createCacheEntryReuseProof, hasCompleteNegativeRequestApiProof, hasQueryInvariantRenderProof };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../utils/protocol-headers.js";
|
|
2
2
|
import { isVinextRscVaryField } from "./app-rsc-vary.js";
|
|
3
|
-
import { VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER, VINEXT_SPECIAL_ERROR_STATUS_HEADER } from "./headers.js";
|
|
3
|
+
import { NEXT_ROUTER_STALE_TIME_HEADER, VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER, VINEXT_SPECIAL_ERROR_STATUS_HEADER, VINEXT_STALE_TIME_PENDING_HEADER } from "./headers.js";
|
|
4
4
|
import { hasSharedCacheCredentials, isNonCacheableCacheControl } from "../shims/cdn-cache.js";
|
|
5
5
|
import { CACHEABILITY_REQUEST_STATE, recordConfigCdnCachePolicyHeader } from "../shims/cacheability-classification.js";
|
|
6
6
|
import { NO_STORE_CACHE_CONTROL, applyCdnResponseBuildIdentityHeaders, applyCdnResponseHeaders, hasExplicitNonCacheableResponsePolicy, isCdnResponsePolicyHeader, readCdnResponseCacheControl, readCdnResponsePolicyHeaderName } from "./cache-control.js";
|
|
@@ -348,20 +348,25 @@ async function captureCacheabilityAdmissionBody(body, deadlineAt, limit = CACHEA
|
|
|
348
348
|
throw error;
|
|
349
349
|
}
|
|
350
350
|
}
|
|
351
|
-
function responseWithCachePolicy(response, body, outcome, browserCacheControl,
|
|
351
|
+
function responseWithCachePolicy(response, body, outcome, browserCacheControl, completedRender) {
|
|
352
352
|
const headers = new Headers(response.headers);
|
|
353
353
|
if (typeof body === "string") headers.delete("Content-Length");
|
|
354
|
-
for (const [name, value] of Object.entries(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
354
|
+
for (const [name, value] of Object.entries(completedRender?.headers ?? {})) if (!headers.has(name)) headers.set(name, value);
|
|
355
|
+
const cacheControl = outcome?.cacheable === true ? outcome.cacheControl : void 0;
|
|
356
|
+
applyCdnResponseHeaders(headers, cacheControl ? {
|
|
357
|
+
cacheControl,
|
|
358
|
+
tags: outcome?.tags,
|
|
358
359
|
browserCacheControl
|
|
359
360
|
} : {
|
|
360
361
|
cacheControl: NO_STORE_CACHE_CONTROL,
|
|
361
362
|
browserCacheControl
|
|
362
363
|
});
|
|
363
|
-
|
|
364
|
-
|
|
364
|
+
if (cacheControl && completedRender) {
|
|
365
|
+
headers.delete(VINEXT_STALE_TIME_PENDING_HEADER);
|
|
366
|
+
if (completedRender.staleTimeSeconds !== void 0 && !headers.has("x-nextjs-stale-time")) headers.set(NEXT_ROUTER_STALE_TIME_HEADER, String(Math.floor(completedRender.staleTimeSeconds)));
|
|
367
|
+
}
|
|
368
|
+
const status = completedRender?.status ?? response.status;
|
|
369
|
+
const completed = completedRender?.status;
|
|
365
370
|
if (completed === 401 || completed === 403 || completed === 404) headers.set(VINEXT_SPECIAL_ERROR_STATUS_HEADER, String(completed));
|
|
366
371
|
return new Response(body, {
|
|
367
372
|
headers,
|
|
@@ -13,7 +13,7 @@ import { NEVER_CACHE_CONTROL } from "./cache-control.js";
|
|
|
13
13
|
import { buildMissIsrCacheControl } from "./isr-decision.js";
|
|
14
14
|
import { isOnDemandRevalidateRequest } from "./revalidation-request.js";
|
|
15
15
|
import "./isr-cache.js";
|
|
16
|
-
import { ensureFetchPatch } from "../shims/fetch-cache.js";
|
|
16
|
+
import { ensureFetchPatch, setCurrentFetchDraftMode } from "../shims/fetch-cache.js";
|
|
17
17
|
import { mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
|
|
18
18
|
import "../shims/router-state.js";
|
|
19
19
|
import { withScriptNonce } from "../shims/script-nonce-context.js";
|
|
@@ -405,7 +405,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
405
405
|
res.end("{}");
|
|
406
406
|
return;
|
|
407
407
|
}
|
|
408
|
-
const requestContext = createRequestContext();
|
|
408
|
+
const requestContext = createRequestContext({ isOnDemandRevalidate: isOnDemandRevalidateRequest(req.headers[PRERENDER_REVALIDATE_HEADER]) });
|
|
409
409
|
const closeRequest = () => void closeAfterResponse(requestContext);
|
|
410
410
|
res.on("finish", closeRequest);
|
|
411
411
|
res.on("close", closeRequest);
|
|
@@ -423,7 +423,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
423
423
|
let requestAsPath = isDataReq ? gsspResolvedUrl : i18nConfig ? extractLocaleFromUrl$1(originalUrl, i18nConfig, locale).url : originalUrl;
|
|
424
424
|
const userFacingParams = route.isDynamic ? params : null;
|
|
425
425
|
let query = mergeRouteParamsIntoQuery(parseQueryString(url), params);
|
|
426
|
-
const requestContext = createRequestContext();
|
|
426
|
+
const requestContext = createRequestContext({ isOnDemandRevalidate: isOnDemandRevalidateRequest(req.headers[PRERENDER_REVALIDATE_HEADER]) });
|
|
427
427
|
let isStaticPropsRender = false;
|
|
428
428
|
const closeRequest = () => void closeAfterResponse(requestContext);
|
|
429
429
|
res.on("finish", closeRequest);
|
|
@@ -468,6 +468,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
468
468
|
shouldClear: false
|
|
469
469
|
};
|
|
470
470
|
const requestPreviewData = requestPreview.data;
|
|
471
|
+
setCurrentFetchDraftMode(requestPreviewData !== false);
|
|
471
472
|
const pagesNextData = {
|
|
472
473
|
...buildPagesReadinessNextData({
|
|
473
474
|
pageModule,
|
package/dist/server/headers.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export declare const VINEXT_CACHE_HEADER = "X-Vinext-Cache";
|
|
|
17
17
|
export declare const NEXTJS_CACHE_HEADER = "x-nextjs-cache";
|
|
18
18
|
/** Next.js cache-tag metadata carried by prerendered App Router responses. */
|
|
19
19
|
export declare const NEXT_CACHE_TAGS_HEADER = "x-next-cache-tags";
|
|
20
|
-
/** Timing metrics: `handlerStart,compileMs,renderMs
|
|
20
|
+
/** Timing metrics: `handlerStart,compileMs,renderMs` (handlerStart is wall-clock ms). */
|
|
21
21
|
export declare const VINEXT_TIMING_HEADER = "x-vinext-timing";
|
|
22
22
|
/** Matched route returned from an independently hosted response stage. */
|
|
23
23
|
export declare const VINEXT_TRACE_ROUTE_HEADER = "X-Vinext-Trace-Route";
|
|
@@ -85,8 +85,11 @@ export declare const VINEXT_PRERENDER_RENDER_ERROR_HEADER = "x-vinext-prerender-
|
|
|
85
85
|
export declare const VINEXT_PRERENDER_SPECIAL_ERROR_HEADER = "x-vinext-prerender-special-error";
|
|
86
86
|
/** Internal marker persisted only inside metadata-route APP_ROUTE cache values. */
|
|
87
87
|
export declare const VINEXT_METADATA_ROUTE_CACHE_HEADER = "x-vinext-metadata-route-cache";
|
|
88
|
-
/**
|
|
89
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Hashed identities of the layouts a client navigation already holds, so a
|
|
90
|
+
* render that's never stored can leave them out. Not part of the RSC cache key.
|
|
91
|
+
*/
|
|
92
|
+
export declare const VINEXT_MOUNTED_LAYOUTS_HEADER = "X-Vinext-Mounted-Layouts";
|
|
90
93
|
/**
|
|
91
94
|
* Side-channel signal that an RSC response (HTTP 200) encodes a `redirect()`
|
|
92
95
|
* thrown during render. The header value is the redirect target (path-only
|