vinext 0.1.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -30
- package/dist/build/css-url-assets.d.ts +3 -1
- package/dist/build/css-url-assets.js +18 -1
- package/dist/build/inject-pregenerated-paths.d.ts +7 -0
- package/dist/build/inject-pregenerated-paths.js +21 -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-server-entry.d.ts +1 -0
- package/dist/build/prerender-server-entry.js +49 -0
- package/dist/build/prerender-server-pool.d.ts +44 -0
- package/dist/build/prerender-server-pool.js +194 -0
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +98 -27
- 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 +12 -2
- package/dist/build/standalone.js +2 -0
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/check.d.ts +4 -6
- package/dist/check.js +48 -11
- 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 +112 -96
- 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/vinext-next-data.d.ts +4 -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 +45 -19
- package/dist/config/next-config.d.ts +41 -9
- package/dist/config/next-config.js +60 -3
- package/dist/config/prerender.d.ts +34 -0
- package/dist/config/prerender.js +55 -0
- package/dist/entries/app-browser-entry.js +5 -1
- package/dist/entries/app-rsc-entry.d.ts +5 -3
- package/dist/entries/app-rsc-entry.js +44 -10
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/pages-client-entry.d.ts +3 -0
- package/dist/entries/pages-client-entry.js +28 -3
- package/dist/entries/pages-server-entry.js +23 -6
- 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 +482 -120
- 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 +209 -99
- 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 +9 -2
- 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 +272 -0
- package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
- package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +44 -20
- 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/fonts.js +1 -1
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +530 -0
- package/dist/plugins/og-assets.js +2 -1
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
- package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
- package/dist/plugins/sass.d.ts +17 -1
- package/dist/plugins/sass.js +74 -1
- package/dist/plugins/styled-jsx.d.ts +16 -0
- package/dist/plugins/styled-jsx.js +149 -0
- 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 +23 -2
- package/dist/routing/app-route-graph.js +138 -38
- package/dist/routing/file-matcher.d.ts +11 -1
- package/dist/routing/file-matcher.js +18 -3
- 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 +198 -57
- 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 +1 -1
- package/dist/server/app-browser-server-action-client.js +8 -7
- package/dist/server/app-browser-state.d.ts +12 -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 +42 -24
- 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 +2 -1
- package/dist/server/app-fallback-renderer.js +10 -6
- 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.js +2 -1
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +5 -4
- 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 +27 -7
- package/dist/server/app-page-dispatch.d.ts +1 -0
- package/dist/server/app-page-dispatch.js +26 -8
- package/dist/server/app-page-element-builder.d.ts +2 -1
- package/dist/server/app-page-element-builder.js +59 -4
- package/dist/server/app-page-execution.js +2 -1
- package/dist/server/app-page-probe.js +5 -0
- package/dist/server/app-page-render-identity.d.ts +2 -0
- package/dist/server/app-page-render-identity.js +3 -2
- package/dist/server/app-page-render.d.ts +2 -0
- package/dist/server/app-page-render.js +85 -16
- package/dist/server/app-page-request.d.ts +14 -0
- package/dist/server/app-page-request.js +69 -4
- package/dist/server/app-page-response.d.ts +7 -0
- package/dist/server/app-page-response.js +16 -4
- package/dist/server/app-page-route-wiring.d.ts +8 -1
- package/dist/server/app-page-route-wiring.js +32 -18
- 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 +7 -1
- package/dist/server/app-page-stream.js +3 -1
- package/dist/server/app-route-handler-execution.js +5 -1
- 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-tree-prefetch.d.ts +43 -0
- package/dist/server/app-route-tree-prefetch.js +187 -0
- package/dist/server/app-router-entry.js +9 -2
- package/dist/server/app-rsc-cache-busting.d.ts +2 -1
- package/dist/server/app-rsc-cache-busting.js +9 -4
- package/dist/server/app-rsc-handler.d.ts +7 -0
- package/dist/server/app-rsc-handler.js +148 -39
- package/dist/server/app-rsc-render-mode.d.ts +3 -2
- package/dist/server/app-rsc-render-mode.js +4 -1
- package/dist/server/app-rsc-request-normalization.d.ts +6 -6
- package/dist/server/app-rsc-request-normalization.js +10 -8
- package/dist/server/app-segment-config.d.ts +11 -0
- package/dist/server/app-segment-config.js +62 -6
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +61 -30
- package/dist/server/app-ssr-entry.d.ts +3 -0
- package/dist/server/app-ssr-entry.js +13 -5
- package/dist/server/app-ssr-stream.d.ts +7 -3
- package/dist/server/app-ssr-stream.js +10 -6
- package/dist/server/app-visited-response-cache.d.ts +6 -0
- package/dist/server/app-visited-response-cache.js +3 -1
- package/dist/server/cache-control.d.ts +3 -1
- package/dist/server/cache-control.js +13 -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.d.ts +11 -1
- package/dist/server/dev-server.js +94 -35
- 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 +7 -15
- package/dist/server/headers.js +11 -18
- 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 +3 -2
- package/dist/server/isr-cache.js +9 -5
- 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-data-route.d.ts +4 -2
- package/dist/server/pages-data-route.js +18 -4
- package/dist/server/pages-dev-module-url.d.ts +2 -1
- package/dist/server/pages-dev-module-url.js +6 -3
- package/dist/server/pages-node-compat.d.ts +19 -1
- package/dist/server/pages-node-compat.js +81 -4
- package/dist/server/pages-page-data.d.ts +33 -1
- package/dist/server/pages-page-data.js +62 -33
- package/dist/server/pages-page-handler.d.ts +2 -1
- package/dist/server/pages-page-handler.js +38 -19
- package/dist/server/pages-page-response.d.ts +8 -0
- package/dist/server/pages-page-response.js +7 -3
- package/dist/server/pages-request-pipeline.d.ts +9 -5
- package/dist/server/pages-request-pipeline.js +55 -7
- 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 +5 -3
- package/dist/server/prod-server.js +68 -39
- package/dist/server/request-pipeline.js +2 -1
- package/dist/server/seed-cache.js +4 -4
- 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-handler.js +8 -1
- package/dist/shims/cache.js +22 -15
- package/dist/shims/cdn-cache.js +1 -1
- package/dist/shims/dynamic-preload-chunks.js +2 -1
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +77 -52
- package/dist/shims/form.d.ts +4 -2
- package/dist/shims/form.js +37 -43
- package/dist/shims/headers.d.ts +7 -1
- package/dist/shims/headers.js +17 -3
- package/dist/shims/image.js +75 -14
- package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
- package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
- 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 +3 -15
- package/dist/shims/internal/hybrid-client-route-owner.js +40 -58
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +10 -5
- package/dist/shims/internal/pages-data-fetch-dedup.js +84 -14
- package/dist/shims/internal/pages-data-target.d.ts +18 -12
- package/dist/shims/internal/pages-data-target.js +97 -13
- 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.d.ts +1 -1
- package/dist/shims/link.js +224 -58
- package/dist/shims/navigation.d.ts +19 -3
- package/dist/shims/navigation.js +245 -47
- package/dist/shims/request-context.js +18 -0
- 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 +387 -102
- package/dist/shims/server.js +3 -2
- package/dist/shims/slot.js +3 -6
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -1
- 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 +3 -3
- package/dist/utils/project.d.ts +48 -2
- package/dist/utils/project.js +225 -4
- package/dist/utils/protocol-headers.d.ts +23 -0
- package/dist/utils/protocol-headers.js +23 -0
- package/dist/utils/react-version.d.ts +4 -0
- package/dist/utils/react-version.js +44 -0
- package/dist/utils/vite-version.d.ts +2 -0
- package/dist/utils/vite-version.js +11 -1
- package/package.json +47 -2
- package/dist/deploy.d.ts +0 -197
- package/dist/deploy.js +0 -1040
- package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
- /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
|
@@ -2,7 +2,7 @@ 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
4
|
import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
5
|
-
import { shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
|
|
5
|
+
import { resolveServerActionOperationLane, 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(),
|
|
@@ -23,7 +23,7 @@ type ClientServerActionDeps = {
|
|
|
23
23
|
commitSameUrlNavigatePayload(elements: Promise<AppElements>, actionInitiation: ClientServerActionInitiation, returnValue: ServerActionResult["returnValue"] | undefined, revalidation: ServerActionRevalidationKind): Promise<unknown>;
|
|
24
24
|
navigationPlanner: typeof navigationPlanner;
|
|
25
25
|
performHardNavigation(url: string, historyMode?: "assign" | "replace"): void;
|
|
26
|
-
renderRedirectPayload(elements: AppElements, target: ActionRedirectTarget, actionInitiation: ClientServerActionInitiation): void;
|
|
26
|
+
renderRedirectPayload(elements: AppElements, target: ActionRedirectTarget, actionInitiation: ClientServerActionInitiation, revalidation: ServerActionRevalidationKind): void;
|
|
27
27
|
syncCurrentHistoryState(previousNextUrl: string | null, bfcacheIds: Readonly<Record<string, string>>): void;
|
|
28
28
|
syncServerActionHttpFallbackHead(status: number | null): void;
|
|
29
29
|
};
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import { hasBasePath } from "../utils/base-path.js";
|
|
1
2
|
import { ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER } from "./headers.js";
|
|
2
3
|
import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
|
|
3
4
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
4
5
|
import "./app-elements.js";
|
|
5
6
|
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createServerActionRequestUrl } from "./app-rsc-cache-busting.js";
|
|
6
|
-
import { createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult } from "./app-browser-action-result.js";
|
|
7
|
+
import { createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult, shouldSyncServerActionHttpFallbackHead } from "./app-browser-action-result.js";
|
|
7
8
|
import { resolveServerActionRequestState } from "./app-browser-state.js";
|
|
8
9
|
import { applyServerActionResultDecision } from "./app-browser-server-action-navigation.js";
|
|
9
10
|
import { throwOnServerActionNotFound } from "./server-action-not-found.js";
|
|
10
11
|
import { createFromFetch, createTemporaryReferenceSet, encodeReply } from "@vitejs/plugin-rsc/browser";
|
|
11
12
|
//#region src/server/app-browser-server-action-client.ts
|
|
12
|
-
function resolveActionRedirectTarget(response, performHardNavigation) {
|
|
13
|
+
function resolveActionRedirectTarget(response, basePath, performHardNavigation) {
|
|
13
14
|
const actionRedirect = response.headers.get(ACTION_REDIRECT_HEADER);
|
|
14
15
|
if (!actionRedirect) return null;
|
|
15
16
|
if (isDangerousScheme(actionRedirect)) {
|
|
@@ -25,7 +26,7 @@ function resolveActionRedirectTarget(response, performHardNavigation) {
|
|
|
25
26
|
if (!baseDir.endsWith("/")) baseDir += "/";
|
|
26
27
|
redirectUrl = new URL(actionRedirect, `${baseParsed.origin}${baseDir}${baseParsed.search}`);
|
|
27
28
|
}
|
|
28
|
-
if (redirectUrl.origin !== window.location.origin) {
|
|
29
|
+
if (redirectUrl.origin !== window.location.origin || basePath !== "" && !hasBasePath(redirectUrl.pathname, basePath)) {
|
|
29
30
|
performHardNavigation(actionRedirect);
|
|
30
31
|
return null;
|
|
31
32
|
}
|
|
@@ -60,6 +61,7 @@ async function invokeClientServerAction(id, args, actionInitiation, deps) {
|
|
|
60
61
|
actionId: id,
|
|
61
62
|
basePath: deps.basePath,
|
|
62
63
|
elements: actionInitiation.routerState.elements,
|
|
64
|
+
interceptionContext: actionInitiation.routerState.interception !== null ? actionInitiation.routerState.interceptionContext : null,
|
|
63
65
|
previousNextUrl: actionInitiation.routerState.previousNextUrl
|
|
64
66
|
}).headers;
|
|
65
67
|
const fetchResponse = await fetch(createServerActionRequestUrl(actionInitiation.path), {
|
|
@@ -69,7 +71,7 @@ async function invokeClientServerAction(id, args, actionInitiation, deps) {
|
|
|
69
71
|
});
|
|
70
72
|
throwOnServerActionNotFound(fetchResponse, id);
|
|
71
73
|
const hasActionRedirect = fetchResponse.headers.has(ACTION_REDIRECT_HEADER);
|
|
72
|
-
const actionRedirectTarget = resolveActionRedirectTarget(fetchResponse, (url, historyMode) => deps.performHardNavigation(url, historyMode));
|
|
74
|
+
const actionRedirectTarget = resolveActionRedirectTarget(fetchResponse, deps.basePath, (url, historyMode) => deps.performHardNavigation(url, historyMode));
|
|
73
75
|
if (hasActionRedirect && !actionRedirectTarget) return void 0;
|
|
74
76
|
const actionResultFacts = createServerActionResultFacts({
|
|
75
77
|
actionRedirectHref: actionRedirectTarget?.href ?? null,
|
|
@@ -100,14 +102,13 @@ async function invokeClientServerAction(id, args, actionInitiation, deps) {
|
|
|
100
102
|
if (revalidation === "none" && shouldClearClientNavigationCachesForServerActionResult(result, revalidation)) deps.clearClientNavigationCaches();
|
|
101
103
|
if (actionRedirectTarget) {
|
|
102
104
|
if (isServerActionResult(result) && result.root !== void 0) {
|
|
103
|
-
deps.renderRedirectPayload(AppElementsWire.decode(result.root), actionRedirectTarget, actionInitiation);
|
|
105
|
+
deps.renderRedirectPayload(AppElementsWire.decode(result.root), actionRedirectTarget, actionInitiation, revalidation);
|
|
104
106
|
throw new ServerActionRedirectError(actionRedirectTarget);
|
|
105
107
|
}
|
|
106
108
|
deps.performHardNavigation(actionRedirectTarget.href);
|
|
107
109
|
return;
|
|
108
110
|
}
|
|
109
|
-
|
|
110
|
-
deps.syncServerActionHttpFallbackHead(hasSameUrlRerenderPayload ? null : fetchResponse.status);
|
|
111
|
+
deps.syncServerActionHttpFallbackHead(shouldSyncServerActionHttpFallbackHead(result) ? fetchResponse.status : null);
|
|
111
112
|
if (isServerActionResult(result)) {
|
|
112
113
|
if (result.root !== void 0) {
|
|
113
114
|
const returnValue = result.returnValue && !result.returnValue.ok ? {
|
|
@@ -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
|
};
|
|
@@ -99,6 +107,7 @@ type ResolveServerActionRequestStateOptions = {
|
|
|
99
107
|
actionId: string;
|
|
100
108
|
basePath: string;
|
|
101
109
|
elements: AppElements;
|
|
110
|
+
interceptionContext?: string | null;
|
|
102
111
|
previousNextUrl: string | null;
|
|
103
112
|
};
|
|
104
113
|
type ResolveServerActionRequestStateResult = {
|
|
@@ -126,6 +135,8 @@ declare function resolvePendingNavigationCommitDispositionDecision(options: {
|
|
|
126
135
|
}): PendingNavigationCommitDispositionDecision;
|
|
127
136
|
declare function createPendingNavigationCommit(options: {
|
|
128
137
|
currentState: AppRouterState;
|
|
138
|
+
navigationCommitKind?: "authoritative" | "detached";
|
|
139
|
+
navigationId?: number;
|
|
129
140
|
nextElements: Promise<AppElements>;
|
|
130
141
|
navigationSnapshot: ClientNavigationRenderSnapshot;
|
|
131
142
|
operationLane: OperationLane;
|
|
@@ -137,4 +148,4 @@ declare function createPendingNavigationCommit(options: {
|
|
|
137
148
|
type: "navigate" | "replace" | "traverse";
|
|
138
149
|
}): Promise<PendingNavigationCommit>;
|
|
139
150
|
//#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 };
|
|
151
|
+
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 };
|
|
@@ -13,21 +13,28 @@ import { navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts }
|
|
|
13
13
|
import { createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
14
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));
|
|
@@ -61,7 +68,7 @@ function resolveServerActionRequestState(options) {
|
|
|
61
68
|
const headers = createRscRequestHeaders();
|
|
62
69
|
headers.set(RSC_ACTION_HEADER, options.actionId);
|
|
63
70
|
headers.set(NEXT_ACTION_HEADER, options.actionId);
|
|
64
|
-
const interceptionContext = resolveInterceptionContextFromPreviousNextUrl(options.previousNextUrl, options.basePath);
|
|
71
|
+
const interceptionContext = resolveInterceptionContextFromPreviousNextUrl(options.previousNextUrl, options.basePath) ?? options.interceptionContext ?? null;
|
|
65
72
|
if (interceptionContext !== null) headers.set(VINEXT_INTERCEPTION_CONTEXT_HEADER, interceptionContext);
|
|
66
73
|
const mountedSlotsHeader = getMountedSlotIdsHeader(options.elements);
|
|
67
74
|
if (mountedSlotsHeader !== null) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, mountedSlotsHeader);
|
|
@@ -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;
|
|
@@ -17,6 +17,8 @@ function commitOperationRecord(operation, visibleCommitVersion) {
|
|
|
17
17
|
return {
|
|
18
18
|
id: operation.id,
|
|
19
19
|
lane: operation.lane,
|
|
20
|
+
...operation.navigationCommitKind !== void 0 ? { navigationCommitKind: operation.navigationCommitKind } : {},
|
|
21
|
+
...operation.navigationId !== void 0 ? { navigationId: operation.navigationId } : {},
|
|
20
22
|
startedVisibleCommitVersion: operation.startedVisibleCommitVersion,
|
|
21
23
|
state: "committed",
|
|
22
24
|
visibleCommitVersion
|
|
@@ -56,9 +58,23 @@ function reduceApprovedVisibleCommitState(state, commit) {
|
|
|
56
58
|
const { action } = commit;
|
|
57
59
|
switch (action.type) {
|
|
58
60
|
case "traverse":
|
|
59
|
-
case "navigate":
|
|
60
|
-
|
|
61
|
-
const
|
|
61
|
+
case "navigate":
|
|
62
|
+
case "replace": {
|
|
63
|
+
const bfcacheCompatiblePreserveElementIds = action.reuseCurrentBfcacheIds && action.operation.lane !== "refresh" ? commit.decision.preserveElementIds.filter((id) => {
|
|
64
|
+
const previousBfcacheId = state.bfcacheIds[id];
|
|
65
|
+
return previousBfcacheId !== void 0 && action.bfcacheIds[id] === previousBfcacheId;
|
|
66
|
+
}) : [];
|
|
67
|
+
const preservedSlotOwnerElementIdSet = new Set(bfcacheCompatiblePreserveElementIds);
|
|
68
|
+
const preservePreviousSlotIds = action.reuseCurrentBfcacheIds ? commit.decision.preservePreviousSlotIds.filter((slotId) => {
|
|
69
|
+
const targetBinding = action.slotBindings.find((binding) => binding.slotId === slotId);
|
|
70
|
+
return targetBinding?.ownerLayoutId !== null && targetBinding?.ownerLayoutId !== void 0 && preservedSlotOwnerElementIdSet.has(targetBinding.ownerLayoutId);
|
|
71
|
+
}) : [];
|
|
72
|
+
const hmrPreservedSlotOwnerLayoutIds = action.operation.lane === "hmr" ? bfcacheCompatiblePreserveElementIds.filter((id) => preservePreviousSlotIds.some((slotId) => {
|
|
73
|
+
return action.slotBindings.find((binding) => binding.slotId === slotId)?.ownerLayoutId === id;
|
|
74
|
+
})) : [];
|
|
75
|
+
const hmrPreserveElementIds = action.operation.lane === "hmr" && state.routeId === action.routeId && Object.hasOwn(state.elements, state.routeId) ? [state.routeId, ...hmrPreservedSlotOwnerLayoutIds] : hmrPreservedSlotOwnerLayoutIds;
|
|
76
|
+
const hmrUniquePreserveElementIds = hmrPreserveElementIds.length > 1 ? [...new Set(hmrPreserveElementIds)] : hmrPreserveElementIds;
|
|
77
|
+
const preserveElementIds = action.operation.lane === "hmr" ? hmrUniquePreserveElementIds : bfcacheCompatiblePreserveElementIds;
|
|
62
78
|
const mergedElements = mergeElements(state.elements, action.elements, {
|
|
63
79
|
clearAbsentSlots: action.type === "traverse" || !action.reuseCurrentBfcacheIds,
|
|
64
80
|
preserveAbsentSlots: action.reuseCurrentBfcacheIds && commit.decision.preserveAbsentSlots,
|
|
@@ -84,20 +100,6 @@ function reduceApprovedVisibleCommitState(state, commit) {
|
|
|
84
100
|
slotBindings: mergeSlotBindings(state.slotBindings, action.slotBindings, action.layoutIds, preservePreviousSlotIds)
|
|
85
101
|
}, action.operation);
|
|
86
102
|
}
|
|
87
|
-
case "replace": return commitVisibleRouterState(state, {
|
|
88
|
-
bfcacheIds: action.bfcacheIds,
|
|
89
|
-
elements: action.elements,
|
|
90
|
-
interception: action.interception,
|
|
91
|
-
interceptionContext: action.interceptionContext,
|
|
92
|
-
layoutFlags: action.layoutFlags,
|
|
93
|
-
layoutIds: action.layoutIds,
|
|
94
|
-
navigationSnapshot: action.navigationSnapshot,
|
|
95
|
-
previousNextUrl: action.previousNextUrl,
|
|
96
|
-
renderId: action.renderId,
|
|
97
|
-
rootLayoutTreePath: action.rootLayoutTreePath,
|
|
98
|
-
routeId: action.routeId,
|
|
99
|
-
slotBindings: action.slotBindings
|
|
100
|
-
}, action.operation);
|
|
101
103
|
default: {
|
|
102
104
|
const _exhaustive = action.type;
|
|
103
105
|
throw new Error("[vinext] Unknown router action: " + String(_exhaustive));
|
|
@@ -176,14 +178,28 @@ function addCommitTransactionTrace(decision, pending) {
|
|
|
176
178
|
default: throw new Error("[vinext] Unknown commit decision: " + String(decision));
|
|
177
179
|
}
|
|
178
180
|
}
|
|
179
|
-
function approveHmrVisibleCommit(
|
|
181
|
+
function approveHmrVisibleCommit(options) {
|
|
182
|
+
const { currentState, pending } = options;
|
|
180
183
|
if (pending.action.operation.lane !== "hmr") throw new Error("[vinext] HMR visible commit approval requires an HMR pending operation");
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
const tracedDecision = addCommitTransactionTrace(resolvePendingNavigationCommitDecision({
|
|
185
|
+
activeNavigationId: pending.action.operation.id,
|
|
186
|
+
currentState,
|
|
187
|
+
pending,
|
|
188
|
+
routeManifest: options.routeManifest,
|
|
189
|
+
startedNavigationId: pending.action.operation.id,
|
|
190
|
+
targetHref: options.targetHref
|
|
191
|
+
}), pending);
|
|
192
|
+
if (tracedDecision.disposition === "commit") return {
|
|
193
|
+
approvedCommit: createApprovedVisibleCommit({
|
|
194
|
+
decision: tracedDecision,
|
|
195
|
+
pending
|
|
196
|
+
}),
|
|
197
|
+
decision: tracedDecision
|
|
198
|
+
};
|
|
199
|
+
return {
|
|
200
|
+
approvedCommit: null,
|
|
201
|
+
decision: tracedDecision
|
|
202
|
+
};
|
|
187
203
|
}
|
|
188
204
|
function approvePendingNavigationCommit(options) {
|
|
189
205
|
const decision = addCommitTransactionTrace(resolvePendingNavigationCommitDecision({
|
|
@@ -213,6 +229,8 @@ function approvePendingNavigationCommit(options) {
|
|
|
213
229
|
async function resolveAndClassifyNavigationCommit(options) {
|
|
214
230
|
const pending = await createPendingNavigationCommit({
|
|
215
231
|
currentState: options.currentState,
|
|
232
|
+
navigationCommitKind: void 0,
|
|
233
|
+
navigationId: options.startedNavigationId,
|
|
216
234
|
nextElements: options.nextElements,
|
|
217
235
|
navigationSnapshot: options.navigationSnapshot,
|
|
218
236
|
operationLane: options.operationLane,
|
|
@@ -6,6 +6,7 @@ import { ReactNode } from "react";
|
|
|
6
6
|
//#region src/server/app-elements-wire.d.ts
|
|
7
7
|
declare const APP_ARTIFACT_COMPATIBILITY_KEY = "__artifactCompatibility";
|
|
8
8
|
declare const APP_CACHE_ENTRY_REUSE_PROOF_KEY = "__cacheEntryReuseProof";
|
|
9
|
+
declare const APP_DYNAMIC_STALE_TIME_KEY = "__dynamicStaleTime";
|
|
9
10
|
declare const APP_INTERCEPTION_KEY = "__interception";
|
|
10
11
|
declare const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
|
|
11
12
|
declare const APP_LAYOUT_IDS_KEY = "__layoutIds";
|
|
@@ -70,6 +71,7 @@ type LayoutFlags = Readonly<Record<string, "s" | "d">>;
|
|
|
70
71
|
type AppElementsMetadata = {
|
|
71
72
|
artifactCompatibility: ArtifactCompatibilityEnvelope;
|
|
72
73
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
74
|
+
dynamicStaleTimeSeconds?: number;
|
|
73
75
|
interception: AppElementsInterception | null;
|
|
74
76
|
interceptionContext: string | null;
|
|
75
77
|
layoutIds: readonly string[];
|
|
@@ -100,6 +102,7 @@ type AppElementsWireElementKey = {
|
|
|
100
102
|
treePath: string;
|
|
101
103
|
};
|
|
102
104
|
type AppElementsWireMetadataInput = {
|
|
105
|
+
dynamicStaleTimeSeconds?: number;
|
|
103
106
|
interception?: AppElementsInterception | null;
|
|
104
107
|
interceptionContext: string | null;
|
|
105
108
|
layoutIds?: readonly string[];
|
|
@@ -109,6 +112,7 @@ type AppElementsWireMetadataInput = {
|
|
|
109
112
|
sourcePage?: string | null;
|
|
110
113
|
};
|
|
111
114
|
type AppElementsWireMetadataEntries = Readonly<{
|
|
115
|
+
[APP_DYNAMIC_STALE_TIME_KEY]?: number;
|
|
112
116
|
[APP_ROUTE_KEY]: string;
|
|
113
117
|
[APP_INTERCEPTION_KEY]?: AppElementsInterception;
|
|
114
118
|
[APP_INTERCEPTION_CONTEXT_KEY]: string | null;
|
|
@@ -123,10 +127,11 @@ type AppElementsWireMetadataEntries = Readonly<{
|
|
|
123
127
|
* known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements
|
|
124
128
|
* which only carry render-time values.
|
|
125
129
|
*/
|
|
126
|
-
type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | RenderObservation | readonly string[] | readonly AppElementsSlotBinding[]>>;
|
|
130
|
+
type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | RenderObservation | number | readonly string[] | readonly AppElementsSlotBinding[]>>;
|
|
127
131
|
type AppElementsWireKeys = {
|
|
128
132
|
readonly artifactCompatibility: typeof APP_ARTIFACT_COMPATIBILITY_KEY;
|
|
129
133
|
readonly cacheEntryReuseProof: typeof APP_CACHE_ENTRY_REUSE_PROOF_KEY;
|
|
134
|
+
readonly dynamicStaleTime: typeof APP_DYNAMIC_STALE_TIME_KEY;
|
|
130
135
|
readonly interception: typeof APP_INTERCEPTION_KEY;
|
|
131
136
|
readonly interceptionContext: typeof APP_INTERCEPTION_CONTEXT_KEY;
|
|
132
137
|
readonly layoutIds: typeof APP_LAYOUT_IDS_KEY;
|
|
@@ -149,6 +154,7 @@ type AppElementsWireCodec = {
|
|
|
149
154
|
element: ReactNode | AppElements;
|
|
150
155
|
artifactCompatibility?: ArtifactCompatibilityEnvelope;
|
|
151
156
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
157
|
+
dynamicStaleTimeSeconds?: number;
|
|
152
158
|
layoutFlags: LayoutFlags;
|
|
153
159
|
renderObservation?: RenderObservation;
|
|
154
160
|
skipDisposition?: ClientReuseManifestSkipDisposition;
|
|
@@ -182,6 +188,7 @@ declare function buildOutgoingAppPayload(input: {
|
|
|
182
188
|
element: ReactNode | AppElements;
|
|
183
189
|
artifactCompatibility?: ArtifactCompatibilityEnvelope;
|
|
184
190
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
191
|
+
dynamicStaleTimeSeconds?: number;
|
|
185
192
|
layoutFlags: LayoutFlags;
|
|
186
193
|
renderObservation?: RenderObservation;
|
|
187
194
|
skipDisposition?: ClientReuseManifestSkipDisposition;
|
|
@@ -189,4 +196,4 @@ declare function buildOutgoingAppPayload(input: {
|
|
|
189
196
|
declare function readAppElementsMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
|
|
190
197
|
declare const AppElementsWire: AppElementsWireCodec;
|
|
191
198
|
//#endregion
|
|
192
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
|
|
199
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
|