vinext 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +1 -1
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +1 -1
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay.js +1 -1
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/next-config.d.ts +19 -0
- package/dist/config/next-config.js +64 -1
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
- package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
- package/dist/entries/app-rsc-entry.js +17 -48
- package/dist/entries/app-rsc-manifest.js +3 -4
- package/dist/entries/app-ssr-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +33 -8
- package/dist/index.js +83 -70
- package/dist/init-cloudflare.d.ts +1 -3
- package/dist/init-cloudflare.js +10 -48
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +4 -0
- package/dist/plugins/extensionless-dynamic-import.js +6 -2
- package/dist/plugins/next-intl-catalog.d.ts +12 -0
- package/dist/plugins/next-intl-catalog.js +85 -0
- package/dist/plugins/pages-node-externals.d.ts +1 -0
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/use-cache-callable.d.ts +1 -1
- package/dist/plugins/use-cache-callable.js +136 -94
- package/dist/routing/app-route-graph.d.ts +6 -0
- package/dist/routing/app-route-graph.js +9 -1
- package/dist/server/api-handler.js +19 -4
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +79 -63
- package/dist/server/app-browser-history-controller.d.ts +5 -4
- package/dist/server/app-browser-history-controller.js +93 -15
- package/dist/server/app-browser-navigation-controller.d.ts +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -2
- package/dist/server/app-browser-rsc-redirect.js +4 -4
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +4 -3
- package/dist/server/app-browser-state.d.ts +2 -4
- package/dist/server/app-browser-state.js +9 -4
- package/dist/server/app-browser-supplemental-refresh.js +16 -1
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-browser-visible-commit.js +2 -12
- package/dist/server/app-elements-wire.d.ts +6 -38
- package/dist/server/app-elements-wire.js +4 -41
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-history-state.d.ts +2 -2
- package/dist/server/app-history-state.js +5 -2
- package/dist/server/app-mounted-layouts.d.ts +21 -0
- package/dist/server/app-mounted-layouts.js +67 -0
- package/dist/server/app-optimistic-routing.d.ts +19 -1
- package/dist/server/app-optimistic-routing.js +42 -2
- package/dist/server/app-page-boundary-render.js +7 -6
- package/dist/server/app-page-boundary.js +2 -2
- package/dist/server/app-page-cache-finalizer.d.ts +12 -1
- package/dist/server/app-page-cache-finalizer.js +70 -29
- package/dist/server/app-page-cache.d.ts +13 -1
- package/dist/server/app-page-cache.js +31 -9
- package/dist/server/app-page-dispatch.d.ts +5 -10
- package/dist/server/app-page-dispatch.js +84 -154
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +10 -9
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +99 -95
- package/dist/server/app-page-head.d.ts +13 -0
- package/dist/server/app-page-head.js +44 -16
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
- package/dist/server/app-page-layout-gate.d.ts +35 -0
- package/dist/server/app-page-layout-gate.js +50 -0
- package/dist/server/app-page-params.d.ts +0 -1
- package/dist/server/app-page-params.js +1 -14
- package/dist/server/app-page-probe.d.ts +3 -21
- package/dist/server/app-page-probe.js +4 -37
- package/dist/server/app-page-render.d.ts +2 -12
- package/dist/server/app-page-render.js +89 -220
- package/dist/server/app-page-request.d.ts +1 -3
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-response.js +3 -3
- package/dist/server/app-page-route-wiring.d.ts +13 -6
- package/dist/server/app-page-route-wiring.js +67 -61
- package/dist/server/app-page-rsc-render-status.d.ts +27 -1
- package/dist/server/app-page-rsc-render-status.js +121 -13
- package/dist/server/app-page-stream.d.ts +2 -0
- package/dist/server/app-page-stream.js +2 -2
- package/dist/server/app-pages-bridge.d.ts +4 -0
- package/dist/server/app-pages-bridge.js +7 -3
- package/dist/server/app-render-dependency.d.ts +11 -4
- package/dist/server/app-render-dependency.js +86 -38
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-route-handler-cache.js +2 -2
- package/dist/server/app-route-handler-dispatch.js +14 -9
- package/dist/server/app-route-handler-execution.js +8 -3
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-handler-runtime.js +17 -4
- package/dist/server/app-rsc-cache-busting.d.ts +2 -2
- package/dist/server/app-rsc-cache-busting.js +4 -4
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +9 -1
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +8 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +30 -24
- package/dist/server/app-rsc-request-normalization.d.ts +0 -4
- package/dist/server/app-rsc-request-normalization.js +1 -4
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +5 -3
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +7 -4
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +9 -8
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/app-visited-response-cache.d.ts +36 -1
- package/dist/server/app-visited-response-cache.js +46 -5
- package/dist/server/app-worker-stages.d.ts +25 -3
- package/dist/server/app-worker-stages.js +45 -6
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-server.js +4 -3
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +26 -1
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/multi-stage.d.ts +52 -11
- package/dist/server/multi-stage.js +13 -1
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/pages-api-route.js +28 -19
- package/dist/server/pages-media-type.d.ts +21 -1
- package/dist/server/pages-media-type.js +69 -5
- package/dist/server/pages-node-compat.js +52 -27
- package/dist/server/pages-page-handler.js +11 -20
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +2 -2
- package/dist/server/pages-request-stage-entry.js +14 -12
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/prod-server.js +5 -1
- package/dist/server/request-pipeline.d.ts +6 -0
- package/dist/server/request-pipeline.js +21 -1
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- package/dist/server/worker-stages.d.ts +16 -3
- package/dist/server/worker-stages.js +23 -4
- package/dist/shims/cache-handler.js +2 -2
- package/dist/shims/cache-request-state.d.ts +17 -20
- package/dist/shims/cache-request-state.js +16 -21
- package/dist/shims/cache-runtime.js +27 -11
- package/dist/shims/cache.d.ts +8 -7
- package/dist/shims/cache.js +17 -19
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- package/dist/shims/client-page-root.js +2 -2
- package/dist/shims/dynamic.js +9 -6
- package/dist/shims/error-boundary.js +2 -2
- package/dist/shims/fetch-cache-state.d.ts +5 -1
- package/dist/shims/fetch-cache-state.js +1 -3
- package/dist/shims/fetch-cache.d.ts +2 -1
- package/dist/shims/fetch-cache.js +34 -24
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +8 -23
- package/dist/shims/headers.js +17 -67
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +3 -1
- package/dist/shims/metadata.d.ts +23 -21
- package/dist/shims/metadata.js +62 -24
- package/dist/shims/navigation-server.js +1 -1
- package/dist/shims/navigation.d.ts +74 -7
- package/dist/shims/navigation.js +183 -29
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +2 -2
- package/dist/shims/slot.d.ts +12 -0
- package/dist/shims/slot.js +37 -9
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +2 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- package/dist/utils/project.d.ts +2 -2
- package/dist/utils/project.js +3 -16
- package/dist/utils/regex.d.ts +5 -0
- package/dist/utils/regex.js +11 -1
- package/dist/utils/text-stream.d.ts +10 -5
- package/dist/utils/text-stream.js +6 -6
- package/package.json +2 -1
- package/dist/build/layout-classification-types.d.ts +0 -60
- package/dist/build/layout-classification-types.js +0 -1
- package/dist/build/layout-classification.d.ts +0 -62
- package/dist/build/layout-classification.js +0 -98
- package/dist/build/route-classification-injector.d.ts +0 -33
- package/dist/build/route-classification-injector.js +0 -59
- package/dist/build/route-classification-manifest.d.ts +0 -54
- package/dist/build/route-classification-manifest.js +0 -143
- package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
- package/dist/server/app-browser-client-reuse-manifest.js +0 -101
- package/dist/server/app-layout-param-observation.d.ts +0 -42
- package/dist/server/app-layout-param-observation.js +0 -168
- package/dist/server/client-reuse-manifest.d.ts +0 -103
- package/dist/server/client-reuse-manifest.js +0 -209
- package/dist/server/skip-cache-proof.d.ts +0 -60
- package/dist/server/skip-cache-proof.js +0 -168
- package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
- package/dist/server/static-layout-client-reuse-proof.js +0 -33
- package/dist/utils/sorted-array.d.ts +0 -8
- package/dist/utils/sorted-array.js +0 -20
|
@@ -7,13 +7,14 @@ import { importModule, reportRequestError } from "./instrumentation.js";
|
|
|
7
7
|
import { mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
|
|
8
8
|
import { tracePagesApiHandler } from "./pages-execution-tracing.js";
|
|
9
9
|
import { DEFAULT_PAGES_API_BODY_SIZE_LIMIT, resolveBodyParserConfig } from "./pages-body-parser-config.js";
|
|
10
|
-
import { PagesBodyParseError,
|
|
10
|
+
import { PagesBodyParseError, createPagesBodyDecoder, isJsonMediaType } from "./pages-media-type.js";
|
|
11
11
|
import { performOnDemandRevalidate } from "./pages-revalidate.js";
|
|
12
12
|
import { attachPagesPreviewApi, attachPagesRequestCookies } from "./pages-node-compat.js";
|
|
13
13
|
import { finalizeEdgeApiResponse, isEdgeApiRuntime } from "./edge-api-runtime.js";
|
|
14
14
|
import { signalFromNodeResponse } from "./node-response-signal.js";
|
|
15
15
|
import { Buffer } from "node:buffer";
|
|
16
16
|
import { decode } from "node:querystring";
|
|
17
|
+
import { Stream } from "node:stream";
|
|
17
18
|
//#region src/server/api-handler.ts
|
|
18
19
|
/**
|
|
19
20
|
* Default request body size (1 MB). Matches Next.js default bodyParser sizeLimit.
|
|
@@ -32,6 +33,8 @@ const MAX_BODY_SIZE = DEFAULT_PAGES_API_BODY_SIZE_LIMIT;
|
|
|
32
33
|
* HMAC signature verification).
|
|
33
34
|
*/
|
|
34
35
|
async function parseBody(req, sizeLimit = MAX_BODY_SIZE) {
|
|
36
|
+
const { mediaType, decoder } = await createPagesBodyDecoder(req.headers["content-type"]);
|
|
37
|
+
if (req.destroyed) throw req.errored ?? /* @__PURE__ */ new Error("Request aborted");
|
|
35
38
|
return new Promise((resolve, reject) => {
|
|
36
39
|
const chunks = [];
|
|
37
40
|
let totalSize = 0;
|
|
@@ -55,10 +58,10 @@ async function parseBody(req, sizeLimit = MAX_BODY_SIZE) {
|
|
|
55
58
|
req.on("end", () => {
|
|
56
59
|
if (settled) return;
|
|
57
60
|
settled = true;
|
|
58
|
-
const
|
|
59
|
-
const
|
|
61
|
+
const body = Buffer.concat(chunks);
|
|
62
|
+
const raw = decoder.decode(body);
|
|
60
63
|
if (!raw) {
|
|
61
|
-
resolve(isJsonMediaType(mediaType) ? {} : mediaType === "application/x-www-form-urlencoded" ? decode(raw) : void 0);
|
|
64
|
+
resolve(isJsonMediaType(mediaType) ? {} : mediaType === "application/x-www-form-urlencoded" ? decode(raw) : body.length > 0 ? raw : void 0);
|
|
62
65
|
return;
|
|
63
66
|
}
|
|
64
67
|
if (isJsonMediaType(mediaType)) try {
|
|
@@ -188,6 +191,18 @@ function enhanceApiObjects(req, res, query, body, trustedRevalidateOrigin, allow
|
|
|
188
191
|
this.end(JSON.stringify(data));
|
|
189
192
|
},
|
|
190
193
|
send(data) {
|
|
194
|
+
if (this.statusCode === 204 || this.statusCode === 304) {
|
|
195
|
+
this.removeHeader("Content-Type");
|
|
196
|
+
this.removeHeader("Content-Length");
|
|
197
|
+
this.removeHeader("Transfer-Encoding");
|
|
198
|
+
this.end();
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (data instanceof Stream) {
|
|
202
|
+
if (!this.getHeader("Content-Type")) this.setHeader("Content-Type", "application/octet-stream");
|
|
203
|
+
data.pipe(this);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
191
206
|
if (Buffer.isBuffer(data)) {
|
|
192
207
|
if (!this.getHeader("Content-Type")) this.setHeader("Content-Type", "application/octet-stream");
|
|
193
208
|
this.setHeader("Content-Length", String(data.length));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
2
2
|
import "./app-elements.js";
|
|
3
|
-
import { isNestedBfcacheSlotSegmentIdFor } from "./bfcache-identity.js";
|
|
4
3
|
import { isBfcacheSegmentId } from "./app-bfcache-id.js";
|
|
4
|
+
import { isNestedBfcacheSlotSegmentIdFor } from "./bfcache-identity.js";
|
|
5
5
|
//#region src/server/app-bfcache-identity.ts
|
|
6
6
|
let nextBfcacheId = 0;
|
|
7
7
|
function rememberBfcacheId(value) {
|
|
@@ -1,35 +1,33 @@
|
|
|
1
1
|
import { addBasePathToPathname, stripBasePath } from "../utils/base-path.js";
|
|
2
|
-
import {
|
|
2
|
+
import { VINEXT_MOUNTED_LAYOUTS_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER } from "./headers.js";
|
|
3
3
|
import { splitPathnameForRouteMatch } from "../routing/utils.js";
|
|
4
4
|
import { AppRouterContext } from "../shims/internal/app-router-context.js";
|
|
5
5
|
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
6
6
|
import { installWindowNext, setWindowNextInternalSourcePage } from "../client/window-next.js";
|
|
7
7
|
import { retryScrollTo, scrollToHashTargetOnNextFrame } from "../shims/hash-scroll.js";
|
|
8
|
-
import { AppElementsWire } from "./app-elements-wire.js";
|
|
9
|
-
import { getMountedSlotIdsHeader, resolveVisitedResponseInterceptionContext } from "./app-elements.js";
|
|
10
|
-
import { getBfcacheIdMapContext, getNavigationContext, setNavigationContext } from "../shims/navigation-context-state.js";
|
|
11
|
-
import { decodeRedirectError, isRedirectError } from "../shims/navigation-errors.js";
|
|
12
|
-
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
13
|
-
import { clearAppNavigationFailureTarget, installAppNavigationFailureListeners } from "../client/app-nav-failure-handler.js";
|
|
14
|
-
import { DevRecoveryBoundary, GlobalErrorBoundary, RedirectBoundary } from "../shims/error-boundary.js";
|
|
15
|
-
import { beginAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
16
|
-
import { AppRouterScrollCommitProvider } from "../shims/app-router-scroll.js";
|
|
17
|
-
import { BfcacheIdentityMapContext, bindAppElementsRenderedSearch, setAppElementsRenderedSearch } from "../shims/slot.js";
|
|
18
8
|
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, formatRscRequestPath, isRscCompatibilityIdCompatible } from "./app-rsc-cache-busting.js";
|
|
9
|
+
import { clearAppNavigationFailureTarget, installAppNavigationFailureListeners } from "../client/app-nav-failure-handler.js";
|
|
19
10
|
import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
|
|
20
11
|
import "../client/instrumentation-client.js";
|
|
21
12
|
import { createNavigationRuntimeRouteManifestLoader, getNavigationRuntime, loadNavigationRuntimeRouteManifest, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
|
|
13
|
+
import { AppElementsWire } from "./app-elements-wire.js";
|
|
14
|
+
import { getMountedSlotIdsHeader, resolveVisitedResponseInterceptionContext } from "./app-elements.js";
|
|
22
15
|
import { createBfcacheSegmentIdentityMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
|
|
23
16
|
import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, resolveServerActionOperationLane } from "./app-browser-action-result.js";
|
|
24
|
-
import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
|
|
25
17
|
import { resolveManifestNavigationInterceptionContext, resolveMiddlewareRewriteNavigationInterceptionContext } from "./app-browser-interception-context.js";
|
|
26
18
|
import { isExternalHistoryState, readHistoryStateActiveRoutePaths, readHistoryStatePreviousNextUrl, resolveActiveRoutePaths } from "./app-history-state.js";
|
|
27
19
|
import { AppBrowserMpaNavigationScheduler } from "./app-browser-mpa-navigation.js";
|
|
28
20
|
import { stripRscCompletionMetadataResponse } from "./rsc-completion-metadata.js";
|
|
29
21
|
import { blockDangerousStreamedRscRedirect } from "./app-browser-rsc-redirect.js";
|
|
30
22
|
import { navigationPlanner } from "./navigation-planner.js";
|
|
31
|
-
import {
|
|
23
|
+
import { decodeRedirectError, isRedirectError } from "../shims/navigation-errors.js";
|
|
24
|
+
import { beginAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
25
|
+
import { getBfcacheIdMapContext, getNavigationContext, setNavigationContext } from "../shims/navigation-context-state.js";
|
|
26
|
+
import { DYNAMIC_NAVIGATION_CACHE_TTL, PREFETCH_CACHE_TTL, __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, deletePrefetchResponseSnapshot, disableNavigationResponsePrefetchCacheReuse, getClientNavigationRenderContext, getMountedSlotsHeader, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidateDynamicPrefetchCache, invalidatePrefetchCache, invalidateVisitedResponsePrefetches, parseRenderedPathAndSearchHeader, preloadHybridClientRouteOwner, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveLoadedHybridClientRewriteHref, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setPendingPathname, trackAppRouterNavigationInFlight, useRouter } from "../shims/navigation.js";
|
|
27
|
+
import { AppRouterScrollCommitProvider } from "../shims/app-router-scroll.js";
|
|
32
28
|
import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
|
|
29
|
+
import { createMountedLayoutsHeader, holdsSkippedLayouts } from "./app-mounted-layouts.js";
|
|
30
|
+
import { BfcacheIdentityMapContext, bindAppElementsRenderedSearch, setAppElementsRenderedSearch } from "../shims/slot.js";
|
|
33
31
|
import { COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, isCompleteAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl } from "./app-browser-state.js";
|
|
34
32
|
import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch, navigateDocumentDirectly } from "./app-browser-navigation-controller.js";
|
|
35
33
|
import { createAppRouteTree } from "./app-route-tree.js";
|
|
@@ -38,17 +36,19 @@ import { createSupplementalRefreshCoordinator, mergeRefreshedParallelSlot, requi
|
|
|
38
36
|
import { createAppBrowserNavigationAbortCoordinator } from "./app-browser-navigation-abort.js";
|
|
39
37
|
import { consumeInitialFormState, createVinextHydrateRootOptions, hydrateRootInTransition, resolveFetchedHydrationLocation } from "./app-browser-hydration.js";
|
|
40
38
|
import { AppBrowserHistoryController } from "./app-browser-history-controller.js";
|
|
41
|
-
import { createVisitedResponseCacheEntry, deleteAllVisitedResponseCacheEntries,
|
|
39
|
+
import { createVisitedResponseCacheEntry, deleteAllVisitedResponseCacheEntries, deleteVisitedResponseCacheEntry, findVisitedResponseCacheEntry, findVisitedResponseForFullPrefetch, hasNavigationResponseHistoryLifetime, isVisitedResponseCacheEntryFresh, revokeHistoryRestoreNavigationReuse } from "./app-visited-response-cache.js";
|
|
42
40
|
import { createPopstateRestoreHandler, restoreSynchronousPopstateScrollPosition, shouldCommitPopstateUrlWithoutNavigation } from "./app-browser-popstate.js";
|
|
41
|
+
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
42
|
+
import { DevRecoveryBoundary, GlobalErrorBoundary, RedirectBoundary } from "../shims/error-boundary.js";
|
|
43
43
|
import { createDevOnCaughtError, createOnUncaughtError, createProdOnCaughtError, createProdOnRecoverableError } from "./app-browser-error.js";
|
|
44
44
|
import { createHydrationCachePublication } from "./app-hydration-cache-publication.js";
|
|
45
45
|
import { peekSettledPrefetchResponseForNavigation, prepareConsumedPrefetchResponseForPublication, preserveCommittedPrefetchExpiry, resolvePrefetchNavigationResponseUrl } from "./app-browser-prefetch-response.js";
|
|
46
|
-
import { canCommitOptimisticRouteTemplate, createOptimisticRouteTemplate, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, keepOptimisticStreamingMetadata, resolveOptimisticNavigationParamsForHref, resolveOptimisticNavigationPayload } from "./app-optimistic-routing.js";
|
|
46
|
+
import { canCommitOptimisticRouteTemplate, createOptimisticRouteTemplate, createOptimisticRouteTemplateStore, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, keepOptimisticStreamingMetadata, resolveOptimisticNavigationParamsForHref, resolveOptimisticNavigationPayload } from "./app-optimistic-routing.js";
|
|
47
47
|
import { removeStylesheetLinksCoveredByInlineCss } from "./app-inline-css-client.js";
|
|
48
48
|
import { createElement, startTransition, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
49
|
-
import { flushSync } from "react-dom";
|
|
50
49
|
import { createRoot, hydrateRoot } from "react-dom/client";
|
|
51
50
|
import { createFromFetch, createFromReadableStream, setServerCallback } from "@vitejs/plugin-rsc/browser";
|
|
51
|
+
import { flushSync } from "react-dom";
|
|
52
52
|
import { hasServerActions, loadServerActionClient } from "virtual:vinext-app-capabilities";
|
|
53
53
|
//#region src/server/app-browser-entry.ts
|
|
54
54
|
const HAS_CLIENT_REWRITES = process.env.__VINEXT_HAS_CLIENT_REWRITES !== "false";
|
|
@@ -80,9 +80,7 @@ function setClientRscCompatibilityId(compatibilityId) {
|
|
|
80
80
|
if (IS_STATIC_EXPORT || !compatibilityId) return;
|
|
81
81
|
clientRscCompatibilityId = compatibilityId;
|
|
82
82
|
}
|
|
83
|
-
const optimisticRouteTemplates =
|
|
84
|
-
const optimisticRouteTemplateSources = /* @__PURE__ */ new Set();
|
|
85
|
-
const optimisticRouteTemplateLearning = /* @__PURE__ */ new Map();
|
|
83
|
+
const optimisticRouteTemplates = createOptimisticRouteTemplateStore();
|
|
86
84
|
function claimInitialAppRouterBootstrap() {
|
|
87
85
|
if (window.__VINEXT_RSC_ROOT__ || window.__VINEXT_RSC_BOOTSTRAP_STATE__) return false;
|
|
88
86
|
window.__VINEXT_RSC_BOOTSTRAP_STATE__ = "starting";
|
|
@@ -114,8 +112,8 @@ const historyController = new AppBrowserHistoryController({
|
|
|
114
112
|
maxHistoryStateSnapshots: 50,
|
|
115
113
|
readHistoryState: () => window.history.state,
|
|
116
114
|
readCurrentHref: () => window.location.href,
|
|
117
|
-
pushHistoryState: (state, href) => pushHistoryStateWithoutNotify(state, "", href),
|
|
118
|
-
replaceHistoryState: (state, href) => replaceHistoryStateWithoutNotify(state, "", href),
|
|
115
|
+
pushHistoryState: (state, href, land) => pushHistoryStateWithoutNotify(state, "", href, land),
|
|
116
|
+
replaceHistoryState: (state, href, land) => replaceHistoryStateWithoutNotify(state, "", href, land),
|
|
119
117
|
readVisibleNavigationMetadata: () => {
|
|
120
118
|
if (!hasBrowserRouterState()) return null;
|
|
121
119
|
const routerState = getBrowserRouterState();
|
|
@@ -223,7 +221,7 @@ function restoreHistoryStateSnapshot(historyState, navId, onApprovedBeforeCommit
|
|
|
223
221
|
});
|
|
224
222
|
if (!restored) return false;
|
|
225
223
|
clientNavigationCacheGeneration += 1;
|
|
226
|
-
|
|
224
|
+
revokeHistoryRestoreNavigationReuse(visitedResponseCache);
|
|
227
225
|
disableNavigationResponsePrefetchCacheReuse();
|
|
228
226
|
commitClientNavigationState(navId, { releaseSnapshot: false });
|
|
229
227
|
return true;
|
|
@@ -250,17 +248,23 @@ function stageClientParams(params) {
|
|
|
250
248
|
}
|
|
251
249
|
function clearVisitedResponseCache() {
|
|
252
250
|
visitedResponseCache.clear();
|
|
251
|
+
invalidateVisitedResponsePrefetches();
|
|
253
252
|
}
|
|
254
|
-
function clearPrefetchState() {
|
|
255
|
-
invalidatePrefetchCache();
|
|
253
|
+
function clearPrefetchState(options) {
|
|
254
|
+
invalidatePrefetchCache(options);
|
|
256
255
|
optimisticRouteTemplates.clear();
|
|
257
|
-
optimisticRouteTemplateSources.clear();
|
|
258
|
-
optimisticRouteTemplateLearning.clear();
|
|
259
256
|
}
|
|
260
|
-
function clearClientNavigationCaches() {
|
|
257
|
+
function clearClientNavigationCaches(options) {
|
|
258
|
+
clientNavigationCacheGeneration += 1;
|
|
259
|
+
clearVisitedResponseCache();
|
|
260
|
+
clearPrefetchState(options);
|
|
261
|
+
historyController.invalidateRestorableClientState();
|
|
262
|
+
}
|
|
263
|
+
function clearDynamicClientNavigationCaches() {
|
|
261
264
|
clientNavigationCacheGeneration += 1;
|
|
262
265
|
clearVisitedResponseCache();
|
|
263
|
-
|
|
266
|
+
invalidateDynamicPrefetchCache();
|
|
267
|
+
optimisticRouteTemplates.clear();
|
|
264
268
|
historyController.invalidateRestorableClientState();
|
|
265
269
|
}
|
|
266
270
|
function getMatchedUrlPathname(matchedUrl) {
|
|
@@ -343,10 +347,10 @@ function parsePrefetchCacheKey(cacheKey) {
|
|
|
343
347
|
}
|
|
344
348
|
async function learnOptimisticRouteTemplateFromPrefetch(options) {
|
|
345
349
|
const source = parsePrefetchCacheKey(options.cacheKey);
|
|
346
|
-
if (source.interceptionContext !== options.interceptionContext) return
|
|
347
|
-
if (resolvePrefetchCacheEntryMountedSlotsHeader(options.entry) !== options.mountedSlotsHeader) return
|
|
348
|
-
if (options.interceptionContext !== null) return
|
|
349
|
-
if (!isRscResponseCompatible(options.entry.snapshot.compatibilityIdHeader)) return
|
|
350
|
+
if (source.interceptionContext !== options.interceptionContext) return null;
|
|
351
|
+
if (resolvePrefetchCacheEntryMountedSlotsHeader(options.entry) !== options.mountedSlotsHeader) return null;
|
|
352
|
+
if (options.interceptionContext !== null) return null;
|
|
353
|
+
if (!isRscResponseCompatible(options.entry.snapshot.compatibilityIdHeader)) return null;
|
|
350
354
|
const elements = await decodeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(options.entry.snapshot))));
|
|
351
355
|
const template = createOptimisticRouteTemplate({
|
|
352
356
|
allowLoadingShell: options.entry.optimisticRouteShell === true,
|
|
@@ -357,40 +361,36 @@ async function learnOptimisticRouteTemplateFromPrefetch(options) {
|
|
|
357
361
|
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
358
362
|
routeManifest: options.routeManifest
|
|
359
363
|
});
|
|
360
|
-
if (template === null) return
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
364
|
+
if (template === null) return null;
|
|
365
|
+
return {
|
|
366
|
+
key: getOptimisticRouteTemplateKey({
|
|
367
|
+
interceptionContext: options.interceptionContext,
|
|
368
|
+
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
369
|
+
routeId: template.routeId
|
|
370
|
+
}),
|
|
371
|
+
template
|
|
372
|
+
};
|
|
367
373
|
}
|
|
368
374
|
async function learnOptimisticRouteTemplatesFromPrefetchCache(options) {
|
|
369
|
-
|
|
370
|
-
|
|
375
|
+
const { routeManifest } = options;
|
|
376
|
+
if (routeManifest === null) return;
|
|
377
|
+
const learning = optimisticRouteTemplates.pendingLearning();
|
|
371
378
|
for (const [cacheKey, entry] of getPrefetchCache()) {
|
|
372
379
|
const sourceKey = getOptimisticPrefetchSourceKey({
|
|
373
380
|
cacheKey,
|
|
374
381
|
interceptionContext: options.interceptionContext,
|
|
375
382
|
mountedSlotsHeader: options.mountedSlotsHeader
|
|
376
383
|
});
|
|
377
|
-
if (
|
|
378
|
-
if (optimisticRouteTemplateLearning.has(sourceKey)) continue;
|
|
384
|
+
if (optimisticRouteTemplates.hasSource(sourceKey)) continue;
|
|
379
385
|
if (!isSettledPrefetchCacheEntry(entry)) continue;
|
|
380
386
|
if (entry.prefetchKind === "route-tree") continue;
|
|
381
|
-
|
|
387
|
+
learning.push(optimisticRouteTemplates.learn(sourceKey, () => learnOptimisticRouteTemplateFromPrefetch({
|
|
382
388
|
cacheKey,
|
|
383
389
|
entry,
|
|
384
390
|
interceptionContext: options.interceptionContext,
|
|
385
391
|
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
386
|
-
routeManifest
|
|
387
|
-
})
|
|
388
|
-
if (learned) optimisticRouteTemplateSources.add(sourceKey);
|
|
389
|
-
}).finally(() => {
|
|
390
|
-
optimisticRouteTemplateLearning.delete(sourceKey);
|
|
391
|
-
});
|
|
392
|
-
optimisticRouteTemplateLearning.set(sourceKey, promise);
|
|
393
|
-
learning.push(promise);
|
|
392
|
+
routeManifest
|
|
393
|
+
})));
|
|
394
394
|
}
|
|
395
395
|
if (learning.length === 0) return;
|
|
396
396
|
await Promise.allSettled(learning);
|
|
@@ -533,7 +533,7 @@ function evictVisitedResponseCacheIfNeeded() {
|
|
|
533
533
|
function readVisitedResponseCacheCandidate(rscUrl, interceptionContext, mountedSlotsHeader, navigationKind) {
|
|
534
534
|
const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
|
|
535
535
|
const match = findVisitedResponseCacheEntry(visitedResponseCache, rscUrl, interceptionContext);
|
|
536
|
-
if (!match) return {
|
|
536
|
+
if (!match || match.entry.navigationReuseRevoked) return {
|
|
537
537
|
cacheKey,
|
|
538
538
|
entry: null,
|
|
539
539
|
facts: {
|
|
@@ -568,13 +568,14 @@ function applyVisitedResponseCacheCandidateDecision(candidate, decision) {
|
|
|
568
568
|
function deleteVisitedResponse(rscUrl, interceptionContext) {
|
|
569
569
|
deleteVisitedResponseCacheEntry(visitedResponseCache, rscUrl, interceptionContext);
|
|
570
570
|
}
|
|
571
|
-
function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, params, prefetchFallbackTtlMs = DYNAMIC_NAVIGATION_CACHE_TTL, requestMountedSlotsHeader = snapshot.mountedSlotsHeader ?? null, elements, seedPrefetchCache = true, prefetchSnapshot = snapshot, reuseAfterHistoryRestore = false) {
|
|
571
|
+
function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, params, prefetchFallbackTtlMs = DYNAMIC_NAVIGATION_CACHE_TTL, requestMountedSlotsHeader = snapshot.mountedSlotsHeader ?? null, elements, seedPrefetchCache = true, prefetchSnapshot = snapshot, reuseAfterHistoryRestore = false, fromHydration = false) {
|
|
572
572
|
const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
|
|
573
573
|
deleteAllVisitedResponseCacheEntries(visitedResponseCache, rscUrl, interceptionContext);
|
|
574
574
|
evictVisitedResponseCacheIfNeeded();
|
|
575
575
|
const entry = createVisitedResponseCacheEntry({
|
|
576
576
|
fallbackTtlMs: prefetchFallbackTtlMs,
|
|
577
577
|
elements,
|
|
578
|
+
fromHydration,
|
|
578
579
|
now: Date.now(),
|
|
579
580
|
mountedSlotsHeader: requestMountedSlotsHeader,
|
|
580
581
|
params,
|
|
@@ -699,7 +700,6 @@ function BrowserRoot({ hydrationCachePublication, initialElements, initialNaviga
|
|
|
699
700
|
interception: initialMetadata.interception,
|
|
700
701
|
interceptionContext: initialMetadata.interceptionContext,
|
|
701
702
|
layoutIds: initialMetadata.layoutIds,
|
|
702
|
-
layoutFlags: initialMetadata.layoutFlags,
|
|
703
703
|
navigationSnapshot: initialNavigationSnapshot,
|
|
704
704
|
previousNextUrl: null,
|
|
705
705
|
renderId: 0,
|
|
@@ -966,6 +966,7 @@ function registerServerActionCallback() {
|
|
|
966
966
|
return loadServerActionClient().then(({ invokeClientServerAction }) => invokeClientServerAction(id, args, actionInitiation, {
|
|
967
967
|
basePath: __basePath,
|
|
968
968
|
clearClientNavigationCaches,
|
|
969
|
+
clearDynamicClientNavigationCaches,
|
|
969
970
|
clientRscCompatibilityId,
|
|
970
971
|
commitSameUrlNavigatePayload,
|
|
971
972
|
navigationPlanner,
|
|
@@ -1059,7 +1060,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1059
1060
|
const fallbackTtlMs = initialRscBootstrap?.initialCacheKind === "static" ? PREFETCH_CACHE_TTL : DYNAMIC_NAVIGATION_CACHE_TTL;
|
|
1060
1061
|
hydrationCachePublication.publish(() => {
|
|
1061
1062
|
if (cacheGeneration !== clientNavigationCacheGeneration) return () => {};
|
|
1062
|
-
return storeVisitedResponseSnapshot(rscUrl, metadata.interceptionContext, snapshot, initialParams, fallbackTtlMs, mountedSlotsHeader, elements, false, snapshot, initialRscBootstrap?.initialCacheKind === "static" || metadata.interceptionContext !== null);
|
|
1063
|
+
return storeVisitedResponseSnapshot(rscUrl, metadata.interceptionContext, snapshot, initialParams, fallbackTtlMs, mountedSlotsHeader, elements, false, snapshot, initialRscBootstrap?.initialCacheKind === "static" || metadata.interceptionContext !== null, true);
|
|
1063
1064
|
});
|
|
1064
1065
|
}).catch(() => {});
|
|
1065
1066
|
historyController.writeBootstrapHistoryMetadata();
|
|
@@ -1151,6 +1152,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1151
1152
|
};
|
|
1152
1153
|
let restoredBfcacheIds = navigationKind === "traverse" ? historyController.readCurrentBfcacheVersionHistoryIds(activeTraversalIntent?.historyState ?? window.history.state) : null;
|
|
1153
1154
|
const reuseCurrentBfcacheIds = navigationKind !== "traverse" || !historyController.isCacheInvalidationGuarded() && historyController.isCurrentBfcacheVersion(activeTraversalIntent?.historyState ?? window.history.state);
|
|
1155
|
+
const releaseNavigationInFlight = trackAppRouterNavigationInFlight();
|
|
1154
1156
|
try {
|
|
1155
1157
|
const shouldUsePendingRouterState = programmaticTransition;
|
|
1156
1158
|
if (hasBrowserRouterState()) {
|
|
@@ -1171,6 +1173,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1171
1173
|
}
|
|
1172
1174
|
const navigationInitiationState = getBrowserRouterState();
|
|
1173
1175
|
const mountedSlotsHeader = getMountedSlotIdsHeader(navigationInitiationState.elements);
|
|
1176
|
+
let mountedLayoutsHeader = navigationKind === "navigate" ? createMountedLayoutsHeader(navigationInitiationState.elements, navigationInitiationState.layoutIds) : null;
|
|
1174
1177
|
while (true) {
|
|
1175
1178
|
const url = new URL(currentHref, window.location.origin);
|
|
1176
1179
|
const requestState = getRequestState(navigationKind, url.pathname, currentPrevNextUrl, activeTraversalIntent?.historyState);
|
|
@@ -1380,7 +1383,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1380
1383
|
interceptionContext: requestInterceptionContext,
|
|
1381
1384
|
mountedSlotsHeader,
|
|
1382
1385
|
routeManifest,
|
|
1383
|
-
templates: optimisticRouteTemplates
|
|
1386
|
+
templates: optimisticRouteTemplates.templates
|
|
1384
1387
|
});
|
|
1385
1388
|
if (optimisticPayload !== null && canCommitOptimisticRouteTemplate({
|
|
1386
1389
|
currentElements: navigationInitiationState.elements,
|
|
@@ -1419,13 +1422,16 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1419
1422
|
}
|
|
1420
1423
|
}
|
|
1421
1424
|
}
|
|
1425
|
+
let sentMountedLayouts = false;
|
|
1422
1426
|
if (!navResponse) {
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1427
|
+
let liveRequestHeaders = requestHeaders;
|
|
1428
|
+
if (mountedLayoutsHeader !== null && requestInterceptionContext === null) {
|
|
1429
|
+
liveRequestHeaders = new Headers(requestHeaders);
|
|
1430
|
+
liveRequestHeaders.set(VINEXT_MOUNTED_LAYOUTS_HEADER, mountedLayoutsHeader);
|
|
1431
|
+
sentMountedLayouts = true;
|
|
1426
1432
|
}
|
|
1427
1433
|
navResponse = await fetch(rscUrl, {
|
|
1428
|
-
headers:
|
|
1434
|
+
headers: liveRequestHeaders,
|
|
1429
1435
|
credentials: "include",
|
|
1430
1436
|
priority: "auto",
|
|
1431
1437
|
signal: navigationAbortHandle.signal
|
|
@@ -1508,6 +1514,15 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1508
1514
|
navigationAbortHandle.release();
|
|
1509
1515
|
}).then(requireCompleteSupplementalRefresh);
|
|
1510
1516
|
}
|
|
1517
|
+
if (sentMountedLayouts) {
|
|
1518
|
+
const elements = await rscPayload;
|
|
1519
|
+
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
1520
|
+
if (!holdsSkippedLayouts(navigationInitiationState, elements) || !holdsSkippedLayouts(getBrowserRouterState(), elements)) {
|
|
1521
|
+
mountedLayoutsHeader = null;
|
|
1522
|
+
continue;
|
|
1523
|
+
}
|
|
1524
|
+
rscPayload = Promise.resolve(elements);
|
|
1525
|
+
}
|
|
1511
1526
|
if (IS_STATIC_EXPORT) {
|
|
1512
1527
|
const staticExportElements = await rscPayload;
|
|
1513
1528
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
@@ -1584,13 +1599,12 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1584
1599
|
const state = committedState;
|
|
1585
1600
|
const committedElements = {
|
|
1586
1601
|
...state.elements,
|
|
1587
|
-
[AppElementsWire.keys.layoutFlags]: state.layoutFlags,
|
|
1588
1602
|
[AppElementsWire.keys.layoutIds]: state.layoutIds,
|
|
1589
1603
|
[AppElementsWire.keys.skippedLayoutIds]: [],
|
|
1590
1604
|
[AppElementsWire.keys.slotBindings]: state.slotBindings
|
|
1591
1605
|
};
|
|
1592
1606
|
if (navigationCacheGeneration !== clientNavigationCacheGeneration) return;
|
|
1593
|
-
storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, navParams, DYNAMIC_NAVIGATION_CACHE_TTL, mountedSlotsHeader, committedElements,
|
|
1607
|
+
storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, navParams, DYNAMIC_NAVIGATION_CACHE_TTL, mountedSlotsHeader, committedElements, isCompleteAppPayloadMetadata(metadata), prefetchSnapshot, interceptionContext !== null || hasNavigationResponseHistoryLifetime(snapshot));
|
|
1594
1608
|
}
|
|
1595
1609
|
} catch {}
|
|
1596
1610
|
return;
|
|
@@ -1603,9 +1617,11 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1603
1617
|
navigationAbortHandle.release();
|
|
1604
1618
|
browserNavigationController.finalizeNavigation(navId, pendingRouterState);
|
|
1605
1619
|
discardedServerActionRefreshScheduler.markNavigationSettled();
|
|
1620
|
+
releaseNavigationInFlight();
|
|
1606
1621
|
if (startedHardNavigation) await waitForMpaNavigationRestore();
|
|
1607
1622
|
}
|
|
1608
1623
|
},
|
|
1624
|
+
readVisitedResponseForFullPrefetch: (rscUrls, interceptionContext, mountedSlotsHeader) => findVisitedResponseForFullPrefetch(visitedResponseCache, rscUrls, interceptionContext, mountedSlotsHeader),
|
|
1609
1625
|
preparePrefetchResponse: (response) => {
|
|
1610
1626
|
if (!isRscResponseCompatible(response.headers.get("X-Vinext-RSC-Compatibility-Id"))) return Promise.reject(/* @__PURE__ */ new Error("[vinext] Prefetched another deployment's payload"));
|
|
1611
1627
|
return decodeAppElementsPromise(createFromFetch(Promise.resolve(response)));
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RouterHistoryWriteLanding } from "../shims/navigation.js";
|
|
1
2
|
import { BfcacheIdMap, HistoryTraversalIntent } from "./app-history-state.js";
|
|
2
3
|
import { AppRouterState } from "./app-browser-state.js";
|
|
3
4
|
import { HistoryUpdateMode } from "./app-browser-navigation-controller.js";
|
|
@@ -19,10 +20,10 @@ type AppBrowserHistoryControllerDeps = {
|
|
|
19
20
|
readHistoryState: () => unknown;
|
|
20
21
|
/** Reads `window.location.href`. Injected so the controller stays unit-testable. */
|
|
21
22
|
readCurrentHref: () => string;
|
|
22
|
-
/** Wraps `pushHistoryStateWithoutNotify(state, "", href)`. */
|
|
23
|
-
pushHistoryState: (state: unknown, href: string) => void;
|
|
24
|
-
/** Wraps `replaceHistoryStateWithoutNotify(state, "", href)`. */
|
|
25
|
-
replaceHistoryState: (state: unknown, href?: string) => void;
|
|
23
|
+
/** Wraps `pushHistoryStateWithoutNotify(state, "", href, land)`. */
|
|
24
|
+
pushHistoryState: (state: unknown, href: string, land?: RouterHistoryWriteLanding) => void;
|
|
25
|
+
/** Wraps `replaceHistoryStateWithoutNotify(state, "", href, land)`. */
|
|
26
|
+
replaceHistoryState: (state: unknown, href?: string, land?: RouterHistoryWriteLanding) => void;
|
|
26
27
|
readVisibleNavigationMetadata: () => VisibleNavigationMetadata | null;
|
|
27
28
|
};
|
|
28
29
|
/**
|
|
@@ -31,6 +31,7 @@ var AppBrowserHistoryController = class {
|
|
|
31
31
|
#treeSnapshots = /* @__PURE__ */ new Map();
|
|
32
32
|
#treeSnapshotClaimCounts = /* @__PURE__ */ new Map();
|
|
33
33
|
#treeSnapshotClaimByHistoryIndex = /* @__PURE__ */ new Map();
|
|
34
|
+
#treeSnapshotIdPrefix = createDocumentTreeSnapshotIdPrefix();
|
|
34
35
|
#readHistoryState;
|
|
35
36
|
#readCurrentHref;
|
|
36
37
|
#pushHistoryState;
|
|
@@ -41,6 +42,9 @@ var AppBrowserHistoryController = class {
|
|
|
41
42
|
#currentTreeSnapshotId = null;
|
|
42
43
|
#nextTreeSnapshotId = 0;
|
|
43
44
|
#treeSnapshotIdPendingFreshState = null;
|
|
45
|
+
#historyIndicesAwaitingTreeSnapshot = /* @__PURE__ */ new Set();
|
|
46
|
+
#treeSnapshotPending = true;
|
|
47
|
+
#historyIndexAwaitingTreeClaim = null;
|
|
44
48
|
constructor(deps) {
|
|
45
49
|
this.#readHistoryState = deps.readHistoryState;
|
|
46
50
|
this.#readCurrentHref = deps.readCurrentHref;
|
|
@@ -99,18 +103,29 @@ var AppBrowserHistoryController = class {
|
|
|
99
103
|
const previousState = this.readCurrentTreeSnapshot();
|
|
100
104
|
const previousOperation = previousState?.activeOperation;
|
|
101
105
|
if (previousState && previousOperation?.navigationCommitKind === "detached" && state.activeOperation?.navigationCommitKind === "authoritative" && state.activeOperation.navigationId === previousOperation.navigationId) this.#restorableClientState.replaceHistoryStateSnapshots(previousState, state);
|
|
106
|
+
for (const historyIndex of this.#historyIndicesAwaitingTreeSnapshot) this.#restorableClientState.rememberHistoryStateSnapshot({
|
|
107
|
+
historyIndex,
|
|
108
|
+
state
|
|
109
|
+
});
|
|
110
|
+
this.#historyIndicesAwaitingTreeSnapshot.clear();
|
|
102
111
|
this.#restorableClientState.rememberHistoryStateSnapshot({
|
|
103
112
|
historyIndex: this.#currentHistoryTraversalIndex,
|
|
104
113
|
state
|
|
105
114
|
});
|
|
115
|
+
this.#treeSnapshotPending = false;
|
|
106
116
|
const historyTreeSnapshotId = readHistoryStateTreeSnapshotId(this.#readHistoryState());
|
|
107
|
-
const treeSnapshotId = historyTreeSnapshotId !== null && this.#treeSnapshots.has(historyTreeSnapshotId) && (historyTreeSnapshotId === this.#treeSnapshotIdPendingFreshState || this.#treeSnapshotClaimCounts.has(historyTreeSnapshotId)) ? historyTreeSnapshotId : this.#nextTreeSnapshotId
|
|
117
|
+
const treeSnapshotId = historyTreeSnapshotId !== null && this.#treeSnapshots.has(historyTreeSnapshotId) && (historyTreeSnapshotId === this.#treeSnapshotIdPendingFreshState || this.#treeSnapshotClaimCounts.has(historyTreeSnapshotId)) ? historyTreeSnapshotId : `${this.#treeSnapshotIdPrefix}:${this.#nextTreeSnapshotId++}`;
|
|
108
118
|
this.#treeSnapshotIdPendingFreshState = null;
|
|
109
119
|
const previousTreeSnapshotId = this.#currentTreeSnapshotId;
|
|
110
120
|
this.#currentTreeSnapshotId = treeSnapshotId;
|
|
111
121
|
this.#treeSnapshots.set(treeSnapshotId, state);
|
|
122
|
+
const claimingHistoryIndex = this.#historyIndexAwaitingTreeClaim;
|
|
123
|
+
this.#historyIndexAwaitingTreeClaim = null;
|
|
124
|
+
const claimsTree = claimingHistoryIndex !== null && claimingHistoryIndex === this.#currentHistoryTraversalIndex && claimingHistoryIndex === readHistoryStateTraversalIndex(this.#readHistoryState());
|
|
125
|
+
if (claimsTree) this.#claimTreeSnapshotAtHistoryIndex(claimingHistoryIndex, treeSnapshotId);
|
|
112
126
|
if (previousTreeSnapshotId !== null && previousTreeSnapshotId !== treeSnapshotId && !this.#treeSnapshotClaimCounts.has(previousTreeSnapshotId)) this.#treeSnapshots.delete(previousTreeSnapshotId);
|
|
113
|
-
if (
|
|
127
|
+
if (claimsTree) this.#replaceHistoryState(createHistoryStateWithTreeSnapshotClaim(createHistoryStateWithTreeSnapshotId(this.#readHistoryState(), treeSnapshotId), true));
|
|
128
|
+
else if (historyTreeSnapshotId !== treeSnapshotId) this.#replaceHistoryState(createHistoryStateWithTreeSnapshotId(this.#readHistoryState(), treeSnapshotId));
|
|
114
129
|
}
|
|
115
130
|
/** The router state of the most recently committed render, if any. */
|
|
116
131
|
readCurrentTreeSnapshot() {
|
|
@@ -125,7 +140,21 @@ var AppBrowserHistoryController = class {
|
|
|
125
140
|
claimCurrentHistoryTreeSnapshot(historyUpdateMode, previousHistoryState) {
|
|
126
141
|
let historyState = this.#readHistoryState();
|
|
127
142
|
const treeSnapshotId = readHistoryStateTreeSnapshotId(historyState);
|
|
128
|
-
if (treeSnapshotId === null || !this.#treeSnapshots.has(treeSnapshotId))
|
|
143
|
+
if (treeSnapshotId === null || !this.#treeSnapshots.has(treeSnapshotId)) {
|
|
144
|
+
if (historyUpdateMode === "push") {
|
|
145
|
+
const previousHistoryIndex = readHistoryStateTraversalIndex(previousHistoryState);
|
|
146
|
+
if (previousHistoryIndex !== null && this.#treeSnapshotPending) this.#historyIndicesAwaitingTreeSnapshot.add(previousHistoryIndex);
|
|
147
|
+
this.#releaseForwardTreeSnapshotClaims();
|
|
148
|
+
const historyIndex = this.#nextHistoryTraversalIndex + 1;
|
|
149
|
+
this.#replaceHistoryState(createHistoryStateWithNavigationMetadata(historyState, {
|
|
150
|
+
previousNextUrl: readHistoryStatePreviousNextUrl(historyState),
|
|
151
|
+
traversalIndex: historyIndex
|
|
152
|
+
}));
|
|
153
|
+
this.commitHistoryTraversalIndex(historyIndex);
|
|
154
|
+
this.#historyIndexAwaitingTreeClaim = this.#treeSnapshotPending ? historyIndex : null;
|
|
155
|
+
}
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
129
158
|
let historyIndex;
|
|
130
159
|
if (historyUpdateMode === "push") {
|
|
131
160
|
this.#releaseForwardTreeSnapshotClaims();
|
|
@@ -185,7 +214,6 @@ var AppBrowserHistoryController = class {
|
|
|
185
214
|
if (treeSnapshotId !== this.#currentTreeSnapshotId) this.#treeSnapshots.delete(treeSnapshotId);
|
|
186
215
|
}
|
|
187
216
|
commitHashOnlyNavigation(href, historyUpdateMode, scroll) {
|
|
188
|
-
if (historyUpdateMode === "push") this.#releaseForwardTreeSnapshotClaims();
|
|
189
217
|
const navigationHistoryIndex = this.allocateNavigationHistoryTraversalIndex(historyUpdateMode);
|
|
190
218
|
const historyState = this.#readHistoryState();
|
|
191
219
|
const visible = this.#readVisibleNavigationMetadata();
|
|
@@ -199,11 +227,59 @@ var AppBrowserHistoryController = class {
|
|
|
199
227
|
previousNextUrl,
|
|
200
228
|
traversalIndex: navigationHistoryIndex
|
|
201
229
|
}), true);
|
|
202
|
-
|
|
203
|
-
else this.#pushHistoryState(nextHistoryState, href);
|
|
230
|
+
const historyIndex = this.#writeNavigationHistoryState(historyUpdateMode, nextHistoryState, href, navigationHistoryIndex, false);
|
|
204
231
|
const treeSnapshotId = readHistoryStateTreeSnapshotId(nextHistoryState);
|
|
205
|
-
if (
|
|
206
|
-
|
|
232
|
+
if (historyIndex !== null && treeSnapshotId !== null) this.#claimTreeSnapshotAtHistoryIndex(historyIndex, treeSnapshotId);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Writes an app-owned push or replace entry and returns the traversal index
|
|
236
|
+
* it landed at. A history wrapper installed after boot can make its own
|
|
237
|
+
* writes before forwarding this one. When those moved the indices, the index
|
|
238
|
+
* is assigned as the write lands: a push goes after them, and a replace takes
|
|
239
|
+
* the index of the entry it actually overwrites. The index is committed as
|
|
240
|
+
* soon as the write succeeds, so a push the wrapper makes after forwarding
|
|
241
|
+
* goes after it.
|
|
242
|
+
*/
|
|
243
|
+
#writeNavigationHistoryState(historyUpdateMode, state, href, allocatedIndex, rendersTree) {
|
|
244
|
+
const allocatedCurrentIndex = this.#currentHistoryTraversalIndex;
|
|
245
|
+
const allocatedNextIndex = this.#nextHistoryTraversalIndex;
|
|
246
|
+
const releaseClaims = (overwrittenHistoryState) => {
|
|
247
|
+
if (historyUpdateMode === "push") {
|
|
248
|
+
this.#releaseForwardTreeSnapshotClaims();
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (!rendersTree) return;
|
|
252
|
+
const overwrittenIndex = readHistoryStateTraversalIndex(overwrittenHistoryState) ?? this.#currentHistoryTraversalIndex;
|
|
253
|
+
if (overwrittenIndex !== null) this.#releaseTreeSnapshotClaimAtHistoryIndex(overwrittenIndex);
|
|
254
|
+
};
|
|
255
|
+
let landedIndex;
|
|
256
|
+
let landingStarted = false;
|
|
257
|
+
const land = (data) => {
|
|
258
|
+
landingStarted = true;
|
|
259
|
+
const index = this.#currentHistoryTraversalIndex !== allocatedCurrentIndex || this.#nextHistoryTraversalIndex !== allocatedNextIndex ? this.allocateNavigationHistoryTraversalIndex(historyUpdateMode) : allocatedIndex;
|
|
260
|
+
const overwrittenHistoryState = this.#readHistoryState();
|
|
261
|
+
return {
|
|
262
|
+
data: index === allocatedIndex ? data : createHistoryStateWithNavigationMetadata(data, {
|
|
263
|
+
previousNextUrl: readHistoryStatePreviousNextUrl(data),
|
|
264
|
+
traversalIndex: index
|
|
265
|
+
}),
|
|
266
|
+
commit: () => {
|
|
267
|
+
releaseClaims(overwrittenHistoryState);
|
|
268
|
+
if (rendersTree) this.#treeSnapshotPending = true;
|
|
269
|
+
landedIndex = index;
|
|
270
|
+
this.commitHistoryTraversalIndex(index);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
};
|
|
274
|
+
const historyStateBeforeWrite = this.#readHistoryState();
|
|
275
|
+
if (historyUpdateMode === "push") this.#pushHistoryState(state, href, land);
|
|
276
|
+
else this.#replaceHistoryState(state, href, land);
|
|
277
|
+
if (landedIndex !== void 0) return landedIndex;
|
|
278
|
+
if (landingStarted) return null;
|
|
279
|
+
releaseClaims(historyStateBeforeWrite);
|
|
280
|
+
if (rendersTree) this.#treeSnapshotPending = true;
|
|
281
|
+
this.commitHistoryTraversalIndex(allocatedIndex);
|
|
282
|
+
return allocatedIndex;
|
|
207
283
|
}
|
|
208
284
|
#createHashOnlyNavigationBaseHistoryState(historyUpdateMode, scroll) {
|
|
209
285
|
const historyState = this.#readHistoryState();
|
|
@@ -238,19 +314,15 @@ var AppBrowserHistoryController = class {
|
|
|
238
314
|
let wroteHistoryState = false;
|
|
239
315
|
if (options.historyUpdateMode === "replace" && (currentHref !== targetHref || replacesClaimedOrExternalTree)) {
|
|
240
316
|
options.stageClientParams();
|
|
241
|
-
|
|
242
|
-
if (currentHistoryIndex !== null) this.#releaseTreeSnapshotClaimAtHistoryIndex(currentHistoryIndex);
|
|
243
|
-
this.#replaceHistoryState(historyState, options.href);
|
|
317
|
+
this.#writeNavigationHistoryState("replace", historyState, options.href, navigationHistoryIndex, true);
|
|
244
318
|
wroteHistoryState = true;
|
|
245
|
-
this.commitHistoryTraversalIndex(navigationHistoryIndex);
|
|
246
319
|
} else if (options.historyUpdateMode === "push" && currentHref !== targetHref) {
|
|
247
320
|
options.stageClientParams();
|
|
248
|
-
this.#
|
|
249
|
-
this.#pushHistoryState(historyState, options.href);
|
|
321
|
+
this.#writeNavigationHistoryState("push", historyState, options.href, navigationHistoryIndex, true);
|
|
250
322
|
wroteHistoryState = true;
|
|
251
|
-
this.commitHistoryTraversalIndex(navigationHistoryIndex);
|
|
252
323
|
}
|
|
253
324
|
if (!wroteHistoryState) {
|
|
325
|
+
this.#treeSnapshotPending = true;
|
|
254
326
|
this.syncCurrentHistoryStatePreviousNextUrl(options.previousNextUrl, options.bfcacheIds, options.activeRoutePaths);
|
|
255
327
|
options.stageClientParams();
|
|
256
328
|
if (options.targetHistoryIndex !== void 0) this.commitHistoryTraversalIndex(options.targetHistoryIndex);
|
|
@@ -306,6 +378,7 @@ var AppBrowserHistoryController = class {
|
|
|
306
378
|
state,
|
|
307
379
|
beforeCommit: () => {
|
|
308
380
|
this.commitTraversalIndexFromHistoryState(options.historyState);
|
|
381
|
+
this.#treeSnapshotPending = true;
|
|
309
382
|
options.stageClientParams(state.navigationSnapshot.params);
|
|
310
383
|
}
|
|
311
384
|
});
|
|
@@ -317,11 +390,16 @@ var AppBrowserHistoryController = class {
|
|
|
317
390
|
state: decision.state,
|
|
318
391
|
beforeCommit: () => {
|
|
319
392
|
this.commitHistoryTraversalIndex(decision.targetHistoryIndex);
|
|
393
|
+
this.#treeSnapshotPending = true;
|
|
320
394
|
options.stageClientParams(decision.state.navigationSnapshot.params);
|
|
321
395
|
}
|
|
322
396
|
});
|
|
323
397
|
}
|
|
324
398
|
};
|
|
399
|
+
function createDocumentTreeSnapshotIdPrefix() {
|
|
400
|
+
const bytes = crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(8));
|
|
401
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
402
|
+
}
|
|
325
403
|
function areStringArraysEqual(a, b) {
|
|
326
404
|
if (a === b) return true;
|
|
327
405
|
if (a === null || b === null || a.length !== b.length) return false;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { BrowserRouteManifest } from "../routing/browser-route-manifest.js";
|
|
2
2
|
import { AppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
3
|
-
import { NavigationRuntimeVisibleCommitMode } from "../client/navigation-runtime.js";
|
|
4
3
|
import { AppElements } from "./app-elements-wire.js";
|
|
5
4
|
import "./app-elements.js";
|
|
5
|
+
import { ClientNavigationRenderSnapshot, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
6
|
+
import { NavigationRuntimeVisibleCommitMode } from "../client/navigation-runtime.js";
|
|
6
7
|
import { OperationLane } from "./operation-token.js";
|
|
7
8
|
import { ServerActionRevalidationKind } from "./app-browser-action-result.js";
|
|
8
|
-
import { ClientNavigationRenderSnapshot, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
9
9
|
import { AppNavigationPayloadOrigin, AppRouterState } from "./app-browser-state.js";
|
|
10
10
|
import { Dispatch, ReactNode } from "react";
|
|
11
11
|
//#region src/server/app-browser-navigation-controller.d.ts
|