vinext 1.3.1 → 1.4.1
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 +25 -22
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +4 -3
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +4 -7
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay-store.d.ts +1 -0
- package/dist/client/dev-error-overlay.d.ts +2 -0
- package/dist/client/dev-error-overlay.js +20 -4
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +2 -0
- package/dist/config/destination-params.d.ts +2 -1
- package/dist/config/destination-params.js +52 -2
- package/dist/config/next-config.d.ts +25 -0
- package/dist/config/next-config.js +82 -4
- 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 -49
- 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 +36 -9
- package/dist/index.js +112 -90
- 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/strip-server-exports.js +2 -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 +21 -5
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +86 -66
- 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 +7 -7
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +5 -4
- 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 +4 -14
- 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 +43 -4
- package/dist/server/app-page-boundary-render.js +10 -14
- 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 -11
- package/dist/server/app-page-dispatch.js +84 -155
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +13 -12
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +102 -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 -13
- package/dist/server/app-page-render.js +103 -234
- 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 +86 -63
- 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 +12 -8
- package/dist/server/app-page-stream.js +4 -3
- 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-request-stage-independent-entry.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 +11 -5
- 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.d.ts +1 -1
- package/dist/server/app-route-handler-runtime.js +28 -11
- package/dist/server/app-router-entry.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +12 -12
- package/dist/server/app-rsc-cache-busting.js +31 -72
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +10 -2
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +11 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +80 -83
- package/dist/server/app-rsc-request-normalization.d.ts +10 -16
- package/dist/server/app-rsc-request-normalization.js +12 -18
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +9 -15
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +15 -8
- package/dist/server/app-ssr-entry.d.ts +8 -0
- package/dist/server/app-ssr-entry.js +22 -16
- 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 +37 -6
- package/dist/server/app-worker-stages.js +81 -9
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/bfcache-identity.d.ts +7 -0
- package/dist/server/bfcache-identity.js +10 -1
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-manifest.js +1 -2
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-origin-check.d.ts +2 -1
- package/dist/server/dev-origin-check.js +2 -1
- package/dist/server/dev-server.js +6 -4
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/image-optimization.d.ts +5 -0
- package/dist/server/image-optimization.js +6 -1
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +30 -2
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/middleware-matcher.js +19 -6
- package/dist/server/middleware-runtime.js +6 -2
- package/dist/server/multi-stage.d.ts +57 -12
- 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.d.ts +1 -1
- package/dist/server/pages-node-compat.js +54 -27
- package/dist/server/pages-page-data.js +2 -1
- package/dist/server/pages-page-handler.js +28 -26
- package/dist/server/pages-page-response.d.ts +9 -0
- package/dist/server/pages-page-response.js +18 -4
- 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 +36 -14
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/pages-router-entry.js +3 -2
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +47 -9
- package/dist/server/request-error-log.d.ts +9 -0
- package/dist/server/request-error-log.js +13 -0
- package/dist/server/request-pipeline.d.ts +15 -4
- package/dist/server/request-pipeline.js +43 -15
- package/dist/server/rsc-completion-metadata.js +3 -0
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- package/dist/server/static-file-cache.d.ts +9 -0
- package/dist/server/static-file-cache.js +13 -2
- 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 +23 -26
- package/dist/shims/cache-request-state.js +22 -57
- package/dist/shims/cache-runtime.d.ts +3 -1
- package/dist/shims/cache-runtime.js +94 -48
- package/dist/shims/cache.d.ts +16 -10
- package/dist/shims/cache.js +47 -36
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- package/dist/shims/client-hook-error.d.ts +2 -0
- package/dist/shims/client-hook-error.js +16 -1
- 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 +39 -25
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +10 -24
- package/dist/shims/headers.js +22 -70
- package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +8 -11
- 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 +184 -31
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +3 -2
- package/dist/shims/slot.d.ts +16 -0
- package/dist/shims/slot.js +44 -9
- package/dist/shims/unified-request-context.d.ts +7 -1
- package/dist/shims/unified-request-context.js +3 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- package/dist/utils/cache-life-profiles.d.ts +33 -0
- package/dist/utils/cache-life-profiles.js +111 -0
- package/dist/utils/middleware-request-headers.d.ts +14 -3
- package/dist/utils/middleware-request-headers.js +54 -7
- 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
|
@@ -3,7 +3,6 @@ import { compareStrings } from "../utils/compare.js";
|
|
|
3
3
|
import { isInterceptionMatchedUrlPath } from "./normalize-path.js";
|
|
4
4
|
import { createAppElementsWireSlotId, isAppElementsWireSlotId, parseAppElementsWireElementKey } from "./app-elements-wire-key.js";
|
|
5
5
|
import { createArtifactCompatibilityEnvelope, parseArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
|
|
6
|
-
import { releaseAppElementRenderDependency } from "./app-render-dependency.js";
|
|
7
6
|
import { isValidElement } from "react";
|
|
8
7
|
//#region src/server/app-elements-wire.ts
|
|
9
8
|
const APP_INTERCEPTION_SEPARATOR = "\0";
|
|
@@ -14,7 +13,6 @@ const APP_DYNAMIC_STALE_TIME_KEY = "__dynamicStaleTime";
|
|
|
14
13
|
const APP_INTERCEPTION_KEY = "__interception";
|
|
15
14
|
const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
|
|
16
15
|
const APP_LAYOUT_IDS_KEY = "__layoutIds";
|
|
17
|
-
const APP_LAYOUT_FLAGS_KEY = "__layoutFlags";
|
|
18
16
|
const APP_ROUTE_KEY = "__route";
|
|
19
17
|
const APP_ROOT_LAYOUT_KEY = "__rootLayout";
|
|
20
18
|
const APP_SKIPPED_LAYOUT_IDS_KEY = "__skippedLayoutIds";
|
|
@@ -33,7 +31,6 @@ const APP_BFCACHE_SEGMENT_IDENTITIES_KEY = "__bfcacheSegmentIdentities";
|
|
|
33
31
|
const APP_STATIC_SIBLINGS_KEY = "__staticSiblings";
|
|
34
32
|
const APP_UNMATCHED_SLOT_WIRE_VALUE = "__VINEXT_UNMATCHED_SLOT__";
|
|
35
33
|
const UNMATCHED_SLOT = Symbol.for("vinext.unmatchedSlot");
|
|
36
|
-
const EMPTY_SKIPPED_LAYOUT_IDS = /* @__PURE__ */ new Set();
|
|
37
34
|
function createCacheProofRejectionCodeSet(codes) {
|
|
38
35
|
return new Set(codes);
|
|
39
36
|
}
|
|
@@ -147,15 +144,6 @@ function normalizeAppElements(elements) {
|
|
|
147
144
|
for (const [key, value] of Object.entries(elements)) normalized[key] = isAppElementsWireSlotId(key) && value === "__VINEXT_UNMATCHED_SLOT__" ? UNMATCHED_SLOT : value;
|
|
148
145
|
return normalized;
|
|
149
146
|
}
|
|
150
|
-
function isLayoutFlagsRecord(value) {
|
|
151
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
152
|
-
for (const v of Object.values(value)) if (v !== "s" && v !== "d") return false;
|
|
153
|
-
return true;
|
|
154
|
-
}
|
|
155
|
-
function parseLayoutFlags(value) {
|
|
156
|
-
if (isLayoutFlagsRecord(value)) return value;
|
|
157
|
-
return {};
|
|
158
|
-
}
|
|
159
147
|
function parseLayoutIdList(value, fieldName) {
|
|
160
148
|
if (value === void 0) return [];
|
|
161
149
|
if (!Array.isArray(value)) throw new Error(`[vinext] Invalid ${fieldName} in App Router payload: expected layout id string[]`);
|
|
@@ -242,7 +230,7 @@ function parseInterceptionMetadata(value) {
|
|
|
242
230
|
* Used to distinguish the App Router payload object from bare React elements at
|
|
243
231
|
* the render boundary. Narrows to `Readonly<Record<string, unknown>>` because
|
|
244
232
|
* the outgoing payload carries heterogeneous values (ReactNodes for the rendered
|
|
245
|
-
* tree, plus metadata like `
|
|
233
|
+
* tree, plus metadata like `__artifactCompatibility`, a plain object). Delegates
|
|
246
234
|
* to React's canonical `isValidElement` so we don't depend on React's internal
|
|
247
235
|
* `$$typeof` marker scheme.
|
|
248
236
|
*/
|
|
@@ -252,36 +240,15 @@ function isAppElementsRecord(value) {
|
|
|
252
240
|
if (isValidElement(value)) return false;
|
|
253
241
|
return true;
|
|
254
242
|
}
|
|
255
|
-
function withLayoutFlags(elements, layoutFlags) {
|
|
256
|
-
return {
|
|
257
|
-
...elements,
|
|
258
|
-
[APP_LAYOUT_FLAGS_KEY]: layoutFlags
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
243
|
function buildOutgoingAppPayload(input) {
|
|
262
244
|
if (!isAppElementsRecord(input.element)) return input.element;
|
|
263
|
-
const skippedLayoutIds = createSkippedLayoutIds(input.skipDisposition);
|
|
264
245
|
const payload = {};
|
|
265
|
-
for (const [key, value] of Object.entries(input.element))
|
|
266
|
-
if (skippedLayoutIds.has(key)) {
|
|
267
|
-
releaseAppElementRenderDependency(input.element, key);
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
payload[key] = value === UNMATCHED_SLOT ? APP_UNMATCHED_SLOT_WIRE_VALUE : value;
|
|
271
|
-
}
|
|
272
|
-
payload[APP_LAYOUT_FLAGS_KEY] = input.layoutFlags;
|
|
273
|
-
if (skippedLayoutIds.size > 0) payload[APP_SKIPPED_LAYOUT_IDS_KEY] = [...skippedLayoutIds];
|
|
246
|
+
for (const [key, value] of Object.entries(input.element)) payload[key] = value === UNMATCHED_SLOT ? APP_UNMATCHED_SLOT_WIRE_VALUE : value;
|
|
274
247
|
payload[APP_ARTIFACT_COMPATIBILITY_KEY] = input.artifactCompatibility ?? createArtifactCompatibilityEnvelope();
|
|
275
248
|
if (input.cacheEntryReuseProof) payload[APP_CACHE_ENTRY_REUSE_PROOF_KEY] = input.cacheEntryReuseProof;
|
|
276
249
|
if (input.dynamicStaleTimeSeconds !== void 0) payload[APP_DYNAMIC_STALE_TIME_KEY] = input.dynamicStaleTimeSeconds;
|
|
277
250
|
return payload;
|
|
278
251
|
}
|
|
279
|
-
function createSkippedLayoutIds(skipDisposition) {
|
|
280
|
-
if (skipDisposition?.enabled !== true) return EMPTY_SKIPPED_LAYOUT_IDS;
|
|
281
|
-
const skippedLayoutIds = /* @__PURE__ */ new Set();
|
|
282
|
-
for (const id of skipDisposition.skippedEntryIds) if (parseAppElementsWireElementKey(id)?.kind === "layout") skippedLayoutIds.add(id);
|
|
283
|
-
return skippedLayoutIds;
|
|
284
|
-
}
|
|
285
252
|
function readArtifactCompatibilityMetadata(value) {
|
|
286
253
|
if (value === void 0) return createArtifactCompatibilityEnvelope();
|
|
287
254
|
return parseArtifactCompatibilityEnvelope(value) ?? createArtifactCompatibilityEnvelope();
|
|
@@ -351,7 +318,6 @@ function readAppElementsMetadata(elements) {
|
|
|
351
318
|
const rootLayoutTreePath = elements[APP_ROOT_LAYOUT_KEY];
|
|
352
319
|
if (rootLayoutTreePath === void 0) throw new Error("[vinext] Missing __rootLayout key in App Router payload");
|
|
353
320
|
if (rootLayoutTreePath !== null && typeof rootLayoutTreePath !== "string") throw new Error("[vinext] Invalid __rootLayout in App Router payload: expected string or null");
|
|
354
|
-
const layoutFlags = parseLayoutFlags(elements[APP_LAYOUT_FLAGS_KEY]);
|
|
355
321
|
const layoutIds = parseLayoutIds(elements[APP_LAYOUT_IDS_KEY]);
|
|
356
322
|
const skippedLayoutIds = parseSkippedLayoutIds(elements[APP_SKIPPED_LAYOUT_IDS_KEY]);
|
|
357
323
|
const slotBindings = parseSlotBindings(elements[APP_SLOT_BINDINGS_KEY], { layoutIds });
|
|
@@ -369,7 +335,6 @@ function readAppElementsMetadata(elements) {
|
|
|
369
335
|
interception,
|
|
370
336
|
interceptionContext: interceptionContext ?? null,
|
|
371
337
|
layoutIds,
|
|
372
|
-
layoutFlags,
|
|
373
338
|
routeId,
|
|
374
339
|
rootLayoutTreePath,
|
|
375
340
|
bfcacheSegmentIdentities,
|
|
@@ -386,7 +351,6 @@ const AppElementsWire = {
|
|
|
386
351
|
interception: APP_INTERCEPTION_KEY,
|
|
387
352
|
interceptionContext: APP_INTERCEPTION_CONTEXT_KEY,
|
|
388
353
|
layoutIds: APP_LAYOUT_IDS_KEY,
|
|
389
|
-
layoutFlags: APP_LAYOUT_FLAGS_KEY,
|
|
390
354
|
rootLayout: APP_ROOT_LAYOUT_KEY,
|
|
391
355
|
route: APP_ROUTE_KEY,
|
|
392
356
|
bfcacheSegmentIdentities: APP_BFCACHE_SEGMENT_IDENTITIES_KEY,
|
|
@@ -406,8 +370,7 @@ const AppElementsWire = {
|
|
|
406
370
|
encodeTemplateId: createAppPayloadTemplateId,
|
|
407
371
|
isSlotId: isAppElementsWireSlotId,
|
|
408
372
|
parseElementKey: parseAppElementsWireElementKey,
|
|
409
|
-
readMetadata: readAppElementsMetadata
|
|
410
|
-
withLayoutFlags
|
|
373
|
+
readMetadata: readAppElementsMetadata
|
|
411
374
|
};
|
|
412
375
|
//#endregion
|
|
413
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY,
|
|
376
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY,
|
|
1
|
+
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsBfcacheSegmentIdentities, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata } from "./app-elements-wire.js";
|
|
2
2
|
//#region src/server/app-elements.d.ts
|
|
3
3
|
export declare const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
|
|
4
4
|
/** Prefix of the element that streams a route's generateMetadata() tags in the body. */
|
|
@@ -7,4 +7,4 @@ export declare function getMountedSlotIds(elements: AppElements): string[];
|
|
|
7
7
|
export declare function getMountedSlotIdsHeader(elements: AppElements): string | null;
|
|
8
8
|
export declare function resolveVisitedResponseInterceptionContext(requestInterceptionContext: string | null, payloadInterceptionContext: string | null): string | null;
|
|
9
9
|
//#endregion
|
|
10
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY,
|
|
10
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsBfcacheSegmentIdentities, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
2
|
-
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY,
|
|
2
|
+
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata } from "./app-elements-wire.js";
|
|
3
3
|
//#region src/server/app-elements.ts
|
|
4
4
|
const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
|
|
5
5
|
/** Prefix of the element that streams a route's generateMetadata() tags in the body. */
|
|
@@ -18,4 +18,4 @@ function resolveVisitedResponseInterceptionContext(requestInterceptionContext, p
|
|
|
18
18
|
return payloadInterceptionContext ?? requestInterceptionContext;
|
|
19
19
|
}
|
|
20
20
|
//#endregion
|
|
21
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY,
|
|
21
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_STREAMING_METADATA_BODY_ID_PREFIX, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext };
|
|
@@ -75,11 +75,11 @@ export declare function isExternalHistoryState(state: unknown): boolean;
|
|
|
75
75
|
*/
|
|
76
76
|
export declare function isAppOwnedHistoryState(state: unknown): boolean;
|
|
77
77
|
export declare function createAppOwnedHistoryState(state: unknown): unknown;
|
|
78
|
-
export declare function createHistoryStateWithTreeSnapshotId(state: unknown, treeSnapshotId:
|
|
78
|
+
export declare function createHistoryStateWithTreeSnapshotId(state: unknown, treeSnapshotId: string | null): unknown;
|
|
79
79
|
export declare function createHistoryStateWithTreeSnapshotClaim(state: unknown, claimed: boolean): unknown;
|
|
80
80
|
export declare function isHistoryStateTreeSnapshotClaimed(state: unknown): boolean;
|
|
81
81
|
export declare function clearHistoryStateTreeSnapshotId(state: unknown): unknown;
|
|
82
|
-
export declare function readHistoryStateTreeSnapshotId(state: unknown):
|
|
82
|
+
export declare function readHistoryStateTreeSnapshotId(state: unknown): string | null;
|
|
83
83
|
export declare function readHistoryStateActiveRoutePaths(state: unknown): readonly string[] | null;
|
|
84
84
|
export declare function resolveActiveRoutePaths(slotBindings: readonly {
|
|
85
85
|
activeRouteId?: string | null;
|
|
@@ -210,7 +210,7 @@ function createAppOwnedHistoryState(state) {
|
|
|
210
210
|
function createHistoryStateWithTreeSnapshotId(state, treeSnapshotId) {
|
|
211
211
|
const nextState = cloneHistoryState(state);
|
|
212
212
|
const previousTreeSnapshotId = readHistoryStateTreeSnapshotId(nextState);
|
|
213
|
-
if (
|
|
213
|
+
if (isTreeSnapshotId(treeSnapshotId)) {
|
|
214
214
|
nextState[VINEXT_TREE_SNAPSHOT_ID_HISTORY_STATE_KEY] = treeSnapshotId;
|
|
215
215
|
if (previousTreeSnapshotId !== treeSnapshotId) delete nextState[VINEXT_TREE_SNAPSHOT_CLAIMED_HISTORY_STATE_KEY];
|
|
216
216
|
} else {
|
|
@@ -233,7 +233,10 @@ function clearHistoryStateTreeSnapshotId(state) {
|
|
|
233
233
|
}
|
|
234
234
|
function readHistoryStateTreeSnapshotId(state) {
|
|
235
235
|
const value = readHistoryStateRecord(state)?.[VINEXT_TREE_SNAPSHOT_ID_HISTORY_STATE_KEY];
|
|
236
|
-
return
|
|
236
|
+
return isTreeSnapshotId(value) ? value : null;
|
|
237
|
+
}
|
|
238
|
+
function isTreeSnapshotId(value) {
|
|
239
|
+
return typeof value === "string" && value.length > 0;
|
|
237
240
|
}
|
|
238
241
|
function readHistoryStateActiveRoutePaths(state) {
|
|
239
242
|
const value = readHistoryStateRecord(state)?.[VINEXT_ACTIVE_ROUTE_PATHS_HISTORY_STATE_KEY];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AppElements } from "./app-elements-wire.js";
|
|
2
|
+
import "./app-elements.js";
|
|
3
|
+
//#region src/server/app-mounted-layouts.d.ts
|
|
4
|
+
export declare function hashMountedLayoutIdentity(identity: string): string;
|
|
5
|
+
export declare function parseMountedLayoutsHeader(value: string | null): ReadonlySet<string> | null;
|
|
6
|
+
/**
|
|
7
|
+
* The header for the outermost layouts a client state holds. Only that prefix
|
|
8
|
+
* can be left out of a render, as a layout below one that re-renders renders
|
|
9
|
+
* inside it.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createMountedLayoutsHeader(elements: AppElements, layoutIds: readonly string[]): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Whether a client state still holds, unchanged, every layout a payload left
|
|
14
|
+
* out. A navigation that started from another state, or a payload stored for
|
|
15
|
+
* another client, can name layouts this one doesn't hold.
|
|
16
|
+
*/
|
|
17
|
+
export declare function holdsSkippedLayouts(current: {
|
|
18
|
+
elements: AppElements;
|
|
19
|
+
layoutIds: readonly string[];
|
|
20
|
+
}, next: AppElements): boolean;
|
|
21
|
+
//#endregion
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { fnv1a64 } from "../utils/hash.js";
|
|
2
|
+
import { AppElementsWire } from "./app-elements-wire.js";
|
|
3
|
+
import "./app-elements.js";
|
|
4
|
+
//#region src/server/app-mounted-layouts.ts
|
|
5
|
+
/**
|
|
6
|
+
* A client navigation names the layouts it already holds, so a render that's
|
|
7
|
+
* never stored can leave them out, as Next.js leaves out the segments above
|
|
8
|
+
* where a navigation diverges from its router state tree.
|
|
9
|
+
*
|
|
10
|
+
* Each entry hashes a layout's segment identity, which binds the layout to its
|
|
11
|
+
* route prefix and that prefix's params, so a layout whose params changed never
|
|
12
|
+
* matches.
|
|
13
|
+
*/
|
|
14
|
+
const MAX_MOUNTED_LAYOUTS = 64;
|
|
15
|
+
const MOUNTED_LAYOUT_HASH = /^[0-9a-f]{16}$/;
|
|
16
|
+
function hashMountedLayoutIdentity(identity) {
|
|
17
|
+
return fnv1a64(identity);
|
|
18
|
+
}
|
|
19
|
+
function serializeMountedLayouts(identities) {
|
|
20
|
+
if (identities.length === 0) return null;
|
|
21
|
+
return identities.slice(0, MAX_MOUNTED_LAYOUTS).map(hashMountedLayoutIdentity).join(",");
|
|
22
|
+
}
|
|
23
|
+
function parseMountedLayoutsHeader(value) {
|
|
24
|
+
if (!value) return null;
|
|
25
|
+
const hashes = /* @__PURE__ */ new Set();
|
|
26
|
+
for (const entry of value.split(",", 65)) {
|
|
27
|
+
const hash = entry.trim();
|
|
28
|
+
if (!MOUNTED_LAYOUT_HASH.test(hash)) return null;
|
|
29
|
+
hashes.add(hash);
|
|
30
|
+
}
|
|
31
|
+
if (hashes.size === 0 || hashes.size > MAX_MOUNTED_LAYOUTS) return null;
|
|
32
|
+
return hashes;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The header for the outermost layouts a client state holds. Only that prefix
|
|
36
|
+
* can be left out of a render, as a layout below one that re-renders renders
|
|
37
|
+
* inside it.
|
|
38
|
+
*/
|
|
39
|
+
function createMountedLayoutsHeader(elements, layoutIds) {
|
|
40
|
+
const identities = AppElementsWire.readMetadata(elements).bfcacheSegmentIdentities;
|
|
41
|
+
const held = [];
|
|
42
|
+
for (const layoutId of layoutIds) {
|
|
43
|
+
const identity = identities[layoutId];
|
|
44
|
+
if (identity === void 0 || !Object.hasOwn(elements, layoutId)) break;
|
|
45
|
+
held.push(identity);
|
|
46
|
+
}
|
|
47
|
+
return serializeMountedLayouts(held);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Whether a client state still holds, unchanged, every layout a payload left
|
|
51
|
+
* out. A navigation that started from another state, or a payload stored for
|
|
52
|
+
* another client, can name layouts this one doesn't hold.
|
|
53
|
+
*/
|
|
54
|
+
function holdsSkippedLayouts(current, next) {
|
|
55
|
+
const nextMetadata = AppElementsWire.readMetadata(next);
|
|
56
|
+
if (nextMetadata.skippedLayoutIds.length === 0) return true;
|
|
57
|
+
const currentIdentities = AppElementsWire.readMetadata(current.elements).bfcacheSegmentIdentities;
|
|
58
|
+
const currentLayoutIds = new Set(current.layoutIds);
|
|
59
|
+
for (const layoutId of nextMetadata.skippedLayoutIds) {
|
|
60
|
+
if (!currentLayoutIds.has(layoutId) || !Object.hasOwn(current.elements, layoutId)) return false;
|
|
61
|
+
const identity = nextMetadata.bfcacheSegmentIdentities[layoutId];
|
|
62
|
+
if (identity === void 0 || identity !== currentIdentities[layoutId]) return false;
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { createMountedLayoutsHeader, hashMountedLayoutIdentity, holdsSkippedLayouts, parseMountedLayoutsHeader };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BrowserRouteManifest, BrowserRouteManifestRoute } from "../routing/browser-route-manifest.js";
|
|
2
|
-
import { OptimisticRouteTrieMatch } from "../routing/optimistic-route-trie.js";
|
|
3
2
|
import { AppElements } from "./app-elements-wire.js";
|
|
4
3
|
import "./app-elements.js";
|
|
4
|
+
import { OptimisticRouteTrieMatch } from "../routing/optimistic-route-trie.js";
|
|
5
5
|
//#region src/server/app-optimistic-routing.d.ts
|
|
6
6
|
type OptimisticRouteMatch = OptimisticRouteTrieMatch<BrowserRouteManifestRoute>;
|
|
7
7
|
export type OptimisticRouteTemplate = {
|
|
@@ -90,5 +90,23 @@ export declare function resolveOptimisticNavigationPayload(options: {
|
|
|
90
90
|
routeManifest: BrowserRouteManifest;
|
|
91
91
|
templates: ReadonlyMap<string, OptimisticRouteTemplate>;
|
|
92
92
|
}): OptimisticNavigationPayload | null;
|
|
93
|
+
export type LearnedOptimisticRouteTemplate = {
|
|
94
|
+
key: string;
|
|
95
|
+
template: OptimisticRouteTemplate;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Optimistic route templates and the prefetch sources they were learned from.
|
|
99
|
+
* `clear()` retires every template, so none can outlive the prefetch payload
|
|
100
|
+
* it was derived from, and drops any result a learning started before the
|
|
101
|
+
* clear resolves to. Sources that are still cached are learned again on the
|
|
102
|
+
* next optimistic navigation.
|
|
103
|
+
*/
|
|
104
|
+
export declare function createOptimisticRouteTemplateStore(): {
|
|
105
|
+
templates: ReadonlyMap<string, OptimisticRouteTemplate>;
|
|
106
|
+
clear(): void;
|
|
107
|
+
hasSource(sourceKey: string): boolean;
|
|
108
|
+
learn(sourceKey: string, learnTemplate: () => Promise<LearnedOptimisticRouteTemplate | null>): Promise<void>;
|
|
109
|
+
pendingLearning(): Promise<void>[];
|
|
110
|
+
};
|
|
93
111
|
//#endregion
|
|
94
112
|
export {};
|
|
@@ -3,10 +3,10 @@ import { stripBasePath } from "../utils/base-path.js";
|
|
|
3
3
|
import { decodeMatchedParams, splitPathnameForRouteMatch } from "../routing/utils.js";
|
|
4
4
|
import { extractRawRoutePatternParams, matchRoutePattern } from "../routing/route-pattern.js";
|
|
5
5
|
import { buildOptimisticRouteTrie, matchOptimisticRouteTrie } from "../routing/optimistic-route-trie.js";
|
|
6
|
+
import { stripRscCacheBustingSearchParam } from "./app-rsc-cache-busting.js";
|
|
6
7
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
7
8
|
import "./app-elements.js";
|
|
8
9
|
import { createNestedBfcacheSlotSegmentId, deriveBfcacheSegmentIdentity, isNestedBfcacheSlotSegmentId } from "./bfcache-identity.js";
|
|
9
|
-
import { stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
|
|
10
10
|
import { canonicalizeAppPageParams, resolveAppPagePatternStateKey, resolveAppPageSemanticSegmentStateKey } from "./app-page-segment-state.js";
|
|
11
11
|
import { Suspense, createElement, isValidElement } from "react";
|
|
12
12
|
//#region src/server/app-optimistic-routing.ts
|
|
@@ -36,8 +36,7 @@ function hrefToRouteParts(href, basePath) {
|
|
|
36
36
|
return null;
|
|
37
37
|
}
|
|
38
38
|
stripRscCacheBustingSearchParam(url);
|
|
39
|
-
const
|
|
40
|
-
const appPathname = stripBasePath(withoutRscSuffix, basePath);
|
|
39
|
+
const appPathname = stripBasePath(url.pathname, basePath);
|
|
41
40
|
const pathname = appPathname === "" ? "/" : appPathname;
|
|
42
41
|
return {
|
|
43
42
|
normalized: splitPathnameForRouteMatch(pathname),
|
|
@@ -310,5 +309,45 @@ function resolveOptimisticNavigationPayload(options) {
|
|
|
310
309
|
urlParts: urlParts.normalized
|
|
311
310
|
};
|
|
312
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* Optimistic route templates and the prefetch sources they were learned from.
|
|
314
|
+
* `clear()` retires every template, so none can outlive the prefetch payload
|
|
315
|
+
* it was derived from, and drops any result a learning started before the
|
|
316
|
+
* clear resolves to. Sources that are still cached are learned again on the
|
|
317
|
+
* next optimistic navigation.
|
|
318
|
+
*/
|
|
319
|
+
function createOptimisticRouteTemplateStore() {
|
|
320
|
+
const templates = /* @__PURE__ */ new Map();
|
|
321
|
+
const learnedSources = /* @__PURE__ */ new Set();
|
|
322
|
+
const learning = /* @__PURE__ */ new Map();
|
|
323
|
+
let generation = 0;
|
|
324
|
+
return {
|
|
325
|
+
templates,
|
|
326
|
+
clear() {
|
|
327
|
+
generation += 1;
|
|
328
|
+
templates.clear();
|
|
329
|
+
learnedSources.clear();
|
|
330
|
+
learning.clear();
|
|
331
|
+
},
|
|
332
|
+
hasSource(sourceKey) {
|
|
333
|
+
return learnedSources.has(sourceKey) || learning.has(sourceKey);
|
|
334
|
+
},
|
|
335
|
+
learn(sourceKey, learnTemplate) {
|
|
336
|
+
const learnedGeneration = generation;
|
|
337
|
+
const promise = learnTemplate().then((learned) => {
|
|
338
|
+
if (learned === null || learnedGeneration !== generation) return;
|
|
339
|
+
templates.set(learned.key, learned.template);
|
|
340
|
+
learnedSources.add(sourceKey);
|
|
341
|
+
}).finally(() => {
|
|
342
|
+
if (learning.get(sourceKey) === promise) learning.delete(sourceKey);
|
|
343
|
+
});
|
|
344
|
+
learning.set(sourceKey, promise);
|
|
345
|
+
return promise;
|
|
346
|
+
},
|
|
347
|
+
pendingLearning() {
|
|
348
|
+
return [...learning.values()];
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
}
|
|
313
352
|
//#endregion
|
|
314
|
-
export { canCommitOptimisticRouteTemplate, createOptimisticRouteElements, createOptimisticRouteTemplate, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, keepOptimisticStreamingMetadata, matchOptimisticRouteManifestRoute, resolveOptimisticNavigationParamsForHref, resolveOptimisticNavigationPayload };
|
|
353
|
+
export { canCommitOptimisticRouteTemplate, createOptimisticRouteElements, createOptimisticRouteTemplate, createOptimisticRouteTemplateStore, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, keepOptimisticStreamingMetadata, matchOptimisticRouteManifestRoute, resolveOptimisticNavigationParamsForHref, resolveOptimisticNavigationPayload };
|
|
@@ -2,26 +2,25 @@ import { stripBasePath } from "../utils/base-path.js";
|
|
|
2
2
|
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
3
3
|
import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders } from "./cache-control.js";
|
|
4
4
|
import { isRenderDynamicLatched, isStaticGenerationAccessError } from "../shims/internal/headers-state.js";
|
|
5
|
+
import { copyLinkHeaderProvenance } from "./app-response-header-provenance.js";
|
|
5
6
|
import { createArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
|
|
6
7
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
7
8
|
import "./app-elements.js";
|
|
8
9
|
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
9
10
|
import { ErrorBoundary, GlobalErrorBoundary, SerializedErrorBoundary } from "../shims/error-boundary.js";
|
|
11
|
+
import { rewriteClientHookError } from "../shims/client-hook-error.js";
|
|
10
12
|
import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
|
|
11
13
|
import { withUseCacheLayoutMarker } from "../shims/internal/app-page-props-cache-key.js";
|
|
12
14
|
import { MetadataHead, ViewportHead } from "../shims/metadata.js";
|
|
13
|
-
import { stripRscSuffix } from "./app-rsc-cache-busting.js";
|
|
14
|
-
import { copyLinkHeaderProvenance } from "./app-response-header-provenance.js";
|
|
15
15
|
import { buildRscRedirectFlightStream } from "./app-rsc-redirect-flight.js";
|
|
16
16
|
import { bufferAppPageBinaryStream, buildAppPageSpecialErrorResponse, resolveAppPageSpecialError } from "./app-page-execution.js";
|
|
17
|
-
import { resolveAppPageBranchParams, resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
18
|
-
import { createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageSourcePage } from "./app-page-route-wiring.js";
|
|
19
|
-
import { buildClientHookErrorMessage } from "../shims/client-hook-error.js";
|
|
20
17
|
import { createAppPageMetadataSearchParamsObserver } from "./app-page-search-params-observation.js";
|
|
21
|
-
import {
|
|
18
|
+
import { resolveAppPageBranchParams, resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
19
|
+
import { hasAppPageDynamicMetadata, prepareAppPageHead, resolveActiveParallelRouteHeadInputs, resolveAppPageHead, resolveInterceptLayoutsBesidePage, slotInterceptKeepsSourceHead } from "./app-page-head.js";
|
|
22
20
|
import { renderAppPageBoundaryResponse, resolveAppPageErrorBoundary, resolveAppPageHttpAccessBoundaryModule, wrapAppPageBoundaryElement } from "./app-page-boundary.js";
|
|
23
21
|
import { createRouteNotFoundHeadPlanOptions, recoverAppPageRouteHead, resolveHttpAccessFallbackMetadata, resolveHttpAccessFallbackViewport } from "./app-page-http-access-fallback-metadata.js";
|
|
24
22
|
import "./app-rsc-route-matching.js";
|
|
23
|
+
import { createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageSourcePage } from "./app-page-route-wiring.js";
|
|
25
24
|
import { resolveSlotParamOverrides } from "./app-page-element-builder.js";
|
|
26
25
|
import { createAppPageFontData, createAppPageRscErrorTracker, createAppPageSsrErrorHandler, renderAppPageHtmlResponse } from "./app-page-stream.js";
|
|
27
26
|
import { Fragment, Suspense, createElement } from "react";
|
|
@@ -258,7 +257,7 @@ async function renderAppPageHttpAccessFallback(options) {
|
|
|
258
257
|
if (!boundaryComponent) return null;
|
|
259
258
|
const layoutModules = options.layoutModules ?? options.route?.layouts ?? options.rootLayouts;
|
|
260
259
|
const pathname = new URL(options.requestUrl).pathname;
|
|
261
|
-
const routePathname = options.routePathname ??
|
|
260
|
+
const routePathname = options.routePathname ?? stripBasePath(pathname, options.basePath ?? "");
|
|
262
261
|
const headBoundaryModule = options.headBoundaryModule ?? boundaryModule;
|
|
263
262
|
const headLayoutModules = options.headLayoutModules ?? layoutModules;
|
|
264
263
|
const routeSegments = resolveHttpAccessFallbackHeadRouteSegments(options.route, headLayoutModules);
|
|
@@ -301,6 +300,7 @@ async function renderAppPageHttpAccessFallback(options) {
|
|
|
301
300
|
head: {
|
|
302
301
|
layoutModules: intercept?.interceptLayouts ?? [],
|
|
303
302
|
layoutParams: (intercept?.interceptLayoutSegments ?? []).map((layoutSegments) => resolveAppPageBranchParams(intercept?.interceptBranchSegments ?? layoutSegments, layoutSegments.length, effectiveParams, layoutSegments)),
|
|
303
|
+
layoutsBesidePage: resolveInterceptLayoutsBesidePage(intercept?.interceptLayoutSegments, intercept?.interceptBranchSegments),
|
|
304
304
|
pageModule: intercept?.interceptPage ?? null,
|
|
305
305
|
params: effectiveParams,
|
|
306
306
|
routeSegments: intercept?.interceptSourcePageSegments ?? segments
|
|
@@ -611,6 +611,7 @@ async function renderAppPageErrorBoundary(options) {
|
|
|
611
611
|
skipLayoutWrapping: errorBoundary.isGlobalError
|
|
612
612
|
});
|
|
613
613
|
};
|
|
614
|
+
const isErrorStatus = errorBoundary.isGlobalError || !options.isRscRequest;
|
|
614
615
|
const renderWith = async (BoundaryComponent) => {
|
|
615
616
|
const response = await renderAppPageBoundaryElementResponse({
|
|
616
617
|
...options,
|
|
@@ -620,9 +621,9 @@ async function renderAppPageErrorBoundary(options) {
|
|
|
620
621
|
navigationParams: matchedParams,
|
|
621
622
|
route: options.route,
|
|
622
623
|
routePattern: options.route?.pattern,
|
|
623
|
-
status:
|
|
624
|
+
status: isErrorStatus ? 500 : 200
|
|
624
625
|
});
|
|
625
|
-
if (
|
|
626
|
+
if (isErrorStatus) applyCdnResponseHeaders(response.headers, { cacheControl: NEVER_CACHE_CONTROL });
|
|
626
627
|
return response;
|
|
627
628
|
};
|
|
628
629
|
try {
|
|
@@ -635,10 +636,5 @@ async function renderAppPageErrorBoundary(options) {
|
|
|
635
636
|
throw renderError;
|
|
636
637
|
}
|
|
637
638
|
}
|
|
638
|
-
const _clientHookPattern = /\b(useState|useEffect|useReducer|useRef|useContext|useLayoutEffect|useInsertionEffect|useSyncExternalStore|useTransition|useImperativeHandle|useDeferredValue|useActionState|useOptimistic|useEffectEvent)\b.*is not a function/;
|
|
639
|
-
function rewriteClientHookError(error) {
|
|
640
|
-
const match = error.message.match(_clientHookPattern);
|
|
641
|
-
if (match) error.message = buildClientHookErrorMessage(`${match[1]}()`);
|
|
642
|
-
}
|
|
643
639
|
//#endregion
|
|
644
640
|
export { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
|
|
2
2
|
import { runWithFetchDedupe } from "../shims/fetch-cache.js";
|
|
3
|
-
import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
|
|
4
3
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
4
|
+
import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
|
|
5
|
+
import { isAppPageRouteGroupSegment } from "./app-page-segment-state.js";
|
|
5
6
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
6
7
|
import { resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
7
|
-
import { isAppPageRouteGroupSegment } from "./app-page-segment-state.js";
|
|
8
8
|
//#region src/server/app-page-boundary.ts
|
|
9
9
|
function resolveAppPageHttpAccessBoundaryComponent(options) {
|
|
10
10
|
return options.getDefaultExport(resolveAppPageHttpAccessBoundaryModule({
|
|
@@ -2,6 +2,7 @@ import { RenderObservation } from "./cache-proof.js";
|
|
|
2
2
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
3
3
|
import { AppPageRenderObservationState } from "./app-page-render-observation.js";
|
|
4
4
|
import { AppPageCacheSetter } from "./isr-cache.js";
|
|
5
|
+
import { CdnAppPageDocument } from "../shims/cdn-cache.js";
|
|
5
6
|
import { AppPageRscRenderStatus } from "./app-page-rsc-render-status.js";
|
|
6
7
|
//#region src/server/app-page-cache-finalizer.d.ts
|
|
7
8
|
type AppPageDebugLogger = (event: string, detail: string) => void;
|
|
@@ -30,6 +31,8 @@ type FinalizeAppPageCacheabilityEvaluationOptions = {
|
|
|
30
31
|
/** An RSC render's status, from its document's shell. */
|
|
31
32
|
resolveRscRenderStatus?: () => Promise<AppPageRscRenderStatus>;
|
|
32
33
|
revalidateSeconds: number | null;
|
|
34
|
+
/** Hands the CDN adapter the page's document to store beside the response. */
|
|
35
|
+
captureAdmittedDocument?: (document: CdnAppPageDocument | null) => void;
|
|
33
36
|
};
|
|
34
37
|
type FinalizeAppPageHtmlCacheResponseOptions = {
|
|
35
38
|
bypassInterceptionContextCache?: boolean;
|
|
@@ -66,15 +69,20 @@ type FinalizeAppPageHtmlCacheResponseOptions = {
|
|
|
66
69
|
};
|
|
67
70
|
type ScheduleAppPageRscCacheWriteOptions = {
|
|
68
71
|
bypassInterceptionContextCache?: boolean;
|
|
72
|
+
/** Hands the CDN adapter the page's document to store beside the response. */
|
|
73
|
+
captureAdmittedDocument?: (document: CdnAppPageDocument | null) => void;
|
|
69
74
|
capturedRscDataPromise: Promise<ArrayBuffer> | null;
|
|
70
75
|
cleanPathname: string;
|
|
71
76
|
consumeDynamicUsage: () => boolean;
|
|
72
77
|
consumeRenderObservationState?: () => AppPageRenderObservationState;
|
|
78
|
+
/** Observes the document the render's status resolution rendered, if any. */
|
|
79
|
+
createHtmlRenderObservation?: BuildAppPageCacheRenderObservation;
|
|
73
80
|
createRscRenderObservation: BuildAppPageCacheRenderObservation;
|
|
74
81
|
dynamicUsedDuringBuild: boolean;
|
|
75
82
|
getPageTags: () => string[];
|
|
76
83
|
getRequestCacheLife?: () => AppPageRequestCacheLife | null;
|
|
77
84
|
isrDebug?: AppPageDebugLogger;
|
|
85
|
+
isrHtmlKey?: (pathname: string) => string;
|
|
78
86
|
isrRscKey: AppPageRscCacheKeyBuilder;
|
|
79
87
|
isrSet: AppPageCacheSetter;
|
|
80
88
|
interceptionContext?: string | null;
|
|
@@ -82,7 +90,10 @@ type ScheduleAppPageRscCacheWriteOptions = {
|
|
|
82
90
|
mountedSlotsHeader?: string | null;
|
|
83
91
|
omitPendingDynamicCacheState?: boolean;
|
|
84
92
|
renderMode?: AppRscRenderMode;
|
|
85
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* The render's status, from its document's shell, and the page's document
|
|
95
|
+
* when it rendered one to store. Without it the render is a 200.
|
|
96
|
+
*/
|
|
86
97
|
resolveRscRenderStatus?: () => Promise<AppPageRscRenderStatus>;
|
|
87
98
|
preserveClientResponseHeaders?: boolean;
|
|
88
99
|
expireSeconds?: number;
|