vinext 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -30
- package/dist/build/inject-pregenerated-paths.d.ts +4 -0
- package/dist/build/inject-pregenerated-paths.js +18 -0
- package/dist/build/layout-classification.js +1 -1
- package/dist/build/nitro-route-rules.js +1 -1
- package/dist/build/pages-client-assets-module.d.ts +11 -0
- package/dist/build/pages-client-assets-module.js +27 -0
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +13 -6
- package/dist/build/report.d.ts +13 -2
- package/dist/build/report.js +99 -2
- package/dist/build/run-prerender.d.ts +7 -0
- package/dist/build/run-prerender.js +10 -1
- package/dist/build/standalone.js +2 -0
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/check.d.ts +18 -0
- package/dist/check.js +77 -19
- package/dist/cli-args.d.ts +1 -2
- package/dist/cli-args.js +1 -1
- package/dist/cli-dev-config.d.ts +12 -0
- package/dist/cli-dev-config.js +23 -0
- package/dist/cli.js +113 -97
- package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
- package/dist/{server → client}/dev-error-overlay-store.js +1 -1
- package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
- package/dist/{server → client}/dev-error-overlay.js +2 -2
- package/dist/client/navigation-runtime.d.ts +2 -0
- package/dist/client/navigation-runtime.js +3 -1
- package/dist/client/window-next.d.ts +2 -1
- package/dist/cloudflare/index.d.ts +2 -2
- package/dist/cloudflare/index.js +2 -2
- package/dist/config/config-matchers.js +14 -10
- package/dist/config/next-config.d.ts +6 -3
- package/dist/config/next-config.js +47 -1
- package/dist/config/prerender.d.ts +34 -0
- package/dist/config/prerender.js +55 -0
- package/dist/config/server-external-packages.d.ts +4 -0
- package/dist/config/server-external-packages.js +91 -0
- package/dist/entries/app-rsc-entry.d.ts +2 -1
- package/dist/entries/app-rsc-entry.js +89 -15
- package/dist/entries/app-rsc-manifest.js +10 -0
- package/dist/entries/pages-client-entry.d.ts +3 -0
- package/dist/entries/pages-client-entry.js +16 -1
- package/dist/entries/pages-server-entry.js +6 -2
- package/dist/image/image-adapters-virtual.d.ts +59 -0
- package/dist/image/image-adapters-virtual.js +59 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +211 -118
- package/dist/init-cloudflare.d.ts +43 -0
- package/dist/init-cloudflare.js +839 -0
- package/dist/init-platform.d.ts +40 -0
- package/dist/init-platform.js +195 -0
- package/dist/init.d.ts +16 -38
- package/dist/init.js +208 -97
- package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
- package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
- package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
- package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
- package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
- package/dist/packages/cloudflare/src/deploy-config.js +150 -0
- package/dist/packages/cloudflare/src/deploy-help.js +55 -0
- package/dist/packages/cloudflare/src/deploy.js +276 -0
- package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
- package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +18 -15
- package/dist/plugins/ast-scope.d.ts +16 -0
- package/dist/plugins/ast-scope.js +62 -0
- package/dist/plugins/ast-utils.d.ts +27 -1
- package/dist/plugins/ast-utils.js +32 -1
- package/dist/plugins/css-module-imports.d.ts +14 -0
- package/dist/plugins/css-module-imports.js +59 -0
- package/dist/plugins/extensionless-dynamic-import.js +2 -2
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +530 -0
- package/dist/plugins/middleware-server-only.d.ts +8 -6
- package/dist/plugins/middleware-server-only.js +8 -7
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/typeof-window.d.ts +1 -1
- package/dist/plugins/typeof-window.js +28 -56
- package/dist/routing/app-route-graph.d.ts +29 -4
- package/dist/routing/app-route-graph.js +182 -40
- package/dist/routing/app-router.d.ts +5 -0
- package/dist/routing/app-router.js +5 -0
- package/dist/routing/file-matcher.d.ts +8 -0
- package/dist/routing/file-matcher.js +10 -1
- package/dist/routing/pages-router.js +2 -2
- package/dist/server/api-handler.js +9 -14
- package/dist/server/app-browser-action-result.d.ts +4 -1
- package/dist/server/app-browser-action-result.js +8 -1
- package/dist/server/app-browser-entry.js +194 -190
- package/dist/server/app-browser-history-controller.d.ts +2 -1
- package/dist/server/app-browser-history-controller.js +6 -2
- package/dist/server/app-browser-interception-context.d.ts +1 -0
- package/dist/server/app-browser-interception-context.js +4 -2
- package/dist/server/app-browser-navigation-controller.d.ts +2 -0
- package/dist/server/app-browser-navigation-controller.js +60 -31
- package/dist/server/app-browser-server-action-client.d.ts +32 -0
- package/dist/server/app-browser-server-action-client.js +127 -0
- package/dist/server/app-browser-state.d.ts +11 -1
- package/dist/server/app-browser-state.js +25 -8
- package/dist/server/app-browser-visible-commit.d.ts +6 -1
- package/dist/server/app-browser-visible-commit.js +43 -25
- package/dist/server/app-elements-wire.d.ts +9 -2
- package/dist/server/app-elements-wire.js +8 -1
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +4 -3
- package/dist/server/app-fallback-renderer.d.ts +5 -2
- package/dist/server/app-fallback-renderer.js +15 -7
- package/dist/server/app-hydration-cache-publication.d.ts +11 -0
- package/dist/server/app-hydration-cache-publication.js +43 -0
- package/dist/server/app-middleware.d.ts +4 -3
- package/dist/server/app-middleware.js +8 -3
- package/dist/server/app-optimistic-routing.js +11 -4
- package/dist/server/app-page-boundary-render.d.ts +3 -0
- package/dist/server/app-page-boundary-render.js +14 -3
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +10 -3
- package/dist/server/app-page-cache-render.d.ts +1 -0
- package/dist/server/app-page-cache-render.js +8 -4
- package/dist/server/app-page-cache.d.ts +1 -0
- package/dist/server/app-page-cache.js +5 -2
- package/dist/server/app-page-dispatch.d.ts +33 -4
- package/dist/server/app-page-dispatch.js +63 -90
- package/dist/server/app-page-element-builder.d.ts +9 -2
- package/dist/server/app-page-element-builder.js +114 -23
- package/dist/server/app-page-head.d.ts +16 -1
- package/dist/server/app-page-head.js +44 -22
- package/dist/server/app-page-params.d.ts +2 -1
- package/dist/server/app-page-params.js +8 -1
- package/dist/server/app-page-ppr-runtime.d.ts +7 -0
- package/dist/server/app-page-ppr-runtime.js +70 -0
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +6 -1
- package/dist/server/app-page-render-identity.d.ts +1 -0
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render.d.ts +4 -1
- package/dist/server/app-page-render.js +26 -3
- package/dist/server/app-page-request.d.ts +22 -1
- package/dist/server/app-page-request.js +92 -15
- package/dist/server/app-page-route-wiring.d.ts +14 -2
- package/dist/server/app-page-route-wiring.js +61 -25
- package/dist/server/app-page-search-params-observation.d.ts +4 -2
- package/dist/server/app-page-search-params-observation.js +11 -7
- package/dist/server/app-page-segment-state.d.ts +2 -1
- package/dist/server/app-page-segment-state.js +3 -1
- package/dist/server/app-page-stream.d.ts +5 -0
- package/dist/server/app-page-stream.js +3 -1
- package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
- package/dist/server/app-route-handler-dispatch.js +1 -0
- package/dist/server/app-route-handler-execution.js +7 -2
- package/dist/server/app-route-handler-response.js +1 -0
- package/dist/server/app-route-handler-runtime.js +1 -1
- package/dist/server/app-route-module-loader.d.ts +2 -0
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-router-entry.js +16 -8
- package/dist/server/app-rsc-errors.js +7 -1
- package/dist/server/app-rsc-handler.d.ts +3 -1
- package/dist/server/app-rsc-handler.js +67 -39
- package/dist/server/app-rsc-request-normalization.d.ts +3 -2
- package/dist/server/app-rsc-request-normalization.js +6 -3
- package/dist/server/app-rsc-route-matching.d.ts +7 -0
- package/dist/server/app-rsc-route-matching.js +36 -3
- package/dist/server/app-segment-config.d.ts +12 -0
- package/dist/server/app-segment-config.js +91 -5
- package/dist/server/app-server-action-execution.d.ts +5 -0
- package/dist/server/app-server-action-execution.js +94 -33
- package/dist/server/app-ssr-entry.d.ts +3 -0
- package/dist/server/app-ssr-entry.js +19 -8
- package/dist/server/app-ssr-stream.d.ts +7 -3
- package/dist/server/app-ssr-stream.js +10 -6
- package/dist/server/app-static-generation.d.ts +1 -0
- package/dist/server/app-static-generation.js +1 -0
- package/dist/server/app-visited-response-cache.d.ts +6 -0
- package/dist/server/app-visited-response-cache.js +3 -1
- package/dist/server/client-trace-metadata.js +26 -0
- package/dist/server/default-global-not-found-module.d.ts +14 -0
- package/dist/server/default-global-not-found-module.js +14 -0
- package/dist/server/dev-route-files.js +4 -0
- package/dist/server/dev-server.js +19 -18
- package/dist/server/dev-stack-sourcemap.d.ts +1 -1
- package/dist/server/dev-stack-sourcemap.js +1 -1
- package/dist/server/fetch-handler.d.ts +2 -0
- package/dist/server/fetch-handler.js +18 -0
- package/dist/server/headers.d.ts +5 -15
- package/dist/server/headers.js +4 -15
- package/dist/server/image-optimization.d.ts +51 -1
- package/dist/server/image-optimization.js +52 -2
- package/dist/server/implicit-tags.js +1 -1
- package/dist/server/isr-cache.d.ts +1 -1
- package/dist/server/isr-cache.js +2 -2
- package/dist/server/metadata-routes.d.ts +3 -1
- package/dist/server/metadata-routes.js +12 -2
- package/dist/server/middleware-runtime.js +6 -1
- package/dist/server/navigation-planner.d.ts +1 -0
- package/dist/server/navigation-planner.js +14 -3
- package/dist/server/pages-api-route.js +2 -2
- package/dist/server/pages-asset-tags.d.ts +4 -6
- package/dist/server/pages-asset-tags.js +12 -12
- package/dist/server/pages-client-assets.d.ts +12 -0
- package/dist/server/pages-client-assets.js +10 -0
- package/dist/server/pages-node-compat.d.ts +8 -1
- package/dist/server/pages-node-compat.js +32 -4
- package/dist/server/pages-page-data.d.ts +24 -1
- package/dist/server/pages-page-data.js +45 -24
- package/dist/server/pages-page-handler.d.ts +2 -1
- package/dist/server/pages-page-handler.js +19 -12
- package/dist/server/pages-page-response.d.ts +7 -0
- package/dist/server/pages-page-response.js +4 -1
- package/dist/server/pages-request-pipeline.d.ts +2 -0
- package/dist/server/pages-request-pipeline.js +25 -1
- package/dist/server/pages-router-entry.d.ts +30 -0
- package/dist/server/pages-router-entry.js +108 -0
- package/dist/server/prerender-manifest.d.ts +3 -1
- package/dist/server/prerender-route-params.js +1 -1
- package/dist/server/prod-server.d.ts +1 -1
- package/dist/server/prod-server.js +48 -26
- package/dist/server/request-pipeline.js +1 -0
- package/dist/server/seed-cache.js +4 -4
- package/dist/server/worker-utils.d.ts +2 -1
- package/dist/server/worker-utils.js +7 -1
- package/dist/shims/app-router-scroll-state.d.ts +1 -0
- package/dist/shims/app-router-scroll-state.js +1 -0
- package/dist/shims/app-router-scroll.js +2 -1
- package/dist/shims/cache.js +19 -15
- package/dist/shims/cdn-cache.js +1 -1
- package/dist/shims/dynamic-preload-chunks.js +2 -1
- package/dist/shims/error-boundary.d.ts +19 -1
- package/dist/shims/error-boundary.js +11 -1
- package/dist/shims/form.d.ts +3 -1
- package/dist/shims/form.js +37 -43
- package/dist/shims/headers.d.ts +9 -1
- package/dist/shims/headers.js +31 -6
- package/dist/shims/image.js +75 -14
- package/dist/shims/internal/app-route-detection.d.ts +2 -17
- package/dist/shims/internal/app-route-detection.js +4 -17
- package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -15
- package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +9 -5
- package/dist/shims/internal/pages-data-fetch-dedup.js +73 -14
- package/dist/shims/internal/pages-data-target.d.ts +10 -9
- package/dist/shims/internal/pages-data-target.js +91 -12
- package/dist/shims/internal/pages-router-components.d.ts +7 -0
- package/dist/shims/internal/pages-router-components.js +13 -0
- package/dist/shims/layout-segment-context.d.ts +4 -1
- package/dist/shims/layout-segment-context.js +18 -4
- package/dist/shims/link.js +70 -37
- package/dist/shims/metadata.d.ts +3 -2
- package/dist/shims/metadata.js +8 -4
- package/dist/shims/navigation.d.ts +5 -1
- package/dist/shims/navigation.js +45 -10
- package/dist/shims/navigation.react-server.js +1 -1
- package/dist/shims/root-params.d.ts +15 -1
- package/dist/shims/root-params.js +21 -1
- package/dist/shims/router.d.ts +5 -7
- package/dist/shims/router.js +374 -94
- package/dist/shims/server.js +3 -2
- package/dist/shims/slot.js +3 -6
- package/dist/typegen.js +6 -5
- package/dist/utils/client-runtime-metadata.d.ts +2 -18
- package/dist/utils/client-runtime-metadata.js +31 -22
- package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
- package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
- package/dist/utils/domain-locale.d.ts +6 -3
- package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
- package/dist/{server → utils}/middleware-request-headers.js +2 -2
- package/dist/utils/path.d.ts +2 -1
- package/dist/utils/path.js +1 -1
- package/dist/utils/project.d.ts +52 -2
- package/dist/utils/project.js +230 -5
- package/dist/utils/protocol-headers.d.ts +17 -0
- package/dist/utils/protocol-headers.js +17 -0
- package/dist/utils/react-version.d.ts +4 -0
- package/dist/utils/react-version.js +44 -0
- package/package.json +53 -4
- package/dist/deploy.d.ts +0 -190
- package/dist/deploy.js +0 -1033
- package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
- /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { RestorableClientStateController, createHistoryStateWithNavigationMetadata, readHistoryStateBfcacheIds, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
2
2
|
//#region src/server/app-browser-history-controller.ts
|
|
3
|
+
function createCanonicalBrowserHistoryHref(href) {
|
|
4
|
+
const url = new URL(href);
|
|
5
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
6
|
+
}
|
|
3
7
|
function stripVinextScrollState(state) {
|
|
4
8
|
if (!state || typeof state !== "object") return state;
|
|
5
9
|
const nextState = {};
|
|
@@ -166,7 +170,7 @@ var AppBrowserHistoryController = class {
|
|
|
166
170
|
this.#replaceHistoryState(createHistoryStateWithNavigationMetadata(this.#readHistoryState(), {
|
|
167
171
|
previousNextUrl: null,
|
|
168
172
|
traversalIndex: this.#currentHistoryTraversalIndex
|
|
169
|
-
}), this.#readCurrentHref());
|
|
173
|
+
}), createCanonicalBrowserHistoryHref(this.#readCurrentHref()));
|
|
170
174
|
}
|
|
171
175
|
/** History write performed on the first committed (hydrated) render. */
|
|
172
176
|
writeHydratedHistoryMetadata(options) {
|
|
@@ -207,4 +211,4 @@ function areBfcacheIdMapsEqual(a, b) {
|
|
|
207
211
|
return aEntries.every(([key, value]) => b[key] === value);
|
|
208
212
|
}
|
|
209
213
|
//#endregion
|
|
210
|
-
export { AppBrowserHistoryController };
|
|
214
|
+
export { AppBrowserHistoryController, createCanonicalBrowserHistoryHref };
|
|
@@ -3,6 +3,7 @@ import { RouteManifest } from "../routing/app-route-graph.js";
|
|
|
3
3
|
//#region src/server/app-browser-interception-context.d.ts
|
|
4
4
|
type ResolveManifestNavigationInterceptionContextOptions = {
|
|
5
5
|
basePath: string;
|
|
6
|
+
currentMatchedPathname?: string | null;
|
|
6
7
|
currentPathname: string;
|
|
7
8
|
routeManifest: RouteManifest | null;
|
|
8
9
|
targetPathname: string;
|
|
@@ -29,13 +29,15 @@ function resolveManifestNavigationInterceptionContext(options) {
|
|
|
29
29
|
function resolveMiddlewareRewriteNavigationInterceptionContext(options) {
|
|
30
30
|
if (options.routeManifest === null) return null;
|
|
31
31
|
const currentPathname = stripBasePath(options.currentPathname, options.basePath);
|
|
32
|
+
const currentMatchedPathname = options.currentMatchedPathname ? stripBasePath(options.currentMatchedPathname, options.basePath) : null;
|
|
32
33
|
const targetPathname = stripBasePath(options.targetPathname, options.basePath);
|
|
33
34
|
const sourceParts = splitPathnameForRouteMatch(currentPathname);
|
|
35
|
+
const matchedSourceParts = currentMatchedPathname ? splitPathnameForRouteMatch(currentMatchedPathname) : null;
|
|
34
36
|
const targetParts = splitPathnameForRouteMatch(targetPathname);
|
|
35
37
|
for (const interception of options.routeManifest.segmentGraph.interceptions.values()) {
|
|
36
|
-
if (!matchRoutePatternPrefix(sourceParts, interception.sourcePatternParts)) continue;
|
|
37
38
|
if (!matchRoutePatternWithOptionalDynamicSegments(targetParts, interception.targetPatternParts)) continue;
|
|
38
|
-
return currentPathname;
|
|
39
|
+
if (matchRoutePatternPrefix(sourceParts, interception.sourcePatternParts)) return currentPathname;
|
|
40
|
+
if (currentMatchedPathname !== null && matchedSourceParts !== null && matchRoutePatternPrefix(matchedSourceParts, interception.sourcePatternParts)) return currentMatchedPathname;
|
|
39
41
|
}
|
|
40
42
|
return null;
|
|
41
43
|
}
|
|
@@ -77,7 +77,9 @@ type BrowserNavigationController = {
|
|
|
77
77
|
targetHistoryIndex?: number | null;
|
|
78
78
|
targetHref: string;
|
|
79
79
|
navId: number;
|
|
80
|
+
navigationCommitKind?: "authoritative" | "detached";
|
|
80
81
|
visibleCommitMode?: NavigationRuntimeVisibleCommitMode;
|
|
82
|
+
onCommittedState?: (state: AppRouterState) => void;
|
|
81
83
|
}): Promise<NavigationPayloadOutcome>;
|
|
82
84
|
commitSameUrlNavigatePayload(nextElements: Promise<AppElements>, navigationSnapshot: ClientNavigationRenderSnapshot, returnValue?: {
|
|
83
85
|
ok: boolean;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { stripBasePath } from "../utils/base-path.js";
|
|
2
2
|
import { clearAppNavigationFailureTarget, getAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
|
|
3
3
|
import { claimAppRouterScrollIntentForCommit, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
4
|
+
import { resolveServerActionOperationLane, shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
|
|
4
5
|
import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
5
|
-
import { shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
|
|
6
6
|
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, createPendingNavigationCommit } from "./app-browser-state.js";
|
|
7
7
|
import { applyApprovedVisibleCommit, approveHmrVisibleCommit, approvePendingNavigationCommit, resolveAndClassifyNavigationCommit } from "./app-browser-visible-commit.js";
|
|
8
8
|
import { startTransition, useInsertionEffect, useLayoutEffect } from "react";
|
|
@@ -73,6 +73,9 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
73
73
|
const syncHistoryStatePreviousNextUrl = deps.syncHistoryStatePreviousNextUrl ?? (() => {});
|
|
74
74
|
let nextNavigationRenderId = 0;
|
|
75
75
|
let activeNavigationId = 0;
|
|
76
|
+
let pendingUserNavigationId = null;
|
|
77
|
+
let pendingUserNavigationLane = null;
|
|
78
|
+
let latestHmrUpdateId = 0;
|
|
76
79
|
const pendingNavigationCommits = /* @__PURE__ */ new Map();
|
|
77
80
|
const pendingNavigationFailureTargets = /* @__PURE__ */ new Map();
|
|
78
81
|
const pendingNavigationPrePaintEffects = /* @__PURE__ */ new Map();
|
|
@@ -105,7 +108,10 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
105
108
|
resolveReady?.();
|
|
106
109
|
}
|
|
107
110
|
function beginNavigation() {
|
|
111
|
+
latestHmrUpdateId += 1;
|
|
108
112
|
activeNavigationId += 1;
|
|
113
|
+
pendingUserNavigationId = activeNavigationId;
|
|
114
|
+
pendingUserNavigationLane = null;
|
|
109
115
|
return activeNavigationId;
|
|
110
116
|
}
|
|
111
117
|
function getActiveNavigationId() {
|
|
@@ -149,13 +155,11 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
149
155
|
}
|
|
150
156
|
function finalizeNavigation(navId, pending) {
|
|
151
157
|
settlePendingBrowserRouterState(pending);
|
|
152
|
-
if (isCurrentNavigation(navId))
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
pending.resolve(applyApprovedVisibleCommit(getBrowserRouterState(), commit));
|
|
158
|
-
if (activePendingBrowserRouterState === pending) activePendingBrowserRouterState = null;
|
|
158
|
+
if (isCurrentNavigation(navId)) {
|
|
159
|
+
pendingUserNavigationId = null;
|
|
160
|
+
pendingUserNavigationLane = null;
|
|
161
|
+
clearPendingPathname(navId);
|
|
162
|
+
}
|
|
159
163
|
}
|
|
160
164
|
function queuePrePaintNavigationEffect(renderId, effect) {
|
|
161
165
|
if (!effect) return;
|
|
@@ -181,16 +185,17 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
181
185
|
}
|
|
182
186
|
}
|
|
183
187
|
/**
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* This pattern is also used in drainPrePaintEffects with the same semantics.
|
|
188
|
+
* Settle all pending navigation renders through the supplied renderId. Only
|
|
189
|
+
* the exact render whose layout effect ran is a successful commit; older
|
|
190
|
+
* superseded renders and cleanup-only settlements resolve as no-commit.
|
|
188
191
|
*/
|
|
189
|
-
function
|
|
190
|
-
for (const [pendingId,
|
|
192
|
+
function settleNavigationCommits(renderId, committed) {
|
|
193
|
+
for (const [pendingId, pendingCommit] of pendingNavigationCommits) {
|
|
191
194
|
if (pendingId > renderId) continue;
|
|
192
195
|
pendingNavigationCommits.delete(pendingId);
|
|
193
|
-
|
|
196
|
+
const didCommit = committed && pendingId === renderId;
|
|
197
|
+
if (didCommit && pendingCommit.committedState !== null) pendingCommit.onCommittedState?.(pendingCommit.committedState);
|
|
198
|
+
pendingCommit.resolve(didCommit);
|
|
194
199
|
}
|
|
195
200
|
}
|
|
196
201
|
function clearCommittedNavigationFailureTargets(renderId) {
|
|
@@ -201,6 +206,8 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
201
206
|
}
|
|
202
207
|
}
|
|
203
208
|
async function hmrReplaceTree(nextElements, navigationSnapshot) {
|
|
209
|
+
const hmrUpdateId = ++latestHmrUpdateId;
|
|
210
|
+
const startedDuringUserNavigation = pendingUserNavigationLane === "navigation";
|
|
204
211
|
if (!hasBrowserRouterState()) return;
|
|
205
212
|
const pending = await createPendingNavigationCommit({
|
|
206
213
|
currentState: getBrowserRouterState(),
|
|
@@ -211,8 +218,16 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
211
218
|
renderId: allocateRenderId(),
|
|
212
219
|
type: "replace"
|
|
213
220
|
});
|
|
221
|
+
if (hmrUpdateId !== latestHmrUpdateId || startedDuringUserNavigation) return;
|
|
214
222
|
if (!hasBrowserRouterState()) return;
|
|
215
|
-
|
|
223
|
+
const approval = approveHmrVisibleCommit({
|
|
224
|
+
currentState: getBrowserRouterState(),
|
|
225
|
+
pending,
|
|
226
|
+
routeManifest: deps.getRouteManifest?.() ?? null,
|
|
227
|
+
targetHref: createSnapshotPathAndSearch(navigationSnapshot)
|
|
228
|
+
});
|
|
229
|
+
if (approval.approvedCommit) dispatchSynchronousVisibleCommit(approval.approvedCommit);
|
|
230
|
+
else if (approval.decision.disposition === "hard-navigate") performHardNavigation(createSnapshotPathAndSearch(navigationSnapshot));
|
|
216
231
|
}
|
|
217
232
|
function NavigationCommitSignal({ renderId, children }) {
|
|
218
233
|
useInsertionEffect(() => {
|
|
@@ -220,30 +235,36 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
220
235
|
}, [renderId]);
|
|
221
236
|
useLayoutEffect(() => {
|
|
222
237
|
drainPrePaintEffects(renderId);
|
|
223
|
-
|
|
224
|
-
resolveCommittedNavigations(renderId);
|
|
225
|
-
});
|
|
238
|
+
settleNavigationCommits(renderId, true);
|
|
226
239
|
return () => {
|
|
227
|
-
|
|
228
|
-
resolveCommittedNavigations(renderId);
|
|
240
|
+
settleNavigationCommits(renderId, false);
|
|
229
241
|
};
|
|
230
242
|
}, [renderId]);
|
|
231
243
|
return children;
|
|
232
244
|
}
|
|
233
|
-
function dispatchApprovedVisibleCommit(commit, pendingRouterState, visibleCommitMode) {
|
|
245
|
+
function dispatchApprovedVisibleCommit(renderId, commit, pendingRouterState, visibleCommitMode) {
|
|
234
246
|
const setter = getBrowserRouterStateSetter();
|
|
247
|
+
const pendingCommit = pendingNavigationCommits.get(renderId);
|
|
248
|
+
const captureCandidateState = (state) => {
|
|
249
|
+
if (pendingCommit) pendingCommit.committedState = state;
|
|
250
|
+
return state;
|
|
251
|
+
};
|
|
235
252
|
if (pendingRouterState) {
|
|
236
|
-
|
|
253
|
+
if (pendingRouterState.settled) return;
|
|
254
|
+
const committedState = captureCandidateState(applyApprovedVisibleCommit(getBrowserRouterState(), commit));
|
|
255
|
+
pendingRouterState.settled = true;
|
|
256
|
+
pendingRouterState.resolve(committedState);
|
|
257
|
+
if (activePendingBrowserRouterState === pendingRouterState) activePendingBrowserRouterState = null;
|
|
237
258
|
return;
|
|
238
259
|
}
|
|
239
260
|
if (visibleCommitMode === "synchronous") {
|
|
240
261
|
flushSync(() => {
|
|
241
|
-
setter(applyApprovedVisibleCommit(getBrowserRouterState(), commit));
|
|
262
|
+
setter(captureCandidateState(applyApprovedVisibleCommit(getBrowserRouterState(), commit)));
|
|
242
263
|
});
|
|
243
264
|
return;
|
|
244
265
|
}
|
|
245
266
|
startTransition(() => {
|
|
246
|
-
setter(applyApprovedVisibleCommit(getBrowserRouterState(), commit));
|
|
267
|
+
setter(captureCandidateState(applyApprovedVisibleCommit(getBrowserRouterState(), commit)));
|
|
247
268
|
});
|
|
248
269
|
}
|
|
249
270
|
function dispatchSynchronousVisibleCommit(commit) {
|
|
@@ -280,6 +301,7 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
280
301
|
previousNextUrl: options.restoredState.previousNextUrl,
|
|
281
302
|
rootLayoutTreePath: options.restoredState.rootLayoutTreePath,
|
|
282
303
|
routeId: options.restoredState.routeId,
|
|
304
|
+
restoredHistorySnapshot: true,
|
|
283
305
|
skippedLayoutIds: []
|
|
284
306
|
};
|
|
285
307
|
}
|
|
@@ -309,18 +331,25 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
309
331
|
lifecycleOptions?.onDiscardedRevalidation?.();
|
|
310
332
|
}
|
|
311
333
|
async function renderNavigationPayload(options) {
|
|
334
|
+
if (options.navId === pendingUserNavigationId) pendingUserNavigationLane = options.operationLane;
|
|
312
335
|
const renderId = allocateRenderId();
|
|
313
336
|
const failureTarget = getAppNavigationFailureTarget(options.targetHref);
|
|
314
337
|
if (failureTarget) pendingNavigationFailureTargets.set(renderId, failureTarget);
|
|
315
338
|
let resolveCommitted;
|
|
316
339
|
const committed = new Promise((resolve) => {
|
|
317
340
|
resolveCommitted = resolve;
|
|
318
|
-
pendingNavigationCommits.set(renderId,
|
|
341
|
+
pendingNavigationCommits.set(renderId, {
|
|
342
|
+
committedState: null,
|
|
343
|
+
onCommittedState: options.onCommittedState,
|
|
344
|
+
resolve
|
|
345
|
+
});
|
|
319
346
|
});
|
|
320
347
|
let snapshotActivated = false;
|
|
321
348
|
try {
|
|
322
349
|
const pending = await createPendingNavigationCommit({
|
|
323
350
|
currentState: getBrowserRouterState(),
|
|
351
|
+
navigationCommitKind: options.navigationCommitKind,
|
|
352
|
+
navigationId: options.navId,
|
|
324
353
|
nextElements: options.nextElements,
|
|
325
354
|
navigationSnapshot: options.navigationSnapshot,
|
|
326
355
|
operationLane: options.operationLane,
|
|
@@ -344,7 +373,7 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
344
373
|
pendingNavigationFailureTargets.delete(renderId);
|
|
345
374
|
if (failureTarget) clearAppNavigationFailureTarget(failureTarget);
|
|
346
375
|
pendingNavigationCommits.delete(renderId);
|
|
347
|
-
resolveCommitted?.();
|
|
376
|
+
resolveCommitted?.(false);
|
|
348
377
|
consumeAppRouterScrollIntent(options.scrollIntent ?? null);
|
|
349
378
|
return "no-commit";
|
|
350
379
|
}
|
|
@@ -371,17 +400,17 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
371
400
|
claimAppRouterScrollIntentForCommit(options.scrollIntent, renderId);
|
|
372
401
|
activateNavigationSnapshot();
|
|
373
402
|
snapshotActivated = true;
|
|
374
|
-
dispatchApprovedVisibleCommit(approvedCommit, options.pendingRouterState, options.visibleCommitMode ?? "transition");
|
|
403
|
+
dispatchApprovedVisibleCommit(renderId, approvedCommit, options.pendingRouterState, options.visibleCommitMode ?? "transition");
|
|
375
404
|
} catch (error) {
|
|
376
405
|
pendingNavigationFailureTargets.delete(renderId);
|
|
377
406
|
pendingNavigationPrePaintEffects.delete(renderId);
|
|
378
407
|
pendingNavigationCommits.delete(renderId);
|
|
379
408
|
if (snapshotActivated) commitClientNavigationStateImpl(options.navId);
|
|
380
409
|
settlePendingBrowserRouterState(options.pendingRouterState);
|
|
381
|
-
resolveCommitted?.();
|
|
410
|
+
resolveCommitted?.(false);
|
|
382
411
|
throw error;
|
|
383
412
|
}
|
|
384
|
-
return committed.then(() => "committed");
|
|
413
|
+
return committed.then((didCommit) => didCommit ? "committed" : "no-commit");
|
|
385
414
|
}
|
|
386
415
|
async function commitSameUrlNavigatePayload(nextElements, navigationSnapshot, returnValue, actionInitiationState, lifecycleOptions) {
|
|
387
416
|
const currentState = actionInitiationState ?? getBrowserRouterState();
|
|
@@ -395,7 +424,7 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
395
424
|
navigationSnapshot,
|
|
396
425
|
nextElements,
|
|
397
426
|
renderId: allocateRenderId(),
|
|
398
|
-
operationLane: "
|
|
427
|
+
operationLane: resolveServerActionOperationLane(lifecycleOptions?.revalidation ?? "none"),
|
|
399
428
|
payloadOrigin: FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN,
|
|
400
429
|
startedNavigationId,
|
|
401
430
|
routeManifest: getRouteManifest(),
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AppElements, AppWireElements } from "./app-elements-wire.js";
|
|
2
|
+
import { navigationPlanner } from "./navigation-planner.js";
|
|
3
|
+
import { AppBrowserServerActionResult, ServerActionRevalidationKind } from "./app-browser-action-result.js";
|
|
4
|
+
import { AppRouterState } from "./app-browser-state.js";
|
|
5
|
+
|
|
6
|
+
//#region src/server/app-browser-server-action-client.d.ts
|
|
7
|
+
type ServerActionResult = AppBrowserServerActionResult<AppWireElements>;
|
|
8
|
+
type ClientServerActionInitiation = {
|
|
9
|
+
href: string;
|
|
10
|
+
navigationId: number;
|
|
11
|
+
path: string;
|
|
12
|
+
routerState: AppRouterState;
|
|
13
|
+
};
|
|
14
|
+
type ActionRedirectTarget = {
|
|
15
|
+
href: string;
|
|
16
|
+
type: string;
|
|
17
|
+
status: number;
|
|
18
|
+
};
|
|
19
|
+
type ClientServerActionDeps = {
|
|
20
|
+
basePath: string;
|
|
21
|
+
clearClientNavigationCaches(): void;
|
|
22
|
+
clientRscCompatibilityId: string | null;
|
|
23
|
+
commitSameUrlNavigatePayload(elements: Promise<AppElements>, actionInitiation: ClientServerActionInitiation, returnValue: ServerActionResult["returnValue"] | undefined, revalidation: ServerActionRevalidationKind): Promise<unknown>;
|
|
24
|
+
navigationPlanner: typeof navigationPlanner;
|
|
25
|
+
performHardNavigation(url: string, historyMode?: "assign" | "replace"): void;
|
|
26
|
+
renderRedirectPayload(elements: AppElements, target: ActionRedirectTarget, actionInitiation: ClientServerActionInitiation, revalidation: ServerActionRevalidationKind): void;
|
|
27
|
+
syncCurrentHistoryState(previousNextUrl: string | null, bfcacheIds: Readonly<Record<string, string>>): void;
|
|
28
|
+
syncServerActionHttpFallbackHead(status: number | null): void;
|
|
29
|
+
};
|
|
30
|
+
declare function invokeClientServerAction(id: string, args: unknown[], actionInitiation: ClientServerActionInitiation, deps: ClientServerActionDeps): Promise<unknown>;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { ClientServerActionDeps, ClientServerActionInitiation, invokeClientServerAction };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER } from "./headers.js";
|
|
2
|
+
import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
|
|
3
|
+
import { AppElementsWire } from "./app-elements-wire.js";
|
|
4
|
+
import "./app-elements.js";
|
|
5
|
+
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createServerActionRequestUrl } from "./app-rsc-cache-busting.js";
|
|
6
|
+
import { createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult, shouldSyncServerActionHttpFallbackHead } from "./app-browser-action-result.js";
|
|
7
|
+
import { resolveServerActionRequestState } from "./app-browser-state.js";
|
|
8
|
+
import { applyServerActionResultDecision } from "./app-browser-server-action-navigation.js";
|
|
9
|
+
import { throwOnServerActionNotFound } from "./server-action-not-found.js";
|
|
10
|
+
import { createFromFetch, createTemporaryReferenceSet, encodeReply } from "@vitejs/plugin-rsc/browser";
|
|
11
|
+
//#region src/server/app-browser-server-action-client.ts
|
|
12
|
+
function resolveActionRedirectTarget(response, performHardNavigation) {
|
|
13
|
+
const actionRedirect = response.headers.get(ACTION_REDIRECT_HEADER);
|
|
14
|
+
if (!actionRedirect) return null;
|
|
15
|
+
if (isDangerousScheme(actionRedirect)) {
|
|
16
|
+
console.error(DANGEROUS_URL_BLOCK_MESSAGE);
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
let redirectUrl;
|
|
21
|
+
if (actionRedirect.startsWith("/") || /^[a-z]+:/i.test(actionRedirect)) redirectUrl = new URL(actionRedirect, window.location.href);
|
|
22
|
+
else {
|
|
23
|
+
const baseParsed = new URL(window.location.href);
|
|
24
|
+
let baseDir = baseParsed.pathname;
|
|
25
|
+
if (!baseDir.endsWith("/")) baseDir += "/";
|
|
26
|
+
redirectUrl = new URL(actionRedirect, `${baseParsed.origin}${baseDir}${baseParsed.search}`);
|
|
27
|
+
}
|
|
28
|
+
if (redirectUrl.origin !== window.location.origin) {
|
|
29
|
+
performHardNavigation(actionRedirect);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const statusHeader = response.headers.get(ACTION_REDIRECT_STATUS_HEADER);
|
|
33
|
+
return {
|
|
34
|
+
href: redirectUrl.href,
|
|
35
|
+
type: response.headers.get("x-action-redirect-type") ?? "push",
|
|
36
|
+
status: statusHeader ? parseInt(statusHeader, 10) : 307
|
|
37
|
+
};
|
|
38
|
+
} catch {
|
|
39
|
+
performHardNavigation(actionRedirect);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
var ServerActionRedirectError = class extends Error {
|
|
44
|
+
digest;
|
|
45
|
+
handled = true;
|
|
46
|
+
constructor(target) {
|
|
47
|
+
super("NEXT_REDIRECT");
|
|
48
|
+
const redirectUrl = new URL(target.href, window.location.href);
|
|
49
|
+
const redirectHref = redirectUrl.pathname + redirectUrl.search + redirectUrl.hash;
|
|
50
|
+
const redirectType = target.type === "push" ? "push" : "replace";
|
|
51
|
+
this.digest = `NEXT_REDIRECT;${redirectType};${encodeURIComponent(redirectHref)};${target.status};`;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
async function invokeClientServerAction(id, args, actionInitiation, deps) {
|
|
55
|
+
deps.syncServerActionHttpFallbackHead(null);
|
|
56
|
+
const temporaryReferences = createTemporaryReferenceSet();
|
|
57
|
+
deps.syncCurrentHistoryState(actionInitiation.routerState.previousNextUrl, actionInitiation.routerState.bfcacheIds);
|
|
58
|
+
const body = await encodeReply(args, { temporaryReferences });
|
|
59
|
+
const headers = resolveServerActionRequestState({
|
|
60
|
+
actionId: id,
|
|
61
|
+
basePath: deps.basePath,
|
|
62
|
+
elements: actionInitiation.routerState.elements,
|
|
63
|
+
previousNextUrl: actionInitiation.routerState.previousNextUrl
|
|
64
|
+
}).headers;
|
|
65
|
+
const fetchResponse = await fetch(createServerActionRequestUrl(actionInitiation.path), {
|
|
66
|
+
method: "POST",
|
|
67
|
+
headers,
|
|
68
|
+
body
|
|
69
|
+
});
|
|
70
|
+
throwOnServerActionNotFound(fetchResponse, id);
|
|
71
|
+
const hasActionRedirect = fetchResponse.headers.has(ACTION_REDIRECT_HEADER);
|
|
72
|
+
const actionRedirectTarget = resolveActionRedirectTarget(fetchResponse, (url, historyMode) => deps.performHardNavigation(url, historyMode));
|
|
73
|
+
if (hasActionRedirect && !actionRedirectTarget) return void 0;
|
|
74
|
+
const actionResultFacts = createServerActionResultFacts({
|
|
75
|
+
actionRedirectHref: actionRedirectTarget?.href ?? null,
|
|
76
|
+
actionRedirectType: actionRedirectTarget?.type ?? null,
|
|
77
|
+
clientCompatibilityId: deps.clientRscCompatibilityId,
|
|
78
|
+
compatibilityIdHeader: fetchResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
|
|
79
|
+
contentTypeHeader: fetchResponse.headers.get("content-type"),
|
|
80
|
+
currentHref: actionInitiation.href,
|
|
81
|
+
origin: window.location.origin,
|
|
82
|
+
responseUrl: fetchResponse.url
|
|
83
|
+
});
|
|
84
|
+
const fetchResponseIsRsc = actionResultFacts.isRscContentType;
|
|
85
|
+
if (applyServerActionResultDecision(deps.navigationPlanner.classifyServerActionResult(actionResultFacts), () => deps.clearClientNavigationCaches(), (url, historyMode) => deps.performHardNavigation(url, historyMode))) return;
|
|
86
|
+
const revalidation = parseServerActionRevalidationHeader(fetchResponse.headers);
|
|
87
|
+
if (revalidation !== "none") deps.clearClientNavigationCaches();
|
|
88
|
+
const invalidResponseError = await readInvalidServerActionResponseError(fetchResponse.clone(), actionRedirectTarget !== null);
|
|
89
|
+
if (invalidResponseError) throw invalidResponseError;
|
|
90
|
+
if (actionRedirectTarget && !fetchResponseIsRsc) {
|
|
91
|
+
deps.performHardNavigation(actionRedirectTarget.href);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const flightResponse = fetchResponse.status === 303 ? new Response(fetchResponse.body, {
|
|
95
|
+
headers: fetchResponse.headers,
|
|
96
|
+
status: 200,
|
|
97
|
+
statusText: "OK"
|
|
98
|
+
}) : fetchResponse;
|
|
99
|
+
const result = await createFromFetch(Promise.resolve(flightResponse), { temporaryReferences });
|
|
100
|
+
if (revalidation === "none" && shouldClearClientNavigationCachesForServerActionResult(result, revalidation)) deps.clearClientNavigationCaches();
|
|
101
|
+
if (actionRedirectTarget) {
|
|
102
|
+
if (isServerActionResult(result) && result.root !== void 0) {
|
|
103
|
+
deps.renderRedirectPayload(AppElementsWire.decode(result.root), actionRedirectTarget, actionInitiation, revalidation);
|
|
104
|
+
throw new ServerActionRedirectError(actionRedirectTarget);
|
|
105
|
+
}
|
|
106
|
+
deps.performHardNavigation(actionRedirectTarget.href);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
deps.syncServerActionHttpFallbackHead(shouldSyncServerActionHttpFallbackHead(result) ? fetchResponse.status : null);
|
|
110
|
+
if (isServerActionResult(result)) {
|
|
111
|
+
if (result.root !== void 0) {
|
|
112
|
+
const returnValue = result.returnValue && !result.returnValue.ok ? {
|
|
113
|
+
ok: false,
|
|
114
|
+
data: normalizeServerActionThrownValue(result.returnValue.data, fetchResponse.status)
|
|
115
|
+
} : result.returnValue;
|
|
116
|
+
return deps.commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result.root)), actionInitiation, returnValue, revalidation);
|
|
117
|
+
}
|
|
118
|
+
if (result.returnValue) {
|
|
119
|
+
if (!result.returnValue.ok) throw normalizeServerActionThrownValue(result.returnValue.data, fetchResponse.status);
|
|
120
|
+
return result.returnValue.data;
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
return deps.commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result)), actionInitiation, void 0, revalidation);
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
export { invokeClientServerAction };
|
|
@@ -11,6 +11,8 @@ import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
|
11
11
|
type OperationRecordBase = {
|
|
12
12
|
id: number;
|
|
13
13
|
lane: OperationLane;
|
|
14
|
+
navigationCommitKind?: "authoritative" | "detached";
|
|
15
|
+
navigationId?: number;
|
|
14
16
|
startedVisibleCommitVersion: number;
|
|
15
17
|
};
|
|
16
18
|
type PendingOperationRecord = OperationRecordBase & {
|
|
@@ -64,18 +66,23 @@ type PendingNavigationCommit = {
|
|
|
64
66
|
previousNextUrl: string | null;
|
|
65
67
|
rootLayoutTreePath: string | null;
|
|
66
68
|
routeId: string;
|
|
69
|
+
restoredHistorySnapshot?: boolean;
|
|
67
70
|
skippedLayoutIds: readonly string[];
|
|
68
71
|
};
|
|
69
72
|
type AppNavigationPayloadOrigin = Readonly<{
|
|
73
|
+
origin: "committed-cache";
|
|
74
|
+
} | {
|
|
70
75
|
origin: "fresh";
|
|
71
76
|
} | {
|
|
72
77
|
origin: "visited-cache";
|
|
73
78
|
}>;
|
|
79
|
+
declare const COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN: AppNavigationPayloadOrigin;
|
|
74
80
|
declare const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN: AppNavigationPayloadOrigin;
|
|
75
81
|
declare const VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN: AppNavigationPayloadOrigin;
|
|
76
82
|
type PendingNavigationCommitDisposition = "dispatch" | "hard-navigate" | "skip";
|
|
77
83
|
type CacheRestorableAppPayloadMetadata = Readonly<{
|
|
78
84
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
85
|
+
dynamicStaleTimeSeconds?: number;
|
|
79
86
|
skippedLayoutIds: readonly string[];
|
|
80
87
|
}>;
|
|
81
88
|
type DispatchPendingNavigationCommitDispositionDecision = {
|
|
@@ -91,6 +98,7 @@ type NonDispatchPendingNavigationCommitDispositionDecision = {
|
|
|
91
98
|
trace: NavigationTrace;
|
|
92
99
|
};
|
|
93
100
|
type PendingNavigationCommitDispositionDecision = DispatchPendingNavigationCommitDispositionDecision | NonDispatchPendingNavigationCommitDispositionDecision;
|
|
101
|
+
declare function isCompleteAppPayloadMetadata(metadata: CacheRestorableAppPayloadMetadata): boolean;
|
|
94
102
|
declare function isCacheRestorableAppPayloadMetadata(metadata: CacheRestorableAppPayloadMetadata): metadata is CacheRestorableAppPayloadMetadata & {
|
|
95
103
|
cacheEntryReuseProof: CacheEntryReuseProof;
|
|
96
104
|
};
|
|
@@ -126,6 +134,8 @@ declare function resolvePendingNavigationCommitDispositionDecision(options: {
|
|
|
126
134
|
}): PendingNavigationCommitDispositionDecision;
|
|
127
135
|
declare function createPendingNavigationCommit(options: {
|
|
128
136
|
currentState: AppRouterState;
|
|
137
|
+
navigationCommitKind?: "authoritative" | "detached";
|
|
138
|
+
navigationId?: number;
|
|
129
139
|
nextElements: Promise<AppElements>;
|
|
130
140
|
navigationSnapshot: ClientNavigationRenderSnapshot;
|
|
131
141
|
operationLane: OperationLane;
|
|
@@ -137,4 +147,4 @@ declare function createPendingNavigationCommit(options: {
|
|
|
137
147
|
type: "navigate" | "replace" | "traverse";
|
|
138
148
|
}): Promise<PendingNavigationCommit>;
|
|
139
149
|
//#endregion
|
|
140
|
-
export { AppNavigationPayloadOrigin, AppRouterAction, AppRouterState, type BfcacheIdMap, CommittedOperationRecord, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, type HistoryTraversalIntent, type OperationLane, PendingNavigationCommit, PendingOperationRecord, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, createBfcacheSegmentStateKeyMap, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createInitialBfcacheIdMap, createNextBfcacheIdMap, createPendingNavigationCommit, isCacheRestorableAppPayloadMetadata, isHistoryStateBfcacheVersionCurrent, preserveBfcacheIdsForMergedElements, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent, resolveInterceptionContextFromPreviousNextUrl, resolvePendingNavigationCommitDispositionDecision, resolveServerActionRequestState };
|
|
150
|
+
export { AppNavigationPayloadOrigin, AppRouterAction, AppRouterState, type BfcacheIdMap, COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, CommittedOperationRecord, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, type HistoryTraversalIntent, type OperationLane, PendingNavigationCommit, PendingOperationRecord, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, createBfcacheSegmentStateKeyMap, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createInitialBfcacheIdMap, createNextBfcacheIdMap, createPendingNavigationCommit, isCacheRestorableAppPayloadMetadata, isCompleteAppPayloadMetadata, isHistoryStateBfcacheVersionCurrent, preserveBfcacheIdsForMergedElements, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent, resolveInterceptionContextFromPreviousNextUrl, resolvePendingNavigationCommitDispositionDecision, resolveServerActionRequestState };
|
|
@@ -6,28 +6,35 @@ import { AppElementsWire } from "./app-elements-wire.js";
|
|
|
6
6
|
import { getMountedSlotIds, getMountedSlotIdsHeader } from "./app-elements.js";
|
|
7
7
|
import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
|
|
8
8
|
import { createCacheEntryReuseProof } from "./cache-proof.js";
|
|
9
|
+
import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
9
10
|
import { createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
10
11
|
import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
|
|
11
12
|
import { verifyOperationTokenForCommit } from "./operation-token.js";
|
|
12
13
|
import { navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts } from "./navigation-planner.js";
|
|
13
14
|
import { createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
14
|
-
import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
15
15
|
//#region src/server/app-browser-state.ts
|
|
16
|
+
const COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "committed-cache" };
|
|
16
17
|
const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "fresh" };
|
|
17
18
|
const VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "visited-cache" };
|
|
18
19
|
function createOperationRecord(options) {
|
|
19
20
|
return {
|
|
20
21
|
id: options.id,
|
|
21
22
|
lane: options.lane,
|
|
23
|
+
...options.navigationCommitKind !== void 0 ? { navigationCommitKind: options.navigationCommitKind } : {},
|
|
24
|
+
...options.navigationId !== void 0 ? { navigationId: options.navigationId } : {},
|
|
22
25
|
startedVisibleCommitVersion: options.startedVisibleCommitVersion,
|
|
23
26
|
state: "pending"
|
|
24
27
|
};
|
|
25
28
|
}
|
|
29
|
+
function isCompleteAppPayloadMetadata(metadata) {
|
|
30
|
+
return metadata.skippedLayoutIds.length === 0;
|
|
31
|
+
}
|
|
26
32
|
function isCacheRestorableAppPayloadMetadata(metadata) {
|
|
27
|
-
return metadata.cacheEntryReuseProof !== void 0 && metadata
|
|
33
|
+
return metadata.cacheEntryReuseProof !== void 0 && isCompleteAppPayloadMetadata(metadata);
|
|
28
34
|
}
|
|
29
35
|
function requiresCacheEntryReuseProof(origin) {
|
|
30
36
|
switch (origin.origin) {
|
|
37
|
+
case "committed-cache":
|
|
31
38
|
case "fresh": return false;
|
|
32
39
|
case "visited-cache": return true;
|
|
33
40
|
default: throw new Error("[vinext] Unknown App Router payload origin: " + String(origin));
|
|
@@ -70,14 +77,21 @@ function resolveServerActionRequestState(options) {
|
|
|
70
77
|
function resolvePendingNavigationCommitDispositionDecision(options) {
|
|
71
78
|
const traceFields = createPendingNavigationTraceFields(options);
|
|
72
79
|
const targetSnapshot = createPendingRouteSnapshot(options.pending);
|
|
73
|
-
const
|
|
80
|
+
const token = createPendingNavigationOperationToken({
|
|
74
81
|
pending: options.pending,
|
|
75
82
|
routeManifest: options.routeManifest ?? null,
|
|
76
83
|
startedNavigationId: options.startedNavigationId,
|
|
77
84
|
targetSnapshot
|
|
78
|
-
})
|
|
85
|
+
});
|
|
86
|
+
if (options.pending.action.operation.navigationCommitKind === "detached" && options.currentState.activeOperation?.navigationId === options.startedNavigationId && options.currentState.activeOperation.navigationCommitKind === "authoritative") return {
|
|
87
|
+
disposition: "skip",
|
|
88
|
+
preserveElementIds: [],
|
|
89
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.staleOperation, traceFields)
|
|
90
|
+
};
|
|
91
|
+
const visibleCommitVersion = options.currentState.activeOperation?.navigationId === options.startedNavigationId && options.currentState.activeOperation.navigationCommitKind === "detached" && options.pending.action.operation.navigationCommitKind === "authoritative" ? options.pending.action.operation.startedVisibleCommitVersion : options.currentState.visibleCommitVersion;
|
|
92
|
+
const verdict = verifyOperationTokenForCommit(token, {
|
|
79
93
|
activeNavigationId: options.activeNavigationId,
|
|
80
|
-
visibleCommitVersion
|
|
94
|
+
visibleCommitVersion
|
|
81
95
|
});
|
|
82
96
|
if (!verdict.authorized) return {
|
|
83
97
|
disposition: "skip",
|
|
@@ -126,7 +140,7 @@ function createMountedParallelSlotSnapshots(elements) {
|
|
|
126
140
|
}
|
|
127
141
|
function createVisibleRouteSnapshot(state) {
|
|
128
142
|
const displayUrl = createSnapshotPathAndSearch(state.navigationSnapshot);
|
|
129
|
-
const matchedUrl = normalizeNavigationSnapshotMatchedUrl(state.navigationSnapshot.pathname);
|
|
143
|
+
const matchedUrl = state.interception?.targetMatchedUrl ?? normalizeNavigationSnapshotMatchedUrl(state.navigationSnapshot.pathname);
|
|
130
144
|
return {
|
|
131
145
|
displayUrl,
|
|
132
146
|
interception: state.interception,
|
|
@@ -144,7 +158,7 @@ function createVisibleRouteSnapshot(state) {
|
|
|
144
158
|
}
|
|
145
159
|
function createPendingRouteSnapshot(pending) {
|
|
146
160
|
const displayUrl = createSnapshotPathAndSearch(pending.action.navigationSnapshot);
|
|
147
|
-
const matchedUrl = normalizeNavigationSnapshotMatchedUrl(pending.action.navigationSnapshot.pathname);
|
|
161
|
+
const matchedUrl = pending.action.interception?.targetMatchedUrl ?? normalizeNavigationSnapshotMatchedUrl(pending.action.navigationSnapshot.pathname);
|
|
148
162
|
return {
|
|
149
163
|
displayUrl,
|
|
150
164
|
interception: pending.action.interception,
|
|
@@ -188,6 +202,7 @@ function planPendingRootBoundaryFlightResponse(options) {
|
|
|
188
202
|
kind: "flightResponseArrived",
|
|
189
203
|
result: {
|
|
190
204
|
...cacheEntryReuseProof ? { cacheEntryReuseProof } : {},
|
|
205
|
+
...options.pending.restoredHistorySnapshot ? { restoredHistorySnapshot: true } : {},
|
|
191
206
|
href: options.targetHref ?? options.targetSnapshot.displayUrl,
|
|
192
207
|
targetSnapshot: options.targetSnapshot
|
|
193
208
|
},
|
|
@@ -292,6 +307,8 @@ async function createPendingNavigationCommit(options) {
|
|
|
292
307
|
operation: createOperationRecord({
|
|
293
308
|
id: options.renderId,
|
|
294
309
|
lane: options.operationLane,
|
|
310
|
+
navigationCommitKind: options.navigationCommitKind,
|
|
311
|
+
navigationId: options.navigationId,
|
|
295
312
|
startedVisibleCommitVersion: options.currentState.visibleCommitVersion
|
|
296
313
|
}),
|
|
297
314
|
previousNextUrl,
|
|
@@ -312,4 +329,4 @@ async function createPendingNavigationCommit(options) {
|
|
|
312
329
|
};
|
|
313
330
|
}
|
|
314
331
|
//#endregion
|
|
315
|
-
export { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, createBfcacheSegmentStateKeyMap, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createInitialBfcacheIdMap, createNextBfcacheIdMap, createPendingNavigationCommit, isCacheRestorableAppPayloadMetadata, isHistoryStateBfcacheVersionCurrent, preserveBfcacheIdsForMergedElements, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent, resolveInterceptionContextFromPreviousNextUrl, resolvePendingNavigationCommitDispositionDecision, resolveServerActionRequestState };
|
|
332
|
+
export { COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, createBfcacheSegmentStateKeyMap, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createInitialBfcacheIdMap, createNextBfcacheIdMap, createPendingNavigationCommit, isCacheRestorableAppPayloadMetadata, isCompleteAppPayloadMetadata, isHistoryStateBfcacheVersionCurrent, preserveBfcacheIdsForMergedElements, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent, resolveInterceptionContextFromPreviousNextUrl, resolvePendingNavigationCommitDispositionDecision, resolveServerActionRequestState };
|
|
@@ -49,7 +49,12 @@ type ClassifiedPendingNavigationCommit = {
|
|
|
49
49
|
trace: NavigationTrace;
|
|
50
50
|
};
|
|
51
51
|
declare function applyApprovedVisibleCommit(state: AppRouterState, commit: ApprovedVisibleCommit): AppRouterState;
|
|
52
|
-
declare function approveHmrVisibleCommit(
|
|
52
|
+
declare function approveHmrVisibleCommit(options: {
|
|
53
|
+
currentState: AppRouterState;
|
|
54
|
+
pending: PendingNavigationCommit;
|
|
55
|
+
routeManifest?: RouteManifest | null;
|
|
56
|
+
targetHref: string;
|
|
57
|
+
}): CommitApproval;
|
|
53
58
|
declare function approvePendingNavigationCommit(options: {
|
|
54
59
|
activeNavigationId: number;
|
|
55
60
|
currentState: AppRouterState;
|