vinext 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +1 -1
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +1 -1
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay.js +1 -1
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/next-config.d.ts +19 -0
- package/dist/config/next-config.js +64 -1
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
- package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
- package/dist/entries/app-rsc-entry.js +17 -48
- package/dist/entries/app-rsc-manifest.js +3 -4
- package/dist/entries/app-ssr-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +33 -8
- package/dist/index.js +83 -70
- package/dist/init-cloudflare.d.ts +1 -3
- package/dist/init-cloudflare.js +10 -48
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +4 -0
- package/dist/plugins/extensionless-dynamic-import.js +6 -2
- package/dist/plugins/next-intl-catalog.d.ts +12 -0
- package/dist/plugins/next-intl-catalog.js +85 -0
- package/dist/plugins/pages-node-externals.d.ts +1 -0
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/use-cache-callable.d.ts +1 -1
- package/dist/plugins/use-cache-callable.js +136 -94
- package/dist/routing/app-route-graph.d.ts +6 -0
- package/dist/routing/app-route-graph.js +9 -1
- package/dist/server/api-handler.js +19 -4
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +79 -63
- package/dist/server/app-browser-history-controller.d.ts +5 -4
- package/dist/server/app-browser-history-controller.js +93 -15
- package/dist/server/app-browser-navigation-controller.d.ts +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -2
- package/dist/server/app-browser-rsc-redirect.js +4 -4
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +4 -3
- package/dist/server/app-browser-state.d.ts +2 -4
- package/dist/server/app-browser-state.js +9 -4
- package/dist/server/app-browser-supplemental-refresh.js +16 -1
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-browser-visible-commit.js +2 -12
- package/dist/server/app-elements-wire.d.ts +6 -38
- package/dist/server/app-elements-wire.js +4 -41
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-history-state.d.ts +2 -2
- package/dist/server/app-history-state.js +5 -2
- package/dist/server/app-mounted-layouts.d.ts +21 -0
- package/dist/server/app-mounted-layouts.js +67 -0
- package/dist/server/app-optimistic-routing.d.ts +19 -1
- package/dist/server/app-optimistic-routing.js +42 -2
- package/dist/server/app-page-boundary-render.js +7 -6
- package/dist/server/app-page-boundary.js +2 -2
- package/dist/server/app-page-cache-finalizer.d.ts +12 -1
- package/dist/server/app-page-cache-finalizer.js +70 -29
- package/dist/server/app-page-cache.d.ts +13 -1
- package/dist/server/app-page-cache.js +31 -9
- package/dist/server/app-page-dispatch.d.ts +5 -10
- package/dist/server/app-page-dispatch.js +84 -154
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +10 -9
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +99 -95
- package/dist/server/app-page-head.d.ts +13 -0
- package/dist/server/app-page-head.js +44 -16
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
- package/dist/server/app-page-layout-gate.d.ts +35 -0
- package/dist/server/app-page-layout-gate.js +50 -0
- package/dist/server/app-page-params.d.ts +0 -1
- package/dist/server/app-page-params.js +1 -14
- package/dist/server/app-page-probe.d.ts +3 -21
- package/dist/server/app-page-probe.js +4 -37
- package/dist/server/app-page-render.d.ts +2 -12
- package/dist/server/app-page-render.js +89 -220
- package/dist/server/app-page-request.d.ts +1 -3
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-response.js +3 -3
- package/dist/server/app-page-route-wiring.d.ts +13 -6
- package/dist/server/app-page-route-wiring.js +67 -61
- package/dist/server/app-page-rsc-render-status.d.ts +27 -1
- package/dist/server/app-page-rsc-render-status.js +121 -13
- package/dist/server/app-page-stream.d.ts +2 -0
- package/dist/server/app-page-stream.js +2 -2
- package/dist/server/app-pages-bridge.d.ts +4 -0
- package/dist/server/app-pages-bridge.js +7 -3
- package/dist/server/app-render-dependency.d.ts +11 -4
- package/dist/server/app-render-dependency.js +86 -38
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-route-handler-cache.js +2 -2
- package/dist/server/app-route-handler-dispatch.js +14 -9
- package/dist/server/app-route-handler-execution.js +8 -3
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-handler-runtime.js +17 -4
- package/dist/server/app-rsc-cache-busting.d.ts +2 -2
- package/dist/server/app-rsc-cache-busting.js +4 -4
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +9 -1
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +8 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +30 -24
- package/dist/server/app-rsc-request-normalization.d.ts +0 -4
- package/dist/server/app-rsc-request-normalization.js +1 -4
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +5 -3
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +7 -4
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +9 -8
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/app-visited-response-cache.d.ts +36 -1
- package/dist/server/app-visited-response-cache.js +46 -5
- package/dist/server/app-worker-stages.d.ts +25 -3
- package/dist/server/app-worker-stages.js +45 -6
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-server.js +4 -3
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +26 -1
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/multi-stage.d.ts +52 -11
- package/dist/server/multi-stage.js +13 -1
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/pages-api-route.js +28 -19
- package/dist/server/pages-media-type.d.ts +21 -1
- package/dist/server/pages-media-type.js +69 -5
- package/dist/server/pages-node-compat.js +52 -27
- package/dist/server/pages-page-handler.js +11 -20
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +2 -2
- package/dist/server/pages-request-stage-entry.js +14 -12
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/prod-server.js +5 -1
- package/dist/server/request-pipeline.d.ts +6 -0
- package/dist/server/request-pipeline.js +21 -1
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- package/dist/server/worker-stages.d.ts +16 -3
- package/dist/server/worker-stages.js +23 -4
- package/dist/shims/cache-handler.js +2 -2
- package/dist/shims/cache-request-state.d.ts +17 -20
- package/dist/shims/cache-request-state.js +16 -21
- package/dist/shims/cache-runtime.js +27 -11
- package/dist/shims/cache.d.ts +8 -7
- package/dist/shims/cache.js +17 -19
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- package/dist/shims/client-page-root.js +2 -2
- package/dist/shims/dynamic.js +9 -6
- package/dist/shims/error-boundary.js +2 -2
- package/dist/shims/fetch-cache-state.d.ts +5 -1
- package/dist/shims/fetch-cache-state.js +1 -3
- package/dist/shims/fetch-cache.d.ts +2 -1
- package/dist/shims/fetch-cache.js +34 -24
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +8 -23
- package/dist/shims/headers.js +17 -67
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +3 -1
- package/dist/shims/metadata.d.ts +23 -21
- package/dist/shims/metadata.js +62 -24
- package/dist/shims/navigation-server.js +1 -1
- package/dist/shims/navigation.d.ts +74 -7
- package/dist/shims/navigation.js +183 -29
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +2 -2
- package/dist/shims/slot.d.ts +12 -0
- package/dist/shims/slot.js +37 -9
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +2 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- package/dist/utils/project.d.ts +2 -2
- package/dist/utils/project.js +3 -16
- package/dist/utils/regex.d.ts +5 -0
- package/dist/utils/regex.js +11 -1
- package/dist/utils/text-stream.d.ts +10 -5
- package/dist/utils/text-stream.js +6 -6
- package/package.json +2 -1
- package/dist/build/layout-classification-types.d.ts +0 -60
- package/dist/build/layout-classification-types.js +0 -1
- package/dist/build/layout-classification.d.ts +0 -62
- package/dist/build/layout-classification.js +0 -98
- package/dist/build/route-classification-injector.d.ts +0 -33
- package/dist/build/route-classification-injector.js +0 -59
- package/dist/build/route-classification-manifest.d.ts +0 -54
- package/dist/build/route-classification-manifest.js +0 -143
- package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
- package/dist/server/app-browser-client-reuse-manifest.js +0 -101
- package/dist/server/app-layout-param-observation.d.ts +0 -42
- package/dist/server/app-layout-param-observation.js +0 -168
- package/dist/server/client-reuse-manifest.d.ts +0 -103
- package/dist/server/client-reuse-manifest.js +0 -209
- package/dist/server/skip-cache-proof.d.ts +0 -60
- package/dist/server/skip-cache-proof.js +0 -168
- package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
- package/dist/server/static-layout-client-reuse-proof.js +0 -33
- package/dist/utils/sorted-array.d.ts +0 -8
- package/dist/utils/sorted-array.js +0 -20
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { stripBasePath } from "../utils/base-path.js";
|
|
2
2
|
import { withBasePath } from "../shims/url-utils.js";
|
|
3
3
|
import { clearAppNavigationFailureTarget, getAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
|
|
4
|
-
import { claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
5
4
|
import { resolveServerActionOperationLane, shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
|
|
6
5
|
import { resolveActiveRoutePaths } from "./app-history-state.js";
|
|
6
|
+
import { claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
7
7
|
import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
8
8
|
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, createPendingNavigationCommit, createPendingNavigationCommitFromElements } from "./app-browser-state.js";
|
|
9
9
|
import { applyApprovedVisibleCommit, approveHmrVisibleCommit, approvePendingNavigationCommit, resolveAndClassifyNavigationCommit } from "./app-browser-visible-commit.js";
|
|
@@ -408,7 +408,6 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
408
408
|
elements: options.restoredState.elements,
|
|
409
409
|
interception: options.restoredState.interception,
|
|
410
410
|
interceptionContext: options.restoredState.interceptionContext,
|
|
411
|
-
layoutFlags: options.restoredState.layoutFlags,
|
|
412
411
|
layoutIds: options.restoredState.layoutIds,
|
|
413
412
|
navigationSnapshot: options.restoredState.navigationSnapshot,
|
|
414
413
|
operation,
|
|
@@ -13,8 +13,7 @@ function toVisibleAppHref(href, origin) {
|
|
|
13
13
|
stripRscCacheBustingSearchParam(url);
|
|
14
14
|
return `${stripRscSuffix(url.pathname)}${url.search}${url.hash}`;
|
|
15
15
|
}
|
|
16
|
-
function toStreamedRedirectVisibleAppHref(
|
|
17
|
-
const url = new URL(href, origin);
|
|
16
|
+
function toStreamedRedirectVisibleAppHref(url) {
|
|
18
17
|
return `${url.pathname}${url.search}${url.hash}`;
|
|
19
18
|
}
|
|
20
19
|
function resolveRedirectLifecycleHopFromTarget(options) {
|
|
@@ -53,10 +52,11 @@ function resolveRscRedirectLifecycleHop(options) {
|
|
|
53
52
|
});
|
|
54
53
|
}
|
|
55
54
|
function resolveStreamedRscRedirectLifecycleHop(options) {
|
|
56
|
-
const
|
|
55
|
+
const requestedUrl = new URL(options.currentHref, options.origin);
|
|
56
|
+
const streamedRedirectUrl = new URL(options.streamedRedirectTarget, requestedUrl);
|
|
57
57
|
return resolveRedirectLifecycleHopFromTarget({
|
|
58
58
|
...options,
|
|
59
|
-
redirectedHref: toStreamedRedirectVisibleAppHref(
|
|
59
|
+
redirectedHref: toStreamedRedirectVisibleAppHref(streamedRedirectUrl),
|
|
60
60
|
targetUrl: streamedRedirectUrl
|
|
61
61
|
});
|
|
62
62
|
}
|
|
@@ -21,6 +21,8 @@ type ActionRedirectTarget = {
|
|
|
21
21
|
export type ClientServerActionDeps = {
|
|
22
22
|
basePath: string;
|
|
23
23
|
clearClientNavigationCaches(): void;
|
|
24
|
+
/** Evict only the cached navigation data that may be dynamic. */
|
|
25
|
+
clearDynamicClientNavigationCaches(): void;
|
|
24
26
|
clientRscCompatibilityId: string | null;
|
|
25
27
|
commitSameUrlNavigatePayload(elements: Promise<AppElements>, actionInitiation: ClientServerActionInitiation, returnValue: ServerActionResult["returnValue"] | undefined, revalidation: ServerActionRevalidationKind, renderedPathAndSearch: string | null): Promise<unknown>;
|
|
26
28
|
navigationPlanner: typeof navigationPlanner;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { hasBasePath } from "../utils/base-path.js";
|
|
2
2
|
import { ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
|
|
3
3
|
import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
|
|
4
|
-
import { AppElementsWire } from "./app-elements-wire.js";
|
|
5
|
-
import "./app-elements.js";
|
|
6
4
|
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createServerActionRequestUrl } from "./app-rsc-cache-busting.js";
|
|
7
5
|
import { throwOnServerActionNotFound } from "./server-action-not-found.js";
|
|
6
|
+
import { AppElementsWire } from "./app-elements-wire.js";
|
|
7
|
+
import "./app-elements.js";
|
|
8
8
|
import { createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult, shouldSyncServerActionHttpFallbackHead } from "./app-browser-action-result.js";
|
|
9
9
|
import { parseRenderedPathAndSearchHeader } from "../shims/navigation.js";
|
|
10
10
|
import { resolveServerActionRequestState } from "./app-browser-state.js";
|
|
@@ -89,7 +89,8 @@ async function invokeClientServerAction(id, args, actionInitiation, deps) {
|
|
|
89
89
|
const actionResultDecision = deps.navigationPlanner.classifyServerActionResult(actionResultFacts);
|
|
90
90
|
if (applyServerActionResultDecision(actionResultDecision, () => deps.clearClientNavigationCaches(), (url, historyMode) => deps.performHardNavigation(url, historyMode))) return;
|
|
91
91
|
const revalidation = parseServerActionRevalidationHeader(fetchResponse.headers);
|
|
92
|
-
if (revalidation
|
|
92
|
+
if (revalidation === "staticAndDynamic") deps.clearClientNavigationCaches();
|
|
93
|
+
else if (revalidation === "dynamicOnly") deps.clearDynamicClientNavigationCaches();
|
|
93
94
|
const invalidResponseError = await readInvalidServerActionResponseError(fetchResponse.clone(), actionRedirectTarget !== null);
|
|
94
95
|
if (invalidResponseError) throw invalidResponseError;
|
|
95
96
|
if (actionRedirectTarget && !fetchResponseIsRsc) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { BrowserRouteManifest } from "../routing/browser-route-manifest.js";
|
|
2
2
|
import { CacheEntryReuseProof } from "./cache-proof.js";
|
|
3
|
-
import { AppElements, AppElementsInterception, AppElementsSlotBinding
|
|
3
|
+
import { AppElements, AppElementsInterception, AppElementsSlotBinding } from "./app-elements-wire.js";
|
|
4
4
|
import "./app-elements.js";
|
|
5
|
+
import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
5
6
|
import { NavigationTrace } from "./navigation-trace.js";
|
|
6
7
|
import { OperationLane } from "./operation-token.js";
|
|
7
8
|
import "./navigation-planner.js";
|
|
8
9
|
import { BfcacheIdMap, HistoryTraversalIntent, createAppOwnedHistoryState, createExternalHistoryStatePreservingMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createHistoryStateWithTreeSnapshotId, isExternalHistoryState, isHistoryStateBfcacheVersionCurrent, readHistoryStateActiveRoutePaths, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveActiveRoutePaths, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
9
10
|
import { createBfcacheSegmentIdentityMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
10
|
-
import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
11
11
|
//#region src/server/app-browser-state.d.ts
|
|
12
12
|
type OperationRecordBase = {
|
|
13
13
|
id: number;
|
|
@@ -30,7 +30,6 @@ export type AppRouterState = {
|
|
|
30
30
|
elements: AppElements;
|
|
31
31
|
interception: AppElementsInterception | null;
|
|
32
32
|
interceptionContext: string | null;
|
|
33
|
-
layoutFlags: LayoutFlags;
|
|
34
33
|
layoutIds: readonly string[];
|
|
35
34
|
previousNextUrl: string | null;
|
|
36
35
|
renderId: number;
|
|
@@ -46,7 +45,6 @@ export type AppRouterAction = {
|
|
|
46
45
|
elements: AppElements;
|
|
47
46
|
interception: AppElementsInterception | null;
|
|
48
47
|
interceptionContext: string | null;
|
|
49
|
-
layoutFlags: LayoutFlags;
|
|
50
48
|
layoutIds: readonly string[];
|
|
51
49
|
navigationSnapshot: ClientNavigationRenderSnapshot;
|
|
52
50
|
operation: PendingOperationRecord;
|
|
@@ -3,17 +3,18 @@ import { VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER } from
|
|
|
3
3
|
import { NEXT_ACTION_HEADER, RSC_ACTION_HEADER } from "./headers.js";
|
|
4
4
|
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
5
5
|
import { normalizePath } from "./normalize-path.js";
|
|
6
|
+
import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
|
|
6
7
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
7
8
|
import { getMountedSlotIds, getMountedSlotIdsHeader } from "./app-elements.js";
|
|
8
|
-
import { bindAppElementsRenderedSearch } from "../shims/slot.js";
|
|
9
|
-
import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
|
|
10
9
|
import { createBfcacheSegmentIdentityMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
11
|
-
import { createCacheEntryReuseProof } from "./cache-proof.js";
|
|
12
10
|
import { createAppOwnedHistoryState, createExternalHistoryStatePreservingMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createHistoryStateWithTreeSnapshotId, isExternalHistoryState, isHistoryStateBfcacheVersionCurrent, readHistoryStateActiveRoutePaths, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveActiveRoutePaths, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
13
11
|
import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
|
|
14
12
|
import { verifyOperationTokenForCommit } from "./operation-token.js";
|
|
15
13
|
import { navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts } from "./navigation-planner.js";
|
|
16
14
|
import { createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
15
|
+
import { holdsSkippedLayouts } from "./app-mounted-layouts.js";
|
|
16
|
+
import { createCacheEntryReuseProof } from "./cache-proof.js";
|
|
17
|
+
import { bindAppElementsRenderedSearch } from "../shims/slot.js";
|
|
17
18
|
//#region src/server/app-browser-state.ts
|
|
18
19
|
const COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "committed-cache" };
|
|
19
20
|
const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "fresh" };
|
|
@@ -239,6 +240,11 @@ function mapNavigationDecisionToPendingDisposition(decision) {
|
|
|
239
240
|
function mergeSkippedLayoutPreservation(options) {
|
|
240
241
|
if (options.decision.disposition !== "dispatch") return options.decision;
|
|
241
242
|
if (options.pending.skippedLayoutIds.length === 0) return options.decision;
|
|
243
|
+
if (!holdsSkippedLayouts(options.currentState, options.pending.action.elements)) return {
|
|
244
|
+
disposition: "hard-navigate",
|
|
245
|
+
preserveElementIds: [],
|
|
246
|
+
trace: options.decision.trace
|
|
247
|
+
};
|
|
242
248
|
const currentLayoutIds = new Set(options.currentState.layoutIds);
|
|
243
249
|
const targetLayoutIds = new Set(options.pending.action.layoutIds);
|
|
244
250
|
const preserveElementIds = [...options.decision.preserveElementIds];
|
|
@@ -303,7 +309,6 @@ function createPendingNavigationCommitFromElements(options) {
|
|
|
303
309
|
interception: metadata.interception,
|
|
304
310
|
interceptionContext: metadata.interceptionContext,
|
|
305
311
|
layoutIds: metadata.layoutIds,
|
|
306
|
-
layoutFlags: metadata.layoutFlags,
|
|
307
312
|
slotBindings: metadata.slotBindings,
|
|
308
313
|
navigationSnapshot: options.navigationSnapshot,
|
|
309
314
|
operation: createOperationRecord({
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { addBasePathToPathname, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
|
|
2
2
|
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
3
3
|
import { normalizePath } from "./normalize-path.js";
|
|
4
|
-
import { APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_SLOT_BINDINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
4
|
+
import { APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_SLOT_BINDINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
5
5
|
import "./app-elements.js";
|
|
6
|
+
import { isNestedBfcacheSlotSegmentIdFor } from "./bfcache-identity.js";
|
|
6
7
|
//#region src/server/app-browser-supplemental-refresh.ts
|
|
7
8
|
const SUPPLEMENTAL_REFRESH_TIMEOUT_MS = 1e4;
|
|
8
9
|
var SupplementalRefreshError = class extends Error {
|
|
@@ -67,6 +68,7 @@ function mergeRefreshedParallelSlot(currentElements, refreshedElements) {
|
|
|
67
68
|
[APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(slotBindings, { layoutIds: refreshedMetadata.layoutIds })
|
|
68
69
|
};
|
|
69
70
|
for (const binding of retainedBindings) merged[binding.slotId] = currentElements[binding.slotId];
|
|
71
|
+
copySlotIdentities(merged, refreshedElements, currentElements, retainedBindings.map((binding) => binding.slotId));
|
|
70
72
|
if (promotedBindings.length === 1) merged[promotedBindings[0].slotId] = refreshedElements[refreshedChildrenBindings[0].slotId];
|
|
71
73
|
copyRefreshedBranchElements(merged, currentElements, { overwrite: false });
|
|
72
74
|
return merged;
|
|
@@ -79,6 +81,7 @@ function mergeRefreshedParallelSlot(currentElements, refreshedElements) {
|
|
|
79
81
|
[APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(slotBindings, { layoutIds: currentMetadata.layoutIds })
|
|
80
82
|
};
|
|
81
83
|
for (const binding of refreshedBindings) merged[binding.slotId] = refreshedElements[binding.slotId];
|
|
84
|
+
copySlotIdentities(merged, currentElements, refreshedElements, refreshedBindings.map((binding) => binding.slotId));
|
|
82
85
|
copyRefreshedBranchElements(merged, refreshedElements);
|
|
83
86
|
return merged;
|
|
84
87
|
}
|
|
@@ -93,9 +96,21 @@ function mergeRefreshedParallelSlot(currentElements, refreshedElements) {
|
|
|
93
96
|
[interception.slotId]: refreshedSlot,
|
|
94
97
|
[APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(slotBindings, { layoutIds: currentMetadata.layoutIds })
|
|
95
98
|
};
|
|
99
|
+
copySlotIdentities(merged, currentElements, refreshedElements, [interception.slotId]);
|
|
96
100
|
copyRefreshedBranchElements(merged, refreshedElements);
|
|
97
101
|
return merged;
|
|
98
102
|
}
|
|
103
|
+
function copySlotIdentities(target, baseElements, slotElements, slotIds) {
|
|
104
|
+
const isSlotSegment = (id) => slotIds.some((slotId) => id === slotId || isNestedBfcacheSlotSegmentIdFor(id, slotId));
|
|
105
|
+
const isNestedSegment = (id) => !slotIds.includes(id) && isSlotSegment(id);
|
|
106
|
+
for (const id of Object.keys(baseElements)) if (isNestedSegment(id)) delete target[id];
|
|
107
|
+
for (const [id, element] of Object.entries(slotElements)) if (isNestedSegment(id)) target[id] = element;
|
|
108
|
+
const identities = {};
|
|
109
|
+
for (const [id, identity] of Object.entries(AppElementsWire.readMetadata(baseElements).bfcacheSegmentIdentities)) if (!isSlotSegment(id)) identities[id] = identity;
|
|
110
|
+
for (const [id, identity] of Object.entries(AppElementsWire.readMetadata(slotElements).bfcacheSegmentIdentities)) if (isSlotSegment(id)) identities[id] = identity;
|
|
111
|
+
if (Object.keys(identities).length > 0) target[APP_BFCACHE_SEGMENT_IDENTITIES_KEY] = identities;
|
|
112
|
+
else delete target[APP_BFCACHE_SEGMENT_IDENTITIES_KEY];
|
|
113
|
+
}
|
|
99
114
|
function copyRefreshedBranchElements(target, refreshedElements, options = {}) {
|
|
100
115
|
for (const [elementId, element] of Object.entries(refreshedElements)) {
|
|
101
116
|
const parsed = AppElementsWire.parseElementKey(elementId);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BrowserRouteManifest } from "../routing/browser-route-manifest.js";
|
|
2
2
|
import { AppElements } from "./app-elements-wire.js";
|
|
3
3
|
import "./app-elements.js";
|
|
4
|
+
import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
4
5
|
import { NavigationTrace } from "./navigation-trace.js";
|
|
5
6
|
import { OperationLane } from "./operation-token.js";
|
|
6
|
-
import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
7
7
|
import { AppNavigationPayloadOrigin, AppRouterAction, AppRouterState, PendingNavigationCommit } from "./app-browser-state.js";
|
|
8
8
|
//#region src/server/app-browser-visible-commit.d.ts
|
|
9
9
|
type VisibleCommitDecision = {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
2
2
|
import "./app-elements.js";
|
|
3
|
-
import { mergeElements } from "../shims/slot.js";
|
|
4
|
-
import { resolveAppPageRouteStateKey } from "./app-page-segment-state.js";
|
|
5
3
|
import { createBfcacheSegmentIdentityMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
6
4
|
import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
|
|
5
|
+
import { mergeElements } from "../shims/slot.js";
|
|
7
6
|
import { createPendingNavigationCommit, resolvePendingNavigationCommitDispositionDecision } from "./app-browser-state.js";
|
|
7
|
+
import { resolveAppPageRouteStateKey } from "./app-page-segment-state.js";
|
|
8
8
|
//#region src/server/app-browser-visible-commit.ts
|
|
9
9
|
const approvedVisibleCommitBrand = Symbol("ApprovedVisibleCommit");
|
|
10
10
|
function hasSameServerTemplateSeedIdentity(id, currentSnapshot, nextSnapshot) {
|
|
@@ -105,7 +105,6 @@ function reduceApprovedVisibleCommitState(state, commit) {
|
|
|
105
105
|
elements: mergedElements,
|
|
106
106
|
interception: action.interception,
|
|
107
107
|
interceptionContext: action.interceptionContext,
|
|
108
|
-
layoutFlags: mergeLayoutFlags(state.layoutFlags, action.layoutFlags, preserveElementIds),
|
|
109
108
|
layoutIds: action.layoutIds,
|
|
110
109
|
navigationSnapshot: action.navigationSnapshot,
|
|
111
110
|
previousNextUrl: action.previousNextUrl,
|
|
@@ -145,15 +144,6 @@ function createVisibleCommitDecision(trace = createNavigationTrace(NavigationTra
|
|
|
145
144
|
trace
|
|
146
145
|
};
|
|
147
146
|
}
|
|
148
|
-
function mergeLayoutFlags(previousFlags, nextFlags, preserveElementIds) {
|
|
149
|
-
const merged = { ...nextFlags };
|
|
150
|
-
for (const id of preserveElementIds) {
|
|
151
|
-
if (Object.hasOwn(merged, id)) continue;
|
|
152
|
-
const value = previousFlags[id];
|
|
153
|
-
if (value) merged[id] = value;
|
|
154
|
-
}
|
|
155
|
-
return merged;
|
|
156
|
-
}
|
|
157
147
|
function createApprovedVisibleCommit(options) {
|
|
158
148
|
return {
|
|
159
149
|
[approvedVisibleCommitBrand]: true,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
|
|
2
2
|
import { CacheEntryReuseProof } from "./cache-proof.js";
|
|
3
|
-
import { ClientReuseManifestSkipDisposition } from "./client-reuse-manifest.js";
|
|
4
3
|
import { BfcacheSegmentIdentity } from "./bfcache-identity.js";
|
|
5
4
|
import { compareStrings } from "../utils/compare.js";
|
|
6
5
|
import { AppElementsWireElementKey } from "./app-elements-wire-key.js";
|
|
@@ -12,7 +11,6 @@ export declare const APP_DYNAMIC_STALE_TIME_KEY = "__dynamicStaleTime";
|
|
|
12
11
|
export declare const APP_INTERCEPTION_KEY = "__interception";
|
|
13
12
|
export declare const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
|
|
14
13
|
export declare const APP_LAYOUT_IDS_KEY = "__layoutIds";
|
|
15
|
-
export declare const APP_LAYOUT_FLAGS_KEY = "__layoutFlags";
|
|
16
14
|
export declare const APP_ROUTE_KEY = "__route";
|
|
17
15
|
export declare const APP_ROOT_LAYOUT_KEY = "__rootLayout";
|
|
18
16
|
export declare const APP_SKIPPED_LAYOUT_IDS_KEY = "__skippedLayoutIds";
|
|
@@ -51,28 +49,10 @@ export declare const compareAppElementsSlotIds: typeof compareStrings;
|
|
|
51
49
|
export declare function normalizeAppElementsSlotBindings(slotBindings: readonly AppElementsSlotBinding[], options?: {
|
|
52
50
|
layoutIds?: readonly string[];
|
|
53
51
|
}): readonly AppElementsSlotBinding[];
|
|
54
|
-
export type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null |
|
|
55
|
-
type AppWireElementValue = ReactNode | string | null |
|
|
52
|
+
export type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | readonly string[] | readonly AppElementsSlotBinding[];
|
|
53
|
+
type AppWireElementValue = ReactNode | string | null | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | readonly string[] | readonly AppElementsSlotBinding[];
|
|
56
54
|
export type AppElements = Readonly<Record<string, AppElementValue>>;
|
|
57
55
|
export type AppWireElements = Readonly<Record<string, AppWireElementValue>>;
|
|
58
|
-
/**
|
|
59
|
-
* Per-layout static/dynamic flags. `"s"` = static (skippable on next nav);
|
|
60
|
-
* `"d"` = dynamic (must always render).
|
|
61
|
-
*
|
|
62
|
-
* Lifecycle (partial — later PRs extend this):
|
|
63
|
-
*
|
|
64
|
-
* 1. PROBE — probeAppPageLayouts (server/app-page-execution.ts) returns
|
|
65
|
-
* LayoutFlags for every layout in the route at render time.
|
|
66
|
-
*
|
|
67
|
-
* 2. ATTACH — AppElementsWire.encodeOutgoingPayload writes `__layoutFlags`
|
|
68
|
-
* into the outgoing App Router payload record.
|
|
69
|
-
*
|
|
70
|
-
* 3. WIRE — renderToReadableStream serializes the record as RSC row 0.
|
|
71
|
-
*
|
|
72
|
-
* 4. PARSE — AppElementsWire.readMetadata extracts layoutFlags from the
|
|
73
|
-
* wire payload on the client side.
|
|
74
|
-
*/
|
|
75
|
-
export type LayoutFlags = Readonly<Record<string, "s" | "d">>;
|
|
76
56
|
export type AppElementsBfcacheSegmentIdentities = Readonly<Record<string, BfcacheSegmentIdentity>>;
|
|
77
57
|
type AppElementsMetadata = {
|
|
78
58
|
artifactCompatibility: ArtifactCompatibilityEnvelope;
|
|
@@ -81,7 +61,6 @@ type AppElementsMetadata = {
|
|
|
81
61
|
interception: AppElementsInterception | null;
|
|
82
62
|
interceptionContext: string | null;
|
|
83
63
|
layoutIds: readonly string[];
|
|
84
|
-
layoutFlags: LayoutFlags;
|
|
85
64
|
routeId: string;
|
|
86
65
|
rootLayoutTreePath: string | null;
|
|
87
66
|
bfcacheSegmentIdentities: AppElementsBfcacheSegmentIdentities;
|
|
@@ -113,11 +92,11 @@ type AppElementsWireMetadataEntries = Readonly<{
|
|
|
113
92
|
}>;
|
|
114
93
|
/**
|
|
115
94
|
* The outgoing wire payload shape. Includes ReactNode values for the
|
|
116
|
-
* rendered tree plus metadata values
|
|
117
|
-
*
|
|
95
|
+
* rendered tree plus metadata values attached under known keys (e.g.
|
|
96
|
+
* __artifactCompatibility). Distinct from AppElements / AppWireElements
|
|
118
97
|
* which only carry render-time values.
|
|
119
98
|
*/
|
|
120
|
-
export type AppOutgoingElements = Readonly<Record<string, ReactNode |
|
|
99
|
+
export type AppOutgoingElements = Readonly<Record<string, ReactNode | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | number | readonly string[] | readonly AppElementsSlotBinding[]>>;
|
|
121
100
|
type AppElementsWireKeys = {
|
|
122
101
|
readonly artifactCompatibility: typeof APP_ARTIFACT_COMPATIBILITY_KEY;
|
|
123
102
|
readonly cacheEntryReuseProof: typeof APP_CACHE_ENTRY_REUSE_PROOF_KEY;
|
|
@@ -125,7 +104,6 @@ type AppElementsWireKeys = {
|
|
|
125
104
|
readonly interception: typeof APP_INTERCEPTION_KEY;
|
|
126
105
|
readonly interceptionContext: typeof APP_INTERCEPTION_CONTEXT_KEY;
|
|
127
106
|
readonly layoutIds: typeof APP_LAYOUT_IDS_KEY;
|
|
128
|
-
readonly layoutFlags: typeof APP_LAYOUT_FLAGS_KEY;
|
|
129
107
|
readonly rootLayout: typeof APP_ROOT_LAYOUT_KEY;
|
|
130
108
|
readonly route: typeof APP_ROUTE_KEY;
|
|
131
109
|
readonly bfcacheSegmentIdentities: typeof APP_BFCACHE_SEGMENT_IDENTITIES_KEY;
|
|
@@ -145,8 +123,6 @@ type AppElementsWireCodec = {
|
|
|
145
123
|
artifactCompatibility?: ArtifactCompatibilityEnvelope;
|
|
146
124
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
147
125
|
dynamicStaleTimeSeconds?: number;
|
|
148
|
-
layoutFlags: LayoutFlags;
|
|
149
|
-
skipDisposition?: ClientReuseManifestSkipDisposition;
|
|
150
126
|
}): ReactNode | AppOutgoingElements;
|
|
151
127
|
encodePageId(routePath: string, interceptionContext: string | null): string;
|
|
152
128
|
encodeRouteId(routePath: string, interceptionContext: string | null): string;
|
|
@@ -155,9 +131,6 @@ type AppElementsWireCodec = {
|
|
|
155
131
|
isSlotId(key: string): boolean;
|
|
156
132
|
parseElementKey(key: string): AppElementsWireElementKey | null;
|
|
157
133
|
readMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
|
|
158
|
-
withLayoutFlags<T extends Record<string, unknown>>(elements: T, layoutFlags: LayoutFlags): T & {
|
|
159
|
-
[APP_LAYOUT_FLAGS_KEY]: LayoutFlags;
|
|
160
|
-
};
|
|
161
134
|
};
|
|
162
135
|
export declare function normalizeAppElements(elements: AppWireElements): AppElements;
|
|
163
136
|
/**
|
|
@@ -165,21 +138,16 @@ export declare function normalizeAppElements(elements: AppWireElements): AppElem
|
|
|
165
138
|
* Used to distinguish the App Router payload object from bare React elements at
|
|
166
139
|
* the render boundary. Narrows to `Readonly<Record<string, unknown>>` because
|
|
167
140
|
* the outgoing payload carries heterogeneous values (ReactNodes for the rendered
|
|
168
|
-
* tree, plus metadata like `
|
|
141
|
+
* tree, plus metadata like `__artifactCompatibility`, a plain object). Delegates
|
|
169
142
|
* to React's canonical `isValidElement` so we don't depend on React's internal
|
|
170
143
|
* `$$typeof` marker scheme.
|
|
171
144
|
*/
|
|
172
145
|
export declare function isAppElementsRecord(value: unknown): value is Readonly<Record<string, unknown>>;
|
|
173
|
-
export declare function withLayoutFlags<T extends Record<string, unknown>>(elements: T, layoutFlags: LayoutFlags): T & {
|
|
174
|
-
[APP_LAYOUT_FLAGS_KEY]: LayoutFlags;
|
|
175
|
-
};
|
|
176
146
|
export declare function buildOutgoingAppPayload(input: {
|
|
177
147
|
element: ReactNode | AppElements;
|
|
178
148
|
artifactCompatibility?: ArtifactCompatibilityEnvelope;
|
|
179
149
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
180
150
|
dynamicStaleTimeSeconds?: number;
|
|
181
|
-
layoutFlags: LayoutFlags;
|
|
182
|
-
skipDisposition?: ClientReuseManifestSkipDisposition;
|
|
183
151
|
}): ReactNode | AppOutgoingElements;
|
|
184
152
|
export declare function readAppElementsMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
|
|
185
153
|
export declare const AppElementsWire: AppElementsWireCodec;
|
|
@@ -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
|