vinext 0.1.4 → 0.1.6
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 +2 -2
- package/dist/build/css-url-assets.d.ts +1 -1
- package/dist/build/css-url-assets.js +9 -7
- package/dist/build/google-fonts/find-font-files-in-css.d.ts +16 -0
- package/dist/build/google-fonts/find-font-files-in-css.js +28 -0
- package/dist/build/prerender.js +2 -1
- package/dist/build/report.d.ts +1 -2
- package/dist/build/report.js +2 -11
- package/dist/build/run-prerender.js +1 -1
- package/dist/cache/cache-adapters-virtual.js +1 -1
- package/dist/check.js +3 -3
- package/dist/client/pages-router-link-navigation.d.ts +10 -0
- package/dist/client/pages-router-link-navigation.js +3 -3
- package/dist/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +1 -1
- package/dist/deploy.js +3 -3
- package/dist/entries/app-rsc-entry.js +25 -20
- package/dist/entries/app-rsc-manifest.js +76 -46
- package/dist/entries/pages-server-entry.js +3 -1
- package/dist/index.js +254 -198
- package/dist/init.d.ts +5 -4
- package/dist/init.js +27 -8
- package/dist/plugins/css-data-url.js +30 -26
- package/dist/plugins/extensionless-dynamic-import.js +27 -24
- package/dist/plugins/fonts.js +3 -1
- package/dist/plugins/import-meta-url.js +21 -15
- package/dist/plugins/instrumentation-client.js +1 -1
- package/dist/plugins/middleware-export-validation.d.ts +5 -0
- package/dist/plugins/middleware-export-validation.js +36 -0
- package/dist/plugins/middleware-server-only.js +7 -6
- package/dist/plugins/og-asset-ownership.d.ts +27 -0
- package/dist/plugins/og-asset-ownership.js +285 -0
- package/dist/plugins/og-assets.js +66 -46
- package/dist/plugins/optimize-imports.js +9 -3
- package/dist/plugins/remove-console.d.ts +7 -1
- package/dist/plugins/remove-console.js +4 -1
- package/dist/plugins/require-context.js +21 -20
- package/dist/plugins/strip-server-exports.d.ts +7 -1
- package/dist/plugins/strip-server-exports.js +4 -1
- package/dist/server/accept-encoding.d.ts +29 -0
- package/dist/server/accept-encoding.js +95 -0
- package/dist/server/app-bfcache-identity.d.ts +26 -0
- package/dist/server/app-bfcache-identity.js +127 -0
- package/dist/server/app-browser-entry.js +17 -11
- package/dist/server/app-browser-rsc-redirect.d.ts +2 -1
- package/dist/server/app-browser-rsc-redirect.js +8 -1
- package/dist/server/app-browser-state.d.ts +2 -21
- package/dist/server/app-browser-state.js +4 -128
- package/dist/server/app-browser-stream.js +1 -1
- package/dist/server/app-browser-visible-commit.js +3 -2
- package/dist/server/app-fallback-renderer.d.ts +1 -1
- package/dist/server/app-layout-param-observation.d.ts +1 -1
- package/dist/server/app-layout-param-observation.js +1 -1
- package/dist/server/app-middleware.d.ts +1 -0
- package/dist/server/app-middleware.js +3 -1
- package/dist/server/app-page-boundary-render.d.ts +1 -1
- package/dist/server/app-page-boundary.js +1 -1
- package/dist/server/app-page-cache-finalizer.d.ts +62 -0
- package/dist/server/app-page-cache-finalizer.js +122 -0
- package/dist/server/app-page-cache-render.d.ts +2 -2
- package/dist/server/app-page-cache-render.js +1 -1
- package/dist/server/app-page-cache.d.ts +2 -53
- package/dist/server/app-page-cache.js +5 -131
- package/dist/server/app-page-dispatch.d.ts +4 -4
- package/dist/server/app-page-dispatch.js +10 -8
- package/dist/server/app-page-head.js +2 -2
- package/dist/server/app-page-probe.js +3 -2
- package/dist/server/app-page-render-observation.js +2 -2
- package/dist/server/app-page-render.d.ts +3 -3
- package/dist/server/app-page-render.js +3 -2
- package/dist/server/app-page-request.d.ts +7 -0
- package/dist/server/app-page-request.js +19 -1
- package/dist/server/app-page-stream.d.ts +2 -9
- package/dist/server/app-page-stream.js +1 -35
- package/dist/server/app-prerender-endpoints.d.ts +3 -3
- package/dist/server/app-prerender-endpoints.js +3 -4
- package/dist/server/app-request-context.d.ts +1 -2
- package/dist/server/app-request-context.js +2 -1
- package/dist/server/app-route-handler-dispatch.js +3 -2
- package/dist/server/app-route-handler-execution.d.ts +1 -1
- package/dist/server/app-route-handler-execution.js +1 -1
- package/dist/server/app-route-handler-response.d.ts +1 -1
- package/dist/server/app-route-module-loader.d.ts +62 -14
- package/dist/server/app-route-module-loader.js +61 -10
- package/dist/server/app-router-entry.js +2 -1
- package/dist/server/app-rsc-handler.d.ts +7 -6
- package/dist/server/app-rsc-handler.js +51 -40
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-rsc-route-matching.d.ts +9 -0
- package/dist/server/app-rsc-route-matching.js +13 -0
- package/dist/server/app-server-action-execution.d.ts +1 -1
- package/dist/server/app-server-action-execution.js +5 -4
- package/dist/server/app-ssr-entry.d.ts +1 -1
- package/dist/server/app-ssr-entry.js +9 -7
- package/dist/server/app-ssr-router-instance.d.ts +6 -0
- package/dist/server/app-ssr-router-instance.js +24 -0
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/artifact-compatibility.js +1 -1
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/defer-until-stream-consumed.d.ts +7 -0
- package/dist/server/defer-until-stream-consumed.js +34 -0
- package/dist/server/dev-server.js +1 -1
- package/dist/server/headers.d.ts +5 -1
- package/dist/server/headers.js +5 -1
- package/dist/server/instrumentation.js +1 -1
- package/dist/server/isr-cache.d.ts +1 -1
- package/dist/server/isr-cache.js +1 -1
- package/dist/server/isr-decision.d.ts +1 -1
- package/dist/server/metadata-route-response.d.ts +3 -3
- package/dist/server/middleware-matcher.js +8 -6
- package/dist/server/middleware-runtime.d.ts +2 -1
- package/dist/server/middleware-runtime.js +21 -10
- package/dist/server/middleware.d.ts +2 -2
- package/dist/server/middleware.js +26 -11
- package/dist/server/open-redirect.d.ts +12 -0
- package/dist/server/open-redirect.js +21 -0
- package/dist/server/pages-page-data.d.ts +1 -1
- package/dist/server/pages-page-response.d.ts +1 -1
- package/dist/server/pages-page-response.js +2 -2
- package/dist/server/pages-request-pipeline.d.ts +3 -1
- package/dist/server/pages-request-pipeline.js +4 -2
- package/dist/server/prod-server.d.ts +1 -1
- package/dist/server/prod-server.js +87 -73
- package/dist/server/request-pipeline.d.ts +1 -24
- package/dist/server/request-pipeline.js +1 -33
- package/dist/server/seed-cache.d.ts +1 -1
- package/dist/shims/cache-handler.d.ts +106 -0
- package/dist/shims/cache-handler.js +176 -0
- package/dist/shims/cache-request-state.d.ts +47 -0
- package/dist/shims/cache-request-state.js +126 -0
- package/dist/shims/cache-runtime.d.ts +2 -2
- package/dist/shims/cache-runtime.js +3 -14
- package/dist/shims/cache.d.ts +3 -231
- package/dist/shims/cache.js +17 -383
- package/dist/shims/cdn-cache.d.ts +1 -1
- package/dist/shims/cdn-cache.js +1 -1
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +44 -0
- package/dist/shims/error-boundary.js +10 -8
- package/dist/shims/error.js +2 -1
- package/dist/shims/fetch-cache.js +1 -1
- package/dist/shims/font-google-base.d.ts +1 -0
- package/dist/shims/font-google-base.js +6 -21
- package/dist/shims/form.js +1 -1
- package/dist/shims/image.js +67 -9
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -0
- package/dist/shims/internal/app-page-props-cache-key.js +16 -0
- package/dist/shims/internal/interpolate-as.d.ts +25 -0
- package/dist/shims/internal/interpolate-as.js +196 -0
- package/dist/shims/internal/navigation-untracked.js +2 -1
- package/dist/shims/layout-segment-context.d.ts +1 -1
- package/dist/shims/layout-segment-context.js +2 -1
- package/dist/shims/link.js +26 -3
- package/dist/shims/navigation-context-state.d.ts +40 -0
- package/dist/shims/navigation-context-state.js +116 -0
- package/dist/shims/navigation-errors.d.ts +55 -0
- package/dist/shims/navigation-errors.js +110 -0
- package/dist/shims/navigation-server.d.ts +3 -0
- package/dist/shims/navigation-server.js +3 -0
- package/dist/shims/navigation-state.d.ts +1 -2
- package/dist/shims/navigation-state.js +2 -1
- package/dist/shims/navigation.d.ts +3 -291
- package/dist/shims/navigation.js +13 -444
- package/dist/shims/navigation.react-server.d.ts +2 -2
- package/dist/shims/navigation.react-server.js +4 -2
- package/dist/shims/request-state-types.d.ts +3 -3
- package/dist/shims/router.d.ts +1 -3
- package/dist/shims/router.js +62 -18
- package/dist/shims/script.js +1 -1
- package/dist/shims/slot.js +3 -1
- package/dist/shims/unified-request-context.d.ts +2 -2
- package/dist/typegen.js +2 -10
- package/dist/utils/project.d.ts +7 -1
- package/dist/utils/project.js +16 -2
- package/dist/utils/virtual-module.d.ts +5 -0
- package/dist/utils/virtual-module.js +0 -0
- package/package.json +7 -3
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import zlib from "node:zlib";
|
|
2
|
+
//#region src/server/accept-encoding.ts
|
|
3
|
+
/** Parse an Accept-Encoding header into exact-token numeric qualities. */
|
|
4
|
+
function parseAcceptedEncodings(accept) {
|
|
5
|
+
const qualities = /* @__PURE__ */ new Map();
|
|
6
|
+
const orders = /* @__PURE__ */ new Map();
|
|
7
|
+
let wildcardQuality = null;
|
|
8
|
+
for (const [order, part] of accept.split(",").entries()) {
|
|
9
|
+
const trimmed = part.trim();
|
|
10
|
+
if (trimmed.length === 0) continue;
|
|
11
|
+
const semi = trimmed.indexOf(";");
|
|
12
|
+
const token = (semi === -1 ? trimmed : trimmed.slice(0, semi)).trim().toLowerCase();
|
|
13
|
+
if (token.length === 0) continue;
|
|
14
|
+
let quality = 1;
|
|
15
|
+
if (semi !== -1) {
|
|
16
|
+
let qStr;
|
|
17
|
+
for (const param of trimmed.slice(semi + 1).split(";")) {
|
|
18
|
+
const [name, value] = param.trim().split("=");
|
|
19
|
+
if (name !== "q") continue;
|
|
20
|
+
qStr = value ?? "";
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
if (qStr !== void 0) quality = Number.parseFloat(qStr);
|
|
24
|
+
}
|
|
25
|
+
if (token === "*") {
|
|
26
|
+
if (wildcardQuality === null || Number.isNaN(quality) || Number.isNaN(wildcardQuality) || quality >= wildcardQuality) wildcardQuality = quality;
|
|
27
|
+
} else {
|
|
28
|
+
const currentQuality = qualities.get(token);
|
|
29
|
+
if (currentQuality === void 0 || Number.isNaN(quality) || Number.isNaN(currentQuality) || quality >= currentQuality) {
|
|
30
|
+
qualities.set(token, quality);
|
|
31
|
+
orders.set(token, order);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
qualities,
|
|
37
|
+
orders,
|
|
38
|
+
wildcardQuality
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** Return the effective quality for a coding, including wildcard/identity rules. */
|
|
42
|
+
function getEncodingQuality(parsed, encoding) {
|
|
43
|
+
const normalized = encoding.toLowerCase();
|
|
44
|
+
const explicit = parsed.qualities.get(normalized);
|
|
45
|
+
if (explicit !== void 0) return Number.isNaN(explicit) ? 0 : explicit;
|
|
46
|
+
if (normalized === "identity") return parsed.wildcardQuality === 0 ? 0 : 1;
|
|
47
|
+
if (parsed.wildcardQuality !== null) return Number.isNaN(parsed.wildcardQuality) ? 0 : parsed.wildcardQuality;
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
function isEncodingAccepted(parsed, encoding) {
|
|
51
|
+
return getEncodingQuality(parsed, encoding) > 0;
|
|
52
|
+
}
|
|
53
|
+
/** Choose the highest-quality available coding, using array order as the tie-breaker. */
|
|
54
|
+
function selectAcceptedEncoding(parsed, available) {
|
|
55
|
+
let selected = null;
|
|
56
|
+
let selectedQuality = 0;
|
|
57
|
+
for (const encoding of available) {
|
|
58
|
+
const quality = getEncodingQuality(parsed, encoding);
|
|
59
|
+
if (quality > selectedQuality) {
|
|
60
|
+
selected = encoding;
|
|
61
|
+
selectedQuality = quality;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return selected;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Select a content coding while matching Next.js's compression middleware:
|
|
68
|
+
* an explicit identity preference can win, but implicit identity remains a
|
|
69
|
+
* fallback rather than suppressing an otherwise acceptable encoding.
|
|
70
|
+
*/
|
|
71
|
+
function selectContentEncoding(parsed, available) {
|
|
72
|
+
const selected = selectAcceptedEncoding(parsed, available);
|
|
73
|
+
if (selected === null) return "identity";
|
|
74
|
+
const identityQuality = parsed.qualities.get("identity");
|
|
75
|
+
if (identityQuality === void 0 || Number.isNaN(identityQuality)) return selected;
|
|
76
|
+
const selectedQuality = getEncodingQuality(parsed, selected);
|
|
77
|
+
if (identityQuality > selectedQuality) return "identity";
|
|
78
|
+
if (identityQuality < selectedQuality) return selected;
|
|
79
|
+
if (!parsed.qualities.has(selected)) return "identity";
|
|
80
|
+
return (parsed.orders.get("identity") ?? Number.POSITIVE_INFINITY) < (parsed.orders.get(selected) ?? Number.POSITIVE_INFINITY) ? "identity" : selected;
|
|
81
|
+
}
|
|
82
|
+
const HAS_ZSTD = typeof zlib.createZstdCompress === "function";
|
|
83
|
+
/** Select by client q-value first, then zstd > br > gzip > deflate > identity. */
|
|
84
|
+
function negotiateEncoding(req) {
|
|
85
|
+
const accept = req.headers["accept-encoding"];
|
|
86
|
+
if (typeof accept !== "string") return "identity";
|
|
87
|
+
return selectContentEncoding(parseAcceptedEncodings(accept), [
|
|
88
|
+
...HAS_ZSTD ? ["zstd"] : [],
|
|
89
|
+
"br",
|
|
90
|
+
"gzip",
|
|
91
|
+
"deflate"
|
|
92
|
+
]);
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { HAS_ZSTD, getEncodingQuality, isEncodingAccepted, negotiateEncoding, parseAcceptedEncodings, selectAcceptedEncoding, selectContentEncoding };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AppElements } from "./app-elements-wire.js";
|
|
2
|
+
import { BfcacheIdMap } from "./app-history-state.js";
|
|
3
|
+
|
|
4
|
+
//#region src/server/app-bfcache-identity.d.ts
|
|
5
|
+
type BfcacheStateKeyMap = Readonly<Record<string, string>>;
|
|
6
|
+
declare function createInitialBfcacheIdMap(elements: AppElements): BfcacheIdMap;
|
|
7
|
+
declare function createBfcacheSegmentStateKeyMap(options: {
|
|
8
|
+
elements: AppElements;
|
|
9
|
+
pathname: string;
|
|
10
|
+
}): BfcacheStateKeyMap;
|
|
11
|
+
declare function createNextBfcacheIdMap(options: {
|
|
12
|
+
current: BfcacheIdMap;
|
|
13
|
+
currentElements: AppElements;
|
|
14
|
+
currentPathname: string;
|
|
15
|
+
elements: AppElements;
|
|
16
|
+
nextPathname: string;
|
|
17
|
+
restored?: BfcacheIdMap | null;
|
|
18
|
+
reuseCurrent?: boolean;
|
|
19
|
+
}): BfcacheIdMap;
|
|
20
|
+
declare function preserveBfcacheIdsForMergedElements(options: {
|
|
21
|
+
elements: AppElements;
|
|
22
|
+
next: BfcacheIdMap;
|
|
23
|
+
previous: BfcacheIdMap;
|
|
24
|
+
}): BfcacheIdMap;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { BfcacheStateKeyMap, createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { countConsumedPathnameSegments, isInvisibleSegment, normalizePathnameForRouteMatch, splitPathSegments } from "../routing/utils.js";
|
|
2
|
+
import { normalizePath } from "./normalize-path.js";
|
|
3
|
+
import { AppElementsWire } from "./app-elements-wire.js";
|
|
4
|
+
import "./app-elements.js";
|
|
5
|
+
import "./app-bfcache-id.js";
|
|
6
|
+
import { isBfcacheSegmentId } from "./app-history-state.js";
|
|
7
|
+
//#region src/server/app-bfcache-identity.ts
|
|
8
|
+
let nextBfcacheId = 0;
|
|
9
|
+
function rememberBfcacheId(value) {
|
|
10
|
+
const match = /^_b_(\d+)_$/.exec(value);
|
|
11
|
+
if (!match) return;
|
|
12
|
+
nextBfcacheId = Math.max(nextBfcacheId, Number(match[1]));
|
|
13
|
+
}
|
|
14
|
+
function mintBfcacheId() {
|
|
15
|
+
nextBfcacheId += 1;
|
|
16
|
+
return `_b_${nextBfcacheId}_`;
|
|
17
|
+
}
|
|
18
|
+
function getVisibleTreePathSegments(treePath) {
|
|
19
|
+
return splitPathSegments(treePath).filter((segment) => !isInvisibleSegment(segment));
|
|
20
|
+
}
|
|
21
|
+
function getTreePathIdentityPrefix(pathname, treePath) {
|
|
22
|
+
const pathnameSegments = splitPathSegments(pathname);
|
|
23
|
+
const consumedPathnameSegments = countConsumedPathnameSegments(getVisibleTreePathSegments(treePath), pathnameSegments.length);
|
|
24
|
+
if (consumedPathnameSegments === 0) return "/";
|
|
25
|
+
return `/${pathnameSegments.slice(0, consumedPathnameSegments).join("/")}`;
|
|
26
|
+
}
|
|
27
|
+
function readAppElementsMetadata(elements) {
|
|
28
|
+
let metadata;
|
|
29
|
+
try {
|
|
30
|
+
metadata = AppElementsWire.readMetadata(elements);
|
|
31
|
+
} catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const slotBindingsBySlotId = /* @__PURE__ */ new Map();
|
|
35
|
+
for (const binding of metadata.slotBindings) slotBindingsBySlotId.set(binding.slotId, binding);
|
|
36
|
+
return {
|
|
37
|
+
metadata,
|
|
38
|
+
slotBindingsBySlotId
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function createActiveSlotIdentity(id, parsed) {
|
|
42
|
+
const activeSlotBinding = parsed?.slotBindingsBySlotId.get(id);
|
|
43
|
+
if (activeSlotBinding?.activeRouteId != null) return `${id}@${activeSlotBinding.activeRouteId}`;
|
|
44
|
+
const interception = parsed?.metadata.interception;
|
|
45
|
+
if (interception?.slotId !== id) return null;
|
|
46
|
+
return `${id}@${interception.targetRouteId}`;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Derive BFCache identity from AppElements wire keys. Keep wire-key parsing
|
|
50
|
+
* contained here until vinext has a route-manifest authority equivalent to
|
|
51
|
+
* Next.js CacheNode or segment-cache state.
|
|
52
|
+
*/
|
|
53
|
+
function createBfcacheSegmentIdentity(id, options) {
|
|
54
|
+
const parsed = AppElementsWire.parseElementKey(id);
|
|
55
|
+
if (!parsed) return null;
|
|
56
|
+
if (parsed.kind === "page") return `${id}@${options.pathname}`;
|
|
57
|
+
if (parsed.kind === "slot") {
|
|
58
|
+
const activeSlotIdentity = createActiveSlotIdentity(id, options.metadata);
|
|
59
|
+
if (activeSlotIdentity !== null) return activeSlotIdentity;
|
|
60
|
+
return `${id}@${getTreePathIdentityPrefix(options.pathname, parsed.treePath)}`;
|
|
61
|
+
}
|
|
62
|
+
if (parsed.kind === "layout" || parsed.kind === "template") return `${id}@${getTreePathIdentityPrefix(options.pathname, parsed.treePath)}`;
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
function collectBfcacheSegmentIds(elements, parsed) {
|
|
66
|
+
const ids = new Set(Object.keys(elements));
|
|
67
|
+
const metadata = parsed === void 0 ? readAppElementsMetadata(elements) : parsed;
|
|
68
|
+
for (const layoutId of metadata?.metadata.layoutIds ?? []) ids.add(layoutId);
|
|
69
|
+
return Array.from(ids).filter(isBfcacheSegmentId);
|
|
70
|
+
}
|
|
71
|
+
function createInitialBfcacheIdMap(elements) {
|
|
72
|
+
const ids = {};
|
|
73
|
+
for (const id of collectBfcacheSegmentIds(elements)) ids[id] = "0";
|
|
74
|
+
return ids;
|
|
75
|
+
}
|
|
76
|
+
function normalizeBfcachePathname(pathname) {
|
|
77
|
+
const normalized = normalizePath(normalizePathnameForRouteMatch(pathname));
|
|
78
|
+
return normalized.length > 1 ? normalized.replace(/\/$/, "") : normalized;
|
|
79
|
+
}
|
|
80
|
+
function createBfcacheSegmentStateKeyMap(options) {
|
|
81
|
+
const metadata = readAppElementsMetadata(options.elements);
|
|
82
|
+
const normalizedPathname = normalizeBfcachePathname(options.pathname);
|
|
83
|
+
const stateKeys = {};
|
|
84
|
+
for (const id of collectBfcacheSegmentIds(options.elements, metadata)) {
|
|
85
|
+
const stateKey = createBfcacheSegmentIdentity(id, {
|
|
86
|
+
metadata,
|
|
87
|
+
pathname: normalizedPathname
|
|
88
|
+
});
|
|
89
|
+
if (stateKey !== null) stateKeys[id] = stateKey;
|
|
90
|
+
}
|
|
91
|
+
return stateKeys;
|
|
92
|
+
}
|
|
93
|
+
function createNextBfcacheIdMap(options) {
|
|
94
|
+
const current = options.reuseCurrent === false ? {} : options.current;
|
|
95
|
+
for (const value of Object.values(current)) rememberBfcacheId(value);
|
|
96
|
+
for (const value of Object.values(options.restored ?? {})) rememberBfcacheId(value);
|
|
97
|
+
const currentMetadata = readAppElementsMetadata(options.currentElements);
|
|
98
|
+
const nextMetadata = readAppElementsMetadata(options.elements);
|
|
99
|
+
const currentPathname = normalizeBfcachePathname(options.currentPathname);
|
|
100
|
+
const nextPathname = normalizeBfcachePathname(options.nextPathname);
|
|
101
|
+
const ids = {};
|
|
102
|
+
for (const id of collectBfcacheSegmentIds(options.elements, nextMetadata)) {
|
|
103
|
+
const currentValue = createBfcacheSegmentIdentity(id, {
|
|
104
|
+
metadata: currentMetadata,
|
|
105
|
+
pathname: currentPathname
|
|
106
|
+
}) === createBfcacheSegmentIdentity(id, {
|
|
107
|
+
metadata: nextMetadata,
|
|
108
|
+
pathname: nextPathname
|
|
109
|
+
}) ? current[id] : void 0;
|
|
110
|
+
const value = options.restored?.[id] ?? currentValue ?? mintBfcacheId();
|
|
111
|
+
ids[id] = value;
|
|
112
|
+
rememberBfcacheId(value);
|
|
113
|
+
}
|
|
114
|
+
return ids;
|
|
115
|
+
}
|
|
116
|
+
function preserveBfcacheIdsForMergedElements(options) {
|
|
117
|
+
const ids = {};
|
|
118
|
+
for (const id of collectBfcacheSegmentIds(options.elements)) {
|
|
119
|
+
const value = options.next[id] ?? options.previous[id];
|
|
120
|
+
if (value === void 0) continue;
|
|
121
|
+
ids[id] = value;
|
|
122
|
+
rememberBfcacheId(value);
|
|
123
|
+
}
|
|
124
|
+
return ids;
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
export { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements };
|
|
@@ -6,25 +6,29 @@ import { getMountedSlotIdsHeader, resolveVisitedResponseInterceptionContext } fr
|
|
|
6
6
|
import { AppRouterContext } from "../shims/internal/app-router-context.js";
|
|
7
7
|
import { installWindowNext, setWindowNextInternalSourcePage } from "../client/window-next.js";
|
|
8
8
|
import { retryScrollTo, scrollToHashTargetOnNextFrame } from "../shims/hash-scroll.js";
|
|
9
|
+
import { getBfcacheIdMapContext, setNavigationContext } from "../shims/navigation-context-state.js";
|
|
10
|
+
import { decodeRedirectError, isRedirectError } from "../shims/navigation-errors.js";
|
|
11
|
+
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
12
|
+
import { clearAppNavigationFailureTarget, installAppNavigationFailureListeners } from "../client/app-nav-failure-handler.js";
|
|
13
|
+
import { DevRecoveryBoundary, GlobalErrorBoundary, RedirectBoundary } from "../shims/error-boundary.js";
|
|
14
|
+
import { beginAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
15
|
+
import { AppRouterScrollCommitProvider } from "../shims/app-router-scroll.js";
|
|
16
|
+
import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
|
|
17
|
+
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId } from "./app-rsc-cache-busting.js";
|
|
9
18
|
import { getNavigationRuntime, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
|
|
10
19
|
import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
|
|
11
|
-
import
|
|
20
|
+
import "../client/instrumentation-client.js";
|
|
12
21
|
import { resolveManifestNavigationInterceptionContext, resolveMiddlewareRewriteNavigationInterceptionContext } from "./app-browser-interception-context.js";
|
|
13
22
|
import { readHistoryStatePreviousNextUrl } from "./app-history-state.js";
|
|
14
|
-
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId } from "./app-rsc-cache-busting.js";
|
|
15
23
|
import { AppBrowserMpaNavigationScheduler } from "./app-browser-mpa-navigation.js";
|
|
24
|
+
import { blockDangerousStreamedRscRedirect } from "./app-browser-rsc-redirect.js";
|
|
16
25
|
import { navigationPlanner } from "./navigation-planner.js";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
20
|
-
import { DevRecoveryBoundary, GlobalErrorBoundary, RedirectBoundary } from "../shims/error-boundary.js";
|
|
21
|
-
import { AppRouterScrollCommitProvider } from "../shims/app-router-scroll.js";
|
|
22
|
-
import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
|
|
23
|
-
import "../client/instrumentation-client.js";
|
|
26
|
+
import { __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, getClientNavigationRenderContext, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, setClientParams, setMountedSlotsHeader, setPendingPathname, useRouter } from "../shims/navigation.js";
|
|
27
|
+
import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
|
|
24
28
|
import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult } from "./app-browser-action-result.js";
|
|
25
29
|
import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
|
|
26
30
|
import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
|
|
27
|
-
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN,
|
|
31
|
+
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl, resolveServerActionRequestState } from "./app-browser-state.js";
|
|
28
32
|
import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch } from "./app-browser-navigation-controller.js";
|
|
29
33
|
import { applyServerActionResultDecision } from "./app-browser-server-action-navigation.js";
|
|
30
34
|
import { consumeInitialFormState, createVinextHydrateRootOptions, hydrateRootInTransition } from "./app-browser-hydration.js";
|
|
@@ -1029,6 +1033,8 @@ function bootstrapHydration(rscStream) {
|
|
|
1029
1033
|
}
|
|
1030
1034
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
1031
1035
|
const navContentType = navResponse.headers.get("content-type") ?? "";
|
|
1036
|
+
const streamedRedirectTarget = navResponse.headers.get(VINEXT_RSC_REDIRECT_HEADER);
|
|
1037
|
+
if (blockDangerousStreamedRscRedirect(navResponse, streamedRedirectTarget)) return;
|
|
1032
1038
|
const liveFetchDecision = navigationPlanner.classifyRscFetchResult({
|
|
1033
1039
|
clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
|
|
1034
1040
|
compatibilityIdHeader: navResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
|
|
@@ -1042,7 +1048,7 @@ function bootstrapHydration(rscStream) {
|
|
|
1042
1048
|
responseOk: navResponse.ok,
|
|
1043
1049
|
responseUrl: navResponseUrl ?? navResponse.url,
|
|
1044
1050
|
source: "live",
|
|
1045
|
-
streamedRedirectTarget
|
|
1051
|
+
streamedRedirectTarget
|
|
1046
1052
|
});
|
|
1047
1053
|
if (liveFetchDecision.kind === "hardNavigate") {
|
|
1048
1054
|
if (liveFetchDecision.discardBody) navResponse.body?.cancel().catch(() => {});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
//#region src/server/app-browser-rsc-redirect.d.ts
|
|
2
|
+
declare function blockDangerousStreamedRscRedirect(response: Response, streamedRedirectTarget: string | null): boolean;
|
|
2
3
|
type RscRedirectHistoryUpdateMode = "push" | "replace" | undefined;
|
|
3
4
|
type RscRedirectLifecycleDecision = {
|
|
4
5
|
href: string;
|
|
@@ -34,4 +35,4 @@ declare function resolveStreamedRscRedirectLifecycleHop(options: {
|
|
|
34
35
|
streamedRedirectTarget: string;
|
|
35
36
|
}): RscRedirectLifecycleDecision;
|
|
36
37
|
//#endregion
|
|
37
|
-
export { resolveRscRedirectLifecycleHop, resolveStreamedRscRedirectLifecycleHop };
|
|
38
|
+
export { blockDangerousStreamedRscRedirect, resolveRscRedirectLifecycleHop, resolveStreamedRscRedirectLifecycleHop };
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { isDangerousScheme, reportBlockedDangerousNavigation } from "../shims/url-safety.js";
|
|
1
2
|
import { resolveHardNavigationTargetFromRscResponse, stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
|
|
2
3
|
//#region src/server/app-browser-rsc-redirect.ts
|
|
3
4
|
const MAX_RSC_REDIRECT_DEPTH = 10;
|
|
5
|
+
function blockDangerousStreamedRscRedirect(response, streamedRedirectTarget) {
|
|
6
|
+
if (streamedRedirectTarget === null || !isDangerousScheme(streamedRedirectTarget)) return false;
|
|
7
|
+
response.body?.cancel().catch(() => {});
|
|
8
|
+
reportBlockedDangerousNavigation();
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
4
11
|
function toVisibleAppHref(href, origin) {
|
|
5
12
|
const url = new URL(href, origin);
|
|
6
13
|
stripRscCacheBustingSearchParam(url);
|
|
@@ -54,4 +61,4 @@ function resolveStreamedRscRedirectLifecycleHop(options) {
|
|
|
54
61
|
});
|
|
55
62
|
}
|
|
56
63
|
//#endregion
|
|
57
|
-
export { resolveRscRedirectLifecycleHop, resolveStreamedRscRedirectLifecycleHop };
|
|
64
|
+
export { blockDangerousStreamedRscRedirect, resolveRscRedirectLifecycleHop, resolveStreamedRscRedirectLifecycleHop };
|
|
@@ -3,8 +3,9 @@ import { CacheEntryReuseProof } from "./cache-proof.js";
|
|
|
3
3
|
import { AppElements, AppElementsInterception, AppElementsSlotBinding, LayoutFlags } from "./app-elements-wire.js";
|
|
4
4
|
import { NavigationTrace } from "./navigation-trace.js";
|
|
5
5
|
import { OperationLane } from "./operation-token.js";
|
|
6
|
-
import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
7
6
|
import { BfcacheIdMap, HistoryTraversalIntent, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
7
|
+
import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
8
|
+
import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
8
9
|
|
|
9
10
|
//#region src/server/app-browser-state.d.ts
|
|
10
11
|
type OperationRecordBase = {
|
|
@@ -70,7 +71,6 @@ type AppNavigationPayloadOrigin = Readonly<{
|
|
|
70
71
|
} | {
|
|
71
72
|
origin: "visited-cache";
|
|
72
73
|
}>;
|
|
73
|
-
type BfcacheStateKeyMap = Readonly<Record<string, string>>;
|
|
74
74
|
declare const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN: AppNavigationPayloadOrigin;
|
|
75
75
|
declare const VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN: AppNavigationPayloadOrigin;
|
|
76
76
|
type PendingNavigationCommitDisposition = "dispatch" | "hard-navigate" | "skip";
|
|
@@ -91,25 +91,6 @@ type NonDispatchPendingNavigationCommitDispositionDecision = {
|
|
|
91
91
|
trace: NavigationTrace;
|
|
92
92
|
};
|
|
93
93
|
type PendingNavigationCommitDispositionDecision = DispatchPendingNavigationCommitDispositionDecision | NonDispatchPendingNavigationCommitDispositionDecision;
|
|
94
|
-
declare function createInitialBfcacheIdMap(elements: AppElements): BfcacheIdMap;
|
|
95
|
-
declare function createBfcacheSegmentStateKeyMap(options: {
|
|
96
|
-
elements: AppElements;
|
|
97
|
-
pathname: string;
|
|
98
|
-
}): BfcacheStateKeyMap;
|
|
99
|
-
declare function createNextBfcacheIdMap(options: {
|
|
100
|
-
current: BfcacheIdMap;
|
|
101
|
-
currentElements: AppElements;
|
|
102
|
-
currentPathname: string;
|
|
103
|
-
elements: AppElements;
|
|
104
|
-
nextPathname: string;
|
|
105
|
-
restored?: BfcacheIdMap | null;
|
|
106
|
-
reuseCurrent?: boolean;
|
|
107
|
-
}): BfcacheIdMap;
|
|
108
|
-
declare function preserveBfcacheIdsForMergedElements(options: {
|
|
109
|
-
elements: AppElements;
|
|
110
|
-
next: BfcacheIdMap;
|
|
111
|
-
previous: BfcacheIdMap;
|
|
112
|
-
}): BfcacheIdMap;
|
|
113
94
|
declare function isCacheRestorableAppPayloadMetadata(metadata: CacheRestorableAppPayloadMetadata): metadata is CacheRestorableAppPayloadMetadata & {
|
|
114
95
|
cacheEntryReuseProof: CacheEntryReuseProof;
|
|
115
96
|
};
|
|
@@ -1,144 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
2
2
|
import { stripBasePath } from "../utils/base-path.js";
|
|
3
3
|
import { NEXT_ACTION_HEADER, RSC_ACTION_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER } from "./headers.js";
|
|
4
4
|
import { normalizePath } from "./normalize-path.js";
|
|
5
5
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
6
6
|
import { getMountedSlotIds, getMountedSlotIdsHeader } from "./app-elements.js";
|
|
7
|
-
import "./app-bfcache-id.js";
|
|
8
|
-
import { createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isBfcacheSegmentId, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
9
7
|
import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
|
|
8
|
+
import { createCacheEntryReuseProof } from "./cache-proof.js";
|
|
9
|
+
import { createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
10
10
|
import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
|
|
11
11
|
import { verifyOperationTokenForCommit } from "./operation-token.js";
|
|
12
12
|
import { navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts } from "./navigation-planner.js";
|
|
13
13
|
import { createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
14
|
-
import {
|
|
14
|
+
import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
15
15
|
//#region src/server/app-browser-state.ts
|
|
16
16
|
const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "fresh" };
|
|
17
17
|
const VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "visited-cache" };
|
|
18
|
-
let nextBfcacheId = 0;
|
|
19
|
-
function rememberBfcacheId(value) {
|
|
20
|
-
const match = /^_b_(\d+)_$/.exec(value);
|
|
21
|
-
if (!match) return;
|
|
22
|
-
nextBfcacheId = Math.max(nextBfcacheId, Number(match[1]));
|
|
23
|
-
}
|
|
24
|
-
function mintBfcacheId() {
|
|
25
|
-
nextBfcacheId += 1;
|
|
26
|
-
return `_b_${nextBfcacheId}_`;
|
|
27
|
-
}
|
|
28
|
-
function getVisibleTreePathSegments(treePath) {
|
|
29
|
-
return splitPathSegments(treePath).filter((segment) => !isInvisibleSegment(segment));
|
|
30
|
-
}
|
|
31
|
-
function getTreePathIdentityPrefix(pathname, treePath) {
|
|
32
|
-
const pathnameSegments = splitPathSegments(pathname);
|
|
33
|
-
const consumedPathnameSegments = countConsumedPathnameSegments(getVisibleTreePathSegments(treePath), pathnameSegments.length);
|
|
34
|
-
if (consumedPathnameSegments === 0) return "/";
|
|
35
|
-
return `/${pathnameSegments.slice(0, consumedPathnameSegments).join("/")}`;
|
|
36
|
-
}
|
|
37
|
-
function readAppElementsMetadata(elements) {
|
|
38
|
-
let metadata;
|
|
39
|
-
try {
|
|
40
|
-
metadata = AppElementsWire.readMetadata(elements);
|
|
41
|
-
} catch {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
const slotBindingsBySlotId = /* @__PURE__ */ new Map();
|
|
45
|
-
for (const binding of metadata.slotBindings) slotBindingsBySlotId.set(binding.slotId, binding);
|
|
46
|
-
return {
|
|
47
|
-
metadata,
|
|
48
|
-
slotBindingsBySlotId
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
function createActiveSlotIdentity(id, parsed) {
|
|
52
|
-
const activeSlotBinding = parsed?.slotBindingsBySlotId.get(id);
|
|
53
|
-
if (activeSlotBinding?.activeRouteId != null) return `${id}@${activeSlotBinding.activeRouteId}`;
|
|
54
|
-
const interception = parsed?.metadata.interception;
|
|
55
|
-
if (interception?.slotId !== id) return null;
|
|
56
|
-
return `${id}@${interception.targetRouteId}`;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Legacy bridge for deriving a bfcache segment identity from AppElements wire
|
|
60
|
-
* keys. Keep wire-key parsing contained here until Vinext has a route-manifest
|
|
61
|
-
* semantic authority equivalent to Next.js CacheNode/segment-cache state.
|
|
62
|
-
*/
|
|
63
|
-
function createBfcacheSegmentIdentity(id, options) {
|
|
64
|
-
const parsed = AppElementsWire.parseElementKey(id);
|
|
65
|
-
if (!parsed) return null;
|
|
66
|
-
if (parsed.kind === "page") return `${id}@${options.pathname}`;
|
|
67
|
-
if (parsed.kind === "slot") {
|
|
68
|
-
const activeSlotIdentity = createActiveSlotIdentity(id, options.metadata);
|
|
69
|
-
if (activeSlotIdentity !== null) return activeSlotIdentity;
|
|
70
|
-
return `${id}@${getTreePathIdentityPrefix(options.pathname, parsed.treePath)}`;
|
|
71
|
-
}
|
|
72
|
-
if (parsed.kind === "layout" || parsed.kind === "template") return `${id}@${getTreePathIdentityPrefix(options.pathname, parsed.treePath)}`;
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
function collectBfcacheSegmentIds(elements, parsed) {
|
|
76
|
-
const ids = new Set(Object.keys(elements));
|
|
77
|
-
const metadata = parsed === void 0 ? readAppElementsMetadata(elements) : parsed;
|
|
78
|
-
for (const layoutId of metadata?.metadata.layoutIds ?? []) ids.add(layoutId);
|
|
79
|
-
return Array.from(ids).filter(isBfcacheSegmentId);
|
|
80
|
-
}
|
|
81
|
-
function createInitialBfcacheIdMap(elements) {
|
|
82
|
-
const ids = {};
|
|
83
|
-
for (const id of collectBfcacheSegmentIds(elements)) ids[id] = "0";
|
|
84
|
-
return ids;
|
|
85
|
-
}
|
|
86
|
-
function normalizeBfcachePathname(pathname) {
|
|
87
|
-
const normalized = normalizePath(normalizePathnameForRouteMatch(pathname));
|
|
88
|
-
return normalized.length > 1 ? normalized.replace(/\/$/, "") : normalized;
|
|
89
|
-
}
|
|
90
|
-
function createBfcacheSegmentStateKeyMap(options) {
|
|
91
|
-
const metadata = readAppElementsMetadata(options.elements);
|
|
92
|
-
const normalizedPathname = normalizeBfcachePathname(options.pathname);
|
|
93
|
-
const stateKeys = {};
|
|
94
|
-
for (const id of collectBfcacheSegmentIds(options.elements, metadata)) {
|
|
95
|
-
const stateKey = createBfcacheSegmentIdentity(id, {
|
|
96
|
-
metadata,
|
|
97
|
-
pathname: normalizedPathname
|
|
98
|
-
});
|
|
99
|
-
if (stateKey !== null) stateKeys[id] = stateKey;
|
|
100
|
-
}
|
|
101
|
-
return stateKeys;
|
|
102
|
-
}
|
|
103
|
-
function createNextBfcacheIdMap(options) {
|
|
104
|
-
const current = options.reuseCurrent === false ? {} : options.current;
|
|
105
|
-
for (const value of Object.values(current)) rememberBfcacheId(value);
|
|
106
|
-
for (const value of Object.values(options.restored ?? {})) rememberBfcacheId(value);
|
|
107
|
-
const currentMetadata = readAppElementsMetadata(options.currentElements);
|
|
108
|
-
const nextMetadata = readAppElementsMetadata(options.elements);
|
|
109
|
-
const currentPathname = normalizeBfcachePathname(options.currentPathname);
|
|
110
|
-
const nextPathname = normalizeBfcachePathname(options.nextPathname);
|
|
111
|
-
const ids = {};
|
|
112
|
-
for (const id of collectBfcacheSegmentIds(options.elements, nextMetadata)) {
|
|
113
|
-
const currentValue = createBfcacheSegmentIdentity(id, {
|
|
114
|
-
metadata: currentMetadata,
|
|
115
|
-
pathname: currentPathname
|
|
116
|
-
}) === createBfcacheSegmentIdentity(id, {
|
|
117
|
-
metadata: nextMetadata,
|
|
118
|
-
pathname: nextPathname
|
|
119
|
-
}) ? current[id] : void 0;
|
|
120
|
-
const value = options.restored?.[id] ?? currentValue ?? mintBfcacheId();
|
|
121
|
-
ids[id] = value;
|
|
122
|
-
rememberBfcacheId(value);
|
|
123
|
-
}
|
|
124
|
-
return ids;
|
|
125
|
-
}
|
|
126
|
-
function preserveBfcacheIdsForMergedElements(options) {
|
|
127
|
-
const ids = {};
|
|
128
|
-
for (const id of collectBfcacheSegmentIds(options.elements)) {
|
|
129
|
-
const nextValue = options.next[id];
|
|
130
|
-
if (nextValue !== void 0) {
|
|
131
|
-
ids[id] = nextValue;
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
const previousValue = options.previous[id];
|
|
135
|
-
if (previousValue !== void 0) {
|
|
136
|
-
ids[id] = previousValue;
|
|
137
|
-
rememberBfcacheId(previousValue);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return ids;
|
|
141
|
-
}
|
|
142
18
|
function createOperationRecord(options) {
|
|
143
19
|
return {
|
|
144
20
|
id: options.id,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ensureNavigationRuntimeRscBootstrap, getNavigationRuntime } from "../client/navigation-runtime.js";
|
|
2
1
|
import { decodeRscEmbeddedChunk } from "./app-rsc-embedded-chunks.js";
|
|
2
|
+
import { ensureNavigationRuntimeRscBootstrap, getNavigationRuntime } from "../client/navigation-runtime.js";
|
|
3
3
|
//#region src/server/app-browser-stream.ts
|
|
4
4
|
function getVinextBrowserGlobal() {
|
|
5
5
|
return globalThis;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
2
2
|
import "./app-elements.js";
|
|
3
|
-
import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
|
|
4
3
|
import { mergeElements } from "../shims/slot.js";
|
|
5
|
-
import {
|
|
4
|
+
import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
|
|
5
|
+
import { preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
6
|
+
import { createPendingNavigationCommit, resolvePendingNavigationCommitDispositionDecision } from "./app-browser-state.js";
|
|
6
7
|
//#region src/server/app-browser-visible-commit.ts
|
|
7
8
|
const approvedVisibleCommitBrand = Symbol("ApprovedVisibleCommit");
|
|
8
9
|
function applyApprovedVisibleCommit(state, commit) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MetadataFileRoute } from "./metadata-routes.js";
|
|
2
2
|
import { AppElements } from "./app-elements-wire.js";
|
|
3
|
-
import { NavigationContext } from "../shims/navigation.js";
|
|
3
|
+
import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
4
4
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
5
5
|
import { AppPageFontPreload } from "./app-page-execution.js";
|
|
6
6
|
import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { UnstableCacheObservation } from "../shims/cache-request-state.js";
|
|
1
2
|
import { RenderRequestApiKind } from "./cache-proof.js";
|
|
2
|
-
import { UnstableCacheObservation } from "../shims/cache.js";
|
|
3
3
|
import { ClientReuseManifestRejectionCode, ClientReuseManifestTraceFields } from "./client-reuse-manifest.js";
|
|
4
4
|
import { ThenableParamsObserver } from "../shims/thenable-params.js";
|
|
5
5
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isInsideUnifiedScope, runWithUnifiedStateMutation } from "../shims/unified-request-context.js";
|
|
2
2
|
import { peekDynamicUsage, peekRenderRequestApiUsage } from "../shims/headers.js";
|
|
3
|
-
import { _peekRequestScopedCacheLife, _peekUnstableCacheObservations } from "../shims/cache.js";
|
|
3
|
+
import { _peekRequestScopedCacheLife, _peekUnstableCacheObservations } from "../shims/cache-request-state.js";
|
|
4
4
|
import { getCollectedFetchTags, peekCacheableFetchObservations, peekDynamicFetchObservations } from "../shims/fetch-cache.js";
|
|
5
5
|
import { isPromiseLike } from "../utils/promise.js";
|
|
6
6
|
//#region src/server/app-layout-param-observation.ts
|
|
@@ -5,8 +5,9 @@ import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
|
5
5
|
import { cloneRequestWithHeaders, processMiddlewareHeaders } from "./request-pipeline.js";
|
|
6
6
|
import { executeMiddleware } from "./middleware-runtime.js";
|
|
7
7
|
import { applyMiddlewareRequestHeaders, setHeadersContext } from "../shims/headers.js";
|
|
8
|
-
import { setNavigationContext } from "../shims/navigation.js";
|
|
8
|
+
import { setNavigationContext } from "../shims/navigation-context-state.js";
|
|
9
9
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
10
|
+
import "../shims/navigation.js";
|
|
10
11
|
//#region src/server/app-middleware.ts
|
|
11
12
|
const FLIGHT_HEADER_SET = new Set(FLIGHT_HEADERS);
|
|
12
13
|
function isForwardedMiddlewareContext(value) {
|
|
@@ -116,6 +117,7 @@ async function applyAppMiddleware(options) {
|
|
|
116
117
|
const result = await executeMiddleware({
|
|
117
118
|
basePath: options.basePath,
|
|
118
119
|
hadBasePath: true,
|
|
120
|
+
filePath: options.filePath,
|
|
119
121
|
i18nConfig: options.i18nConfig,
|
|
120
122
|
isDataRequest: options.isDataRequest,
|
|
121
123
|
isProxy: options.isProxy,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MetadataFileRoute } from "./metadata-routes.js";
|
|
2
2
|
import { AppElements } from "./app-elements-wire.js";
|
|
3
|
-
import { NavigationContext } from "../shims/navigation.js";
|
|
3
|
+
import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
4
4
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
5
5
|
import { AppPageFontPreload } from "./app-page-execution.js";
|
|
6
6
|
import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { runWithFetchDedupe } from "../shims/fetch-cache.js";
|
|
2
|
-
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
3
2
|
import { resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
3
|
+
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
4
4
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
5
5
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
6
6
|
//#region src/server/app-page-boundary.ts
|