vinext 1.0.0-beta.3 → 1.0.0-beta.4
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/dist/build/precompress.js +1 -1
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +12 -2
- package/dist/cli-args.d.ts +2 -1
- package/dist/cli-args.js +10 -0
- package/dist/cli.js +14 -8
- package/dist/client/navigation-runtime.d.ts +6 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/dotenv.d.ts +3 -4
- package/dist/config/dotenv.js +30 -22
- package/dist/config/next-config.d.ts +4 -2
- package/dist/config/next-config.js +3 -0
- package/dist/entries/app-browser-entry.js +1 -1
- package/dist/entries/app-rsc-entry.js +18 -3
- package/dist/entries/pages-server-entry.js +4 -1
- package/dist/index.js +11 -7
- package/dist/plugins/client-reference-dedup.js +7 -5
- package/dist/plugins/sass.js +3 -4
- package/dist/server/api-handler.js +4 -3
- package/dist/server/app-bfcache-identity.js +28 -2
- package/dist/server/app-browser-entry.js +73 -45
- package/dist/server/app-browser-navigation-controller.d.ts +1 -1
- package/dist/server/app-browser-navigation-controller.js +29 -4
- package/dist/server/app-browser-prefetch-response.d.ts +9 -0
- package/dist/server/app-browser-prefetch-response.js +32 -0
- package/dist/server/app-browser-state.d.ts +8 -3
- package/dist/server/app-browser-state.js +9 -3
- package/dist/server/app-page-dispatch.d.ts +1 -1
- package/dist/server/app-page-dispatch.js +6 -2
- package/dist/server/app-page-element-builder.d.ts +2 -1
- package/dist/server/app-page-element-builder.js +1 -0
- package/dist/server/app-page-render.d.ts +1 -1
- package/dist/server/app-page-render.js +13 -3
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +3 -12
- package/dist/server/app-page-response.d.ts +2 -0
- package/dist/server/app-page-response.js +6 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -2
- package/dist/server/app-page-route-wiring.js +61 -13
- package/dist/server/app-pages-bridge.d.ts +2 -1
- package/dist/server/app-pages-bridge.js +2 -1
- package/dist/server/app-rsc-cache-busting.d.ts +7 -0
- package/dist/server/app-rsc-cache-busting.js +6 -0
- package/dist/server/app-rsc-handler.d.ts +2 -0
- package/dist/server/app-rsc-handler.js +9 -4
- 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.js +65 -4
- package/dist/server/app-server-action-execution.d.ts +1 -1
- package/dist/server/app-visited-response-cache.d.ts +6 -1
- package/dist/server/app-visited-response-cache.js +49 -1
- package/dist/server/dev-server.d.ts +1 -1
- package/dist/server/dev-server.js +61 -38
- package/dist/server/edge-api-runtime.d.ts +10 -1
- package/dist/server/edge-api-runtime.js +29 -1
- package/dist/server/headers.d.ts +3 -1
- package/dist/server/headers.js +3 -1
- package/dist/server/pages-api-route.d.ts +2 -0
- package/dist/server/pages-api-route.js +2 -2
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +6 -4
- package/dist/server/pages-document-asset-props.d.ts +26 -0
- package/dist/server/pages-document-asset-props.js +69 -0
- package/dist/server/pages-node-compat.js +3 -3
- package/dist/server/pages-page-handler.d.ts +1 -0
- package/dist/server/pages-page-handler.js +4 -1
- package/dist/server/pages-page-response.d.ts +2 -0
- package/dist/server/pages-page-response.js +19 -8
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prerender-manifest.d.ts +1 -0
- package/dist/server/prod-server.js +2 -1
- package/dist/server/seed-cache.js +1 -1
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/shims/app-router-scroll-state.d.ts +2 -1
- package/dist/shims/app-router-scroll-state.js +7 -2
- package/dist/shims/document.js +15 -2
- package/dist/shims/hash-scroll.d.ts +1 -1
- package/dist/shims/hash-scroll.js +2 -1
- package/dist/shims/link.d.ts +2 -0
- package/dist/shims/link.js +59 -18
- package/dist/shims/metadata.d.ts +11 -17
- package/dist/shims/metadata.js +24 -32
- package/dist/shims/navigation.d.ts +18 -2
- package/dist/shims/navigation.js +69 -20
- package/dist/shims/request-context.d.ts +2 -1
- package/dist/shims/slot.d.ts +2 -1
- package/dist/shims/slot.js +6 -2
- package/dist/shims/streamed-icons.d.ts +9 -0
- package/dist/shims/streamed-icons.js +33 -0
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@ import { PagesBodyParseError, getMediaType, isJsonMediaType } from "./pages-medi
|
|
|
9
9
|
import { resolveRequestHost, resolveRequestProtocol } from "./proxy-trust.js";
|
|
10
10
|
import { performOnDemandRevalidate } from "./pages-revalidate.js";
|
|
11
11
|
import { attachPagesPreviewApi, attachPagesRequestCookies } from "./pages-node-compat.js";
|
|
12
|
-
import { isEdgeApiRuntime } from "./edge-api-runtime.js";
|
|
12
|
+
import { finalizeEdgeApiResponse, isEdgeApiRuntime } from "./edge-api-runtime.js";
|
|
13
13
|
import { decode } from "node:querystring";
|
|
14
14
|
import { Buffer } from "node:buffer";
|
|
15
15
|
//#region src/server/api-handler.ts
|
|
@@ -227,8 +227,9 @@ async function handleApiRoute(runner, req, res, url, apiRoutes, nextConfig) {
|
|
|
227
227
|
i18n: nextConfig.i18n ?? void 0,
|
|
228
228
|
trailingSlash: nextConfig.trailingSlash
|
|
229
229
|
} } : void 0);
|
|
230
|
-
const
|
|
231
|
-
if (!(
|
|
230
|
+
const handlerResponse = await apiModule.default(nextRequest);
|
|
231
|
+
if (!(handlerResponse instanceof Response)) throw new Error("Edge API route did not return a Response");
|
|
232
|
+
const response = finalizeEdgeApiResponse(handlerResponse, "node");
|
|
232
233
|
res.statusCode = response.status;
|
|
233
234
|
res.statusMessage = response.statusText;
|
|
234
235
|
const setCookieHeaders = response.headers.getSetCookie();
|
|
@@ -51,19 +51,45 @@ function createActiveSlotIdentity(id, parsed) {
|
|
|
51
51
|
if (interception?.slotId !== id) return null;
|
|
52
52
|
return `${id}@${interception.targetRouteId}`;
|
|
53
53
|
}
|
|
54
|
+
function getDirectMatchedRoutePathname(metadata) {
|
|
55
|
+
if (metadata?.metadata.interception != null || metadata?.metadata.sourcePage == null) return null;
|
|
56
|
+
const route = AppElementsWire.parseElementKey(metadata.metadata.routeId);
|
|
57
|
+
return route?.kind === "route" ? route.path : null;
|
|
58
|
+
}
|
|
59
|
+
function getPageMatchedUrl(parsed, metadata) {
|
|
60
|
+
const interception = metadata?.metadata.interception;
|
|
61
|
+
if (interception === null || interception === void 0) {
|
|
62
|
+
const matchedRoutePathname = getDirectMatchedRoutePathname(metadata);
|
|
63
|
+
return matchedRoutePathname === parsed.path ? matchedRoutePathname : null;
|
|
64
|
+
}
|
|
65
|
+
for (const [routeId, matchedUrl] of [[interception.sourceRouteId, interception.sourceMatchedUrl], [interception.targetRouteId, interception.targetMatchedUrl]]) {
|
|
66
|
+
const route = AppElementsWire.parseElementKey(routeId);
|
|
67
|
+
if (route?.kind === "route" && route.path === parsed.path) return matchedUrl;
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
function getTreePathname(treePath, metadata) {
|
|
72
|
+
const interception = metadata?.metadata.interception;
|
|
73
|
+
if (interception === null || interception === void 0) return getDirectMatchedRoutePathname(metadata);
|
|
74
|
+
const slot = AppElementsWire.parseElementKey(interception.slotId);
|
|
75
|
+
if (slot?.kind !== "slot") return interception.sourceMatchedUrl;
|
|
76
|
+
const treeSegments = splitPathSegments(treePath);
|
|
77
|
+
const ownerSegments = splitPathSegments(slot.treePath);
|
|
78
|
+
return treeSegments.length > ownerSegments.length && ownerSegments.every((segment, index) => treeSegments[index] === segment) && treeSegments[ownerSegments.length] === `@${slot.name}` ? interception.targetMatchedUrl : interception.sourceMatchedUrl;
|
|
79
|
+
}
|
|
54
80
|
/**
|
|
55
81
|
* Derive BFCache identity from AppElements wire keys. Keep wire-key parsing
|
|
56
82
|
* contained here until vinext has a route-manifest authority equivalent to
|
|
57
83
|
* Next.js CacheNode or segment-cache state.
|
|
58
84
|
*/
|
|
59
85
|
function createBfcacheSegmentIdentity(id, parsed, options) {
|
|
60
|
-
if (parsed.kind === "page") return `${id}@${options.pathname}`;
|
|
86
|
+
if (parsed.kind === "page") return `${id}@${getPageMatchedUrl(parsed, options.metadata) ?? options.pathname}`;
|
|
61
87
|
if (parsed.kind === "slot") {
|
|
62
88
|
const activeSlotIdentity = createActiveSlotIdentity(id, options.metadata);
|
|
63
89
|
if (activeSlotIdentity !== null) return activeSlotIdentity;
|
|
64
90
|
return `${id}@${getTreePathIdentityPrefix(options.pathname, parsed.treePath)}`;
|
|
65
91
|
}
|
|
66
|
-
if (parsed.kind === "layout" || parsed.kind === "template") return `${id}@${getTreePathIdentityPrefix(options.pathname, parsed.treePath)}`;
|
|
92
|
+
if (parsed.kind === "layout" || parsed.kind === "template") return `${id}@${getTreePathIdentityPrefix(getTreePathname(parsed.treePath, options.metadata) ?? options.pathname, parsed.treePath)}`;
|
|
67
93
|
return null;
|
|
68
94
|
}
|
|
69
95
|
function collectBfcacheSegmentIdCandidates(elements, metadata = readAppElementsMetadata(elements)) {
|
|
@@ -12,7 +12,7 @@ import { DevRecoveryBoundary, GlobalErrorBoundary, RedirectBoundary } from "../s
|
|
|
12
12
|
import { beginAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
13
13
|
import { AppRouterScrollCommitProvider } from "../shims/app-router-scroll.js";
|
|
14
14
|
import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
|
|
15
|
-
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, getVinextRscCompatibilityId
|
|
15
|
+
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, getVinextRscCompatibilityId } from "./app-rsc-cache-busting.js";
|
|
16
16
|
import { getNavigationRuntime, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
|
|
17
17
|
import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
|
|
18
18
|
import "../client/instrumentation-client.js";
|
|
@@ -24,17 +24,18 @@ import { readHistoryStatePreviousNextUrl } from "./app-history-state.js";
|
|
|
24
24
|
import { AppBrowserMpaNavigationScheduler } from "./app-browser-mpa-navigation.js";
|
|
25
25
|
import { blockDangerousStreamedRscRedirect } from "./app-browser-rsc-redirect.js";
|
|
26
26
|
import { navigationPlanner } from "./navigation-planner.js";
|
|
27
|
-
import { DYNAMIC_NAVIGATION_CACHE_TTL, PREFETCH_CACHE_TTL, __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, deletePrefetchResponseSnapshot, getClientNavigationRenderContext, getMountedSlotsHeader, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, preloadHybridClientRouteOwner, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveLoadedHybridClientRewriteHref, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setPendingPathname, useRouter } from "../shims/navigation.js";
|
|
27
|
+
import { DYNAMIC_NAVIGATION_CACHE_TTL, PREFETCH_CACHE_TTL, __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, deletePrefetchResponseSnapshot, getClientNavigationRenderContext, getMountedSlotsHeader, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, preloadHybridClientRouteOwner, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveLoadedHybridClientRewriteHref, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setPendingPathname, useRouter } from "../shims/navigation.js";
|
|
28
28
|
import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
|
|
29
29
|
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";
|
|
30
30
|
import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch } from "./app-browser-navigation-controller.js";
|
|
31
31
|
import { consumeInitialFormState, createVinextHydrateRootOptions, hydrateRootInTransition } from "./app-browser-hydration.js";
|
|
32
32
|
import { AppBrowserHistoryController } from "./app-browser-history-controller.js";
|
|
33
|
-
import { createVisitedResponseCacheEntry, isVisitedResponseCacheEntryFresh } from "./app-visited-response-cache.js";
|
|
33
|
+
import { createVisitedResponseCacheEntry, deleteVisitedResponseCacheEntry, findVisitedResponseCacheEntry, isVisitedResponseCacheEntryFresh } from "./app-visited-response-cache.js";
|
|
34
34
|
import { createPopstateRestoreHandler, restoreSynchronousPopstateScrollPosition } from "./app-browser-popstate.js";
|
|
35
35
|
import { createDevOnCaughtError, createOnUncaughtError, createProdOnCaughtError, prodOnRecoverableError } from "./app-browser-error.js";
|
|
36
36
|
import { createHydrationCachePublication } from "./app-hydration-cache-publication.js";
|
|
37
|
-
import {
|
|
37
|
+
import { resolvePrefetchNavigationResponseUrl } from "./app-browser-prefetch-response.js";
|
|
38
|
+
import { createOptimisticRouteTemplate, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, matchOptimisticRouteManifestRoute, resolveOptimisticNavigationPayload } from "./app-optimistic-routing.js";
|
|
38
39
|
import { removeStylesheetLinksCoveredByInlineCss } from "./app-inline-css-client.js";
|
|
39
40
|
import { createElement, startTransition, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
40
41
|
import { flushSync } from "react-dom";
|
|
@@ -126,6 +127,7 @@ let latestClientParams = {};
|
|
|
126
127
|
const visitedResponseCache = /* @__PURE__ */ new Map();
|
|
127
128
|
let clientNavigationCacheGeneration = 0;
|
|
128
129
|
let browserRouterStateHasEverCommitted = false;
|
|
130
|
+
let initialPrefetchRouterState = null;
|
|
129
131
|
const mpaNavigationScheduler = new AppBrowserMpaNavigationScheduler();
|
|
130
132
|
const unresolvedMpaNavigation = new Promise(() => {});
|
|
131
133
|
const RSC_HMR_SETTLE_DELAY_MS = 150;
|
|
@@ -193,21 +195,6 @@ function clearClientNavigationCaches() {
|
|
|
193
195
|
clearPrefetchState();
|
|
194
196
|
historyController.invalidateRestorableClientState();
|
|
195
197
|
}
|
|
196
|
-
function normalizeBrowserRscUrlForReuse(url) {
|
|
197
|
-
if (!url) return null;
|
|
198
|
-
try {
|
|
199
|
-
const parsed = new URL(url, window.location.origin);
|
|
200
|
-
stripRscCacheBustingSearchParam(parsed);
|
|
201
|
-
return `${parsed.pathname}${parsed.search}`;
|
|
202
|
-
} catch {
|
|
203
|
-
return null;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
function isAlternatePrefetchResponseUrl(responseUrl, additionalRscUrls) {
|
|
207
|
-
const normalizedResponseUrl = normalizeBrowserRscUrlForReuse(responseUrl);
|
|
208
|
-
if (normalizedResponseUrl === null) return false;
|
|
209
|
-
return additionalRscUrls.some((additionalRscUrl) => normalizeBrowserRscUrlForReuse(additionalRscUrl) === normalizedResponseUrl);
|
|
210
|
-
}
|
|
211
198
|
function isSettledPrefetchCacheEntry(entry) {
|
|
212
199
|
return entry.outcome === "cache-seeded" && entry.pending === void 0 && entry.snapshot !== void 0;
|
|
213
200
|
}
|
|
@@ -347,8 +334,8 @@ function evictVisitedResponseCacheIfNeeded() {
|
|
|
347
334
|
}
|
|
348
335
|
function readVisitedResponseCacheCandidate(rscUrl, interceptionContext, mountedSlotsHeader, navigationKind) {
|
|
349
336
|
const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
|
|
350
|
-
const
|
|
351
|
-
if (!
|
|
337
|
+
const match = findVisitedResponseCacheEntry(visitedResponseCache, rscUrl, interceptionContext);
|
|
338
|
+
if (!match) return {
|
|
352
339
|
cacheKey,
|
|
353
340
|
entry: null,
|
|
354
341
|
facts: {
|
|
@@ -357,15 +344,15 @@ function readVisitedResponseCacheCandidate(rscUrl, interceptionContext, mountedS
|
|
|
357
344
|
}
|
|
358
345
|
};
|
|
359
346
|
return {
|
|
360
|
-
cacheKey,
|
|
361
|
-
entry:
|
|
347
|
+
cacheKey: match.cacheKey,
|
|
348
|
+
entry: match.entry,
|
|
362
349
|
facts: {
|
|
363
350
|
candidate: "present",
|
|
364
|
-
fresh: isVisitedResponseCacheEntryFresh(
|
|
351
|
+
fresh: isVisitedResponseCacheEntryFresh(match.entry, {
|
|
365
352
|
navigationKind,
|
|
366
353
|
now: Date.now()
|
|
367
354
|
}),
|
|
368
|
-
mountedSlotsMatch:
|
|
355
|
+
mountedSlotsMatch: match.entry.elements !== void 0 || match.entry.mountedSlotsHeader === mountedSlotsHeader,
|
|
369
356
|
navigationKind
|
|
370
357
|
}
|
|
371
358
|
};
|
|
@@ -381,9 +368,9 @@ function applyVisitedResponseCacheCandidateDecision(candidate, decision) {
|
|
|
381
368
|
return null;
|
|
382
369
|
}
|
|
383
370
|
function deleteVisitedResponse(rscUrl, interceptionContext) {
|
|
384
|
-
visitedResponseCache
|
|
371
|
+
deleteVisitedResponseCacheEntry(visitedResponseCache, rscUrl, interceptionContext);
|
|
385
372
|
}
|
|
386
|
-
function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, params, prefetchFallbackTtlMs = DYNAMIC_NAVIGATION_CACHE_TTL, requestMountedSlotsHeader = snapshot.mountedSlotsHeader ?? null, elements) {
|
|
373
|
+
function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, params, prefetchFallbackTtlMs = DYNAMIC_NAVIGATION_CACHE_TTL, requestMountedSlotsHeader = snapshot.mountedSlotsHeader ?? null, elements, seedPrefetchCache = true) {
|
|
387
374
|
const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
|
|
388
375
|
visitedResponseCache.delete(cacheKey);
|
|
389
376
|
evictVisitedResponseCacheIfNeeded();
|
|
@@ -396,10 +383,10 @@ function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, par
|
|
|
396
383
|
response: snapshot
|
|
397
384
|
});
|
|
398
385
|
visitedResponseCache.set(cacheKey, entry);
|
|
399
|
-
seedPrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext, requestMountedSlotsHeader, prefetchFallbackTtlMs);
|
|
386
|
+
if (seedPrefetchCache) seedPrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext, requestMountedSlotsHeader, prefetchFallbackTtlMs);
|
|
400
387
|
return () => {
|
|
401
388
|
if (visitedResponseCache.get(cacheKey) === entry) visitedResponseCache.delete(cacheKey);
|
|
402
|
-
deletePrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext);
|
|
389
|
+
if (seedPrefetchCache) deletePrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext);
|
|
403
390
|
};
|
|
404
391
|
}
|
|
405
392
|
function clientNavigationSnapshotHref(snapshot) {
|
|
@@ -778,6 +765,10 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
778
765
|
Promise.all([root, initialCacheBuffer]).then(async ([elements, buffer]) => {
|
|
779
766
|
if (cacheGeneration !== clientNavigationCacheGeneration) return;
|
|
780
767
|
const metadata = AppElementsWire.readMetadata(elements);
|
|
768
|
+
initialPrefetchRouterState = {
|
|
769
|
+
pathAndSearch: initialPathAndSearch,
|
|
770
|
+
routeId: metadata.routeId
|
|
771
|
+
};
|
|
781
772
|
if (!isCompleteAppPayloadMetadata(metadata)) return;
|
|
782
773
|
const mountedSlotsHeader = getMountedSlotIdsHeader(elements);
|
|
783
774
|
const headers = createRscRequestHeaders({ mountedSlotsHeader });
|
|
@@ -796,8 +787,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
796
787
|
const fallbackTtlMs = initialRscBootstrap?.initialCacheKind === "static" ? PREFETCH_CACHE_TTL : DYNAMIC_NAVIGATION_CACHE_TTL;
|
|
797
788
|
hydrationCachePublication.publish(() => {
|
|
798
789
|
if (cacheGeneration !== clientNavigationCacheGeneration) return () => {};
|
|
799
|
-
|
|
800
|
-
return storeVisitedResponseSnapshot(rscUrl, metadata.interceptionContext, snapshot, initialParams, fallbackTtlMs, mountedSlotsHeader, elements);
|
|
790
|
+
return storeVisitedResponseSnapshot(rscUrl, metadata.interceptionContext, snapshot, initialParams, fallbackTtlMs, mountedSlotsHeader, elements, false);
|
|
801
791
|
});
|
|
802
792
|
}).catch(() => {});
|
|
803
793
|
historyController.writeBootstrapHistoryMetadata();
|
|
@@ -855,6 +845,26 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
855
845
|
registerNavigationRuntimeFunctions({
|
|
856
846
|
clearNavigationCaches: clearClientNavigationCaches,
|
|
857
847
|
commitHashNavigation: (href, historyUpdateMode, scroll) => historyController.commitHashOnlyNavigation(href, historyUpdateMode, scroll),
|
|
848
|
+
getPrefetchRouterState: () => {
|
|
849
|
+
if (!browserNavigationController.hasBrowserRouterState()) {
|
|
850
|
+
if (initialPrefetchRouterState) return initialPrefetchRouterState;
|
|
851
|
+
const routeManifest = getNavigationRuntime()?.bootstrap.routeManifest ?? null;
|
|
852
|
+
const match = routeManifest ? matchOptimisticRouteManifestRoute({
|
|
853
|
+
basePath: __basePath,
|
|
854
|
+
href: window.location.href,
|
|
855
|
+
routeManifest
|
|
856
|
+
}) : null;
|
|
857
|
+
return match ? {
|
|
858
|
+
pathAndSearch: createBasePathStrippedPathAndSearch(new URL(window.location.href), __basePath),
|
|
859
|
+
routeId: match.route.id
|
|
860
|
+
} : null;
|
|
861
|
+
}
|
|
862
|
+
const state = browserNavigationController.getBrowserRouterState();
|
|
863
|
+
return {
|
|
864
|
+
pathAndSearch: createSnapshotPathAndSearch(state.navigationSnapshot),
|
|
865
|
+
routeId: state.routeId
|
|
866
|
+
};
|
|
867
|
+
},
|
|
858
868
|
navigate: async function navigateRsc(href, redirectDepth = 0, navigationKind = "navigate", historyUpdateMode, previousNextUrlOverride, programmaticTransition = false, traversalIntent, scrollIntent, visibleCommitMode = "transition") {
|
|
859
869
|
abortSupersededNavigation();
|
|
860
870
|
const navigationAbortController = new AbortController();
|
|
@@ -879,8 +889,9 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
879
889
|
const reuseCurrentBfcacheIds = navigationKind !== "traverse" || !historyController.isCacheInvalidationGuarded() && historyController.isCurrentBfcacheVersion(activeTraversalIntent?.historyState ?? window.history.state);
|
|
880
890
|
try {
|
|
881
891
|
const shouldUsePendingRouterState = programmaticTransition;
|
|
882
|
-
if (
|
|
883
|
-
|
|
892
|
+
if (hasBrowserRouterState()) {
|
|
893
|
+
if (shouldUsePendingRouterState) pendingRouterState = beginPendingBrowserRouterState();
|
|
894
|
+
} else {
|
|
884
895
|
await waitForBrowserRouterStateReady();
|
|
885
896
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
886
897
|
if (shouldUsePendingRouterState) pendingRouterState = beginPendingBrowserRouterState();
|
|
@@ -903,12 +914,21 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
903
914
|
}) : null;
|
|
904
915
|
const shouldBypassNavigationCache = earlyIntentDecision?.kind === "flightNavigation" && earlyIntentDecision.bypassNavigationCache;
|
|
905
916
|
const requestHeaders = createRscRequestHeaders({
|
|
917
|
+
fetchPriority: "auto",
|
|
906
918
|
interceptionContext: requestInterceptionContext,
|
|
907
919
|
mountedSlotsHeader
|
|
908
920
|
});
|
|
909
|
-
const rscUrl = await createRscRequestUrl(url.pathname + url.search, requestHeaders);
|
|
910
921
|
const rewrittenNavigationHref = navigationKind === "navigate" && HAS_CLIENT_REWRITES ? resolveLoadedHybridClientRewriteHref(currentHref, __basePath) : null;
|
|
911
|
-
const
|
|
922
|
+
const targetPathAndSearch = url.pathname + url.search;
|
|
923
|
+
const additionalPrefetchPathAndSearch = rewrittenNavigationHref && rewrittenNavigationHref !== currentHref ? [rewrittenNavigationHref] : [];
|
|
924
|
+
const settledPrefetchedResponse = navigationKind === "navigate" && !shouldBypassNavigationCache ? consumePrefetchResponse(targetPathAndSearch, requestInterceptionContext, mountedSlotsHeader, { additionalRscUrls: additionalPrefetchPathAndSearch }) : null;
|
|
925
|
+
const rscUrl = settledPrefetchedResponse ? resolvePrefetchNavigationResponseUrl({
|
|
926
|
+
additionalRscUrls: additionalPrefetchPathAndSearch,
|
|
927
|
+
origin: window.location.origin,
|
|
928
|
+
responseUrl: settledPrefetchedResponse.url,
|
|
929
|
+
visibleRscUrl: targetPathAndSearch
|
|
930
|
+
}) : await createRscRequestUrl(targetPathAndSearch, requestHeaders);
|
|
931
|
+
const additionalPrefetchRscUrls = settledPrefetchedResponse ? additionalPrefetchPathAndSearch : await Promise.all(additionalPrefetchPathAndSearch.map((href) => createRscRequestUrl(href, requestHeaders)));
|
|
912
932
|
const visitedResponseCandidate = shouldBypassNavigationCache ? {
|
|
913
933
|
cacheKey: AppElementsWire.encodeCacheKey(rscUrl, requestInterceptionContext),
|
|
914
934
|
entry: null,
|
|
@@ -925,7 +945,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
925
945
|
visitedResponse
|
|
926
946
|
});
|
|
927
947
|
let routeManifest = navigationKind === "navigate" ? getBrowserRouteManifest() : null;
|
|
928
|
-
const hasPrefetchCandidate = prefetchProbeDecision.kind === "probe" && hasPrefetchCacheEntryForNavigation(rscUrl, requestInterceptionContext, mountedSlotsHeader, {
|
|
948
|
+
const hasPrefetchCandidate = settledPrefetchedResponse !== null || prefetchProbeDecision.kind === "probe" && hasPrefetchCacheEntryForNavigation(rscUrl, requestInterceptionContext, mountedSlotsHeader, {
|
|
929
949
|
additionalRscUrls: additionalPrefetchRscUrls,
|
|
930
950
|
notifyInvalidation: false
|
|
931
951
|
});
|
|
@@ -1003,17 +1023,24 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1003
1023
|
let navResponse;
|
|
1004
1024
|
let navResponseExpiresAt;
|
|
1005
1025
|
let navResponseUrl = null;
|
|
1026
|
+
let prefetchedElements;
|
|
1006
1027
|
let fallbackReuseDecision = reuseDecision;
|
|
1007
1028
|
if (reuseDecision.kind === "consumePrefetch") {
|
|
1008
|
-
const prefetchedResponse = await consumePrefetchResponseForNavigation(rscUrl, requestInterceptionContext, mountedSlotsHeader, {
|
|
1029
|
+
const prefetchedResponse = settledPrefetchedResponse ?? await consumePrefetchResponseForNavigation(rscUrl, requestInterceptionContext, mountedSlotsHeader, {
|
|
1009
1030
|
additionalRscUrls: additionalPrefetchRscUrls,
|
|
1010
1031
|
shouldConsume: () => browserNavigationController.isCurrentNavigation(navId)
|
|
1011
1032
|
});
|
|
1012
1033
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
1013
1034
|
if (prefetchedResponse) {
|
|
1035
|
+
prefetchedElements = prefetchedResponse.preparedElements;
|
|
1014
1036
|
navResponse = restoreRscResponse(prefetchedResponse, false);
|
|
1015
1037
|
navResponseExpiresAt = prefetchedResponse.expiresAt;
|
|
1016
|
-
navResponseUrl =
|
|
1038
|
+
navResponseUrl = resolvePrefetchNavigationResponseUrl({
|
|
1039
|
+
additionalRscUrls: additionalPrefetchRscUrls,
|
|
1040
|
+
origin: window.location.origin,
|
|
1041
|
+
responseUrl: prefetchedResponse.url,
|
|
1042
|
+
visibleRscUrl: rscUrl
|
|
1043
|
+
});
|
|
1017
1044
|
}
|
|
1018
1045
|
if (!navResponse) {
|
|
1019
1046
|
routeManifest = navigationKind === "navigate" ? getBrowserRouteManifest() : null;
|
|
@@ -1082,6 +1109,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1082
1109
|
navResponse = await fetch(rscUrl, {
|
|
1083
1110
|
headers: requestHeaders,
|
|
1084
1111
|
credentials: "include",
|
|
1112
|
+
priority: "auto",
|
|
1085
1113
|
signal: navigationAbortController.signal
|
|
1086
1114
|
});
|
|
1087
1115
|
}
|
|
@@ -1135,7 +1163,8 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1135
1163
|
const cacheBufferPromise = new Response(cacheBranch).arrayBuffer();
|
|
1136
1164
|
cacheBufferPromise.catch(() => {});
|
|
1137
1165
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
1138
|
-
|
|
1166
|
+
if (prefetchedElements) reactBranch.cancel().catch(() => {});
|
|
1167
|
+
const rscPayload = prefetchedElements ? prefetchedElements : decodeAppElementsPromise(createFromFetch(Promise.resolve(reactResponse)));
|
|
1139
1168
|
if (!browserNavigationController.isCurrentNavigation(navId)) return;
|
|
1140
1169
|
let committedState = null;
|
|
1141
1170
|
if (await renderNavigationPayload({
|
|
@@ -1160,8 +1189,9 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1160
1189
|
scrollIntent,
|
|
1161
1190
|
targetHref: currentHref,
|
|
1162
1191
|
traversalIntent: activeTraversalIntent,
|
|
1163
|
-
visibleCommitMode
|
|
1192
|
+
visibleCommitMode: prefetchedElements ? "synchronous" : visibleCommitMode
|
|
1164
1193
|
}) !== "committed") return;
|
|
1194
|
+
committedState ??= getBrowserRouterState();
|
|
1165
1195
|
try {
|
|
1166
1196
|
const renderedElements = await rscPayload;
|
|
1167
1197
|
if (navigationCacheGeneration !== clientNavigationCacheGeneration) return;
|
|
@@ -1182,7 +1212,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1182
1212
|
if (isCacheRestorableAppPayloadMetadata(metadata)) {
|
|
1183
1213
|
if (navigationCacheGeneration !== clientNavigationCacheGeneration) return;
|
|
1184
1214
|
storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, navParams, PREFETCH_CACHE_TTL, mountedSlotsHeader);
|
|
1185
|
-
} else
|
|
1215
|
+
} else {
|
|
1186
1216
|
const state = committedState;
|
|
1187
1217
|
const committedElements = {
|
|
1188
1218
|
...state.elements,
|
|
@@ -1193,9 +1223,6 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1193
1223
|
};
|
|
1194
1224
|
if (navigationCacheGeneration !== clientNavigationCacheGeneration) return;
|
|
1195
1225
|
storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, navParams, DYNAMIC_NAVIGATION_CACHE_TTL, mountedSlotsHeader, committedElements);
|
|
1196
|
-
} else {
|
|
1197
|
-
if (navigationCacheGeneration !== clientNavigationCacheGeneration) return;
|
|
1198
|
-
seedPrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext, mountedSlotsHeader, DYNAMIC_NAVIGATION_CACHE_TTL);
|
|
1199
1226
|
}
|
|
1200
1227
|
} catch {}
|
|
1201
1228
|
return;
|
|
@@ -1209,7 +1236,8 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1209
1236
|
browserNavigationController.finalizeNavigation(navId, pendingRouterState);
|
|
1210
1237
|
discardedServerActionRefreshScheduler.markNavigationSettled();
|
|
1211
1238
|
}
|
|
1212
|
-
}
|
|
1239
|
+
},
|
|
1240
|
+
preparePrefetchResponse: (response) => decodeAppElementsPromise(createFromFetch(Promise.resolve(response)))
|
|
1213
1241
|
});
|
|
1214
1242
|
const handlePopstate = createPopstateRestoreHandler({
|
|
1215
1243
|
getActiveNavigationId: browserNavigationController.getActiveNavigationId.bind(browserNavigationController),
|
|
@@ -51,7 +51,7 @@ type BrowserNavigationPayloadOptions = {
|
|
|
51
51
|
navigationInitiationState: AppRouterState;
|
|
52
52
|
navigationSnapshot: ClientNavigationRenderSnapshot;
|
|
53
53
|
navId: number;
|
|
54
|
-
nextElements: Promise<AppElements
|
|
54
|
+
nextElements: Promise<AppElements> | AppElements;
|
|
55
55
|
onCommittedState?: (state: AppRouterState) => void;
|
|
56
56
|
operationLane: OperationLane;
|
|
57
57
|
params: Record<string, string | string[]>;
|
|
@@ -3,7 +3,7 @@ import { clearAppNavigationFailureTarget, getAppNavigationFailureTarget } from "
|
|
|
3
3
|
import { claimAppRouterScrollIntentForCommit, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
4
4
|
import { resolveServerActionOperationLane, shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
|
|
5
5
|
import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
6
|
-
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, createPendingNavigationCommit } from "./app-browser-state.js";
|
|
6
|
+
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, createPendingNavigationCommit, createPendingNavigationCommitFromElements } 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";
|
|
9
9
|
import { flushSync } from "react-dom";
|
|
@@ -255,6 +255,9 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
255
255
|
pendingRouterState.settled = true;
|
|
256
256
|
pendingRouterState.resolve(committedState);
|
|
257
257
|
if (activePendingBrowserRouterState === pendingRouterState) activePendingBrowserRouterState = null;
|
|
258
|
+
if (visibleCommitMode === "synchronous") flushSync(() => {
|
|
259
|
+
setter(committedState);
|
|
260
|
+
});
|
|
258
261
|
return;
|
|
259
262
|
}
|
|
260
263
|
if (visibleCommitMode === "synchronous") {
|
|
@@ -332,6 +335,22 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
332
335
|
if (!shouldScheduleRefreshForDiscardedServerAction(lifecycleOptions?.revalidation ?? "none")) return;
|
|
333
336
|
lifecycleOptions?.onDiscardedRevalidation?.();
|
|
334
337
|
}
|
|
338
|
+
function isSamePathSearchHashCommit(targetHref) {
|
|
339
|
+
if (typeof window === "undefined") return false;
|
|
340
|
+
try {
|
|
341
|
+
const currentUrl = new URL(window.location.href);
|
|
342
|
+
const targetUrl = new URL(targetHref, currentUrl.href);
|
|
343
|
+
return targetUrl.origin === currentUrl.origin && targetUrl.pathname === currentUrl.pathname && targetUrl.search !== currentUrl.search && targetUrl.hash !== "";
|
|
344
|
+
} catch {
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function shouldForceSynchronousCommit(options) {
|
|
349
|
+
if (options.actionType === "traverse") return false;
|
|
350
|
+
if (options.historyUpdateMode === void 0) return false;
|
|
351
|
+
if (options.scrollIntent?.hash == null) return false;
|
|
352
|
+
return isSamePathSearchHashCommit(options.targetHref);
|
|
353
|
+
}
|
|
335
354
|
async function renderNavigationPayload(options) {
|
|
336
355
|
if (options.navId === pendingUserNavigationId) pendingUserNavigationLane = options.operationLane;
|
|
337
356
|
const renderId = allocateRenderId();
|
|
@@ -348,11 +367,10 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
348
367
|
});
|
|
349
368
|
let snapshotActivated = false;
|
|
350
369
|
try {
|
|
351
|
-
const
|
|
370
|
+
const pendingOptions = {
|
|
352
371
|
currentState: options.navigationInitiationState,
|
|
353
372
|
navigationCommitKind: options.navigationCommitKind,
|
|
354
373
|
navigationId: options.navId,
|
|
355
|
-
nextElements: options.nextElements,
|
|
356
374
|
navigationSnapshot: options.navigationSnapshot,
|
|
357
375
|
operationLane: options.operationLane,
|
|
358
376
|
payloadOrigin: options.payloadOrigin,
|
|
@@ -361,6 +379,13 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
361
379
|
restoredBfcacheIds: options.restoredBfcacheIds,
|
|
362
380
|
reuseCurrentBfcacheIds: options.reuseCurrentBfcacheIds,
|
|
363
381
|
type: options.actionType
|
|
382
|
+
};
|
|
383
|
+
const pending = options.nextElements instanceof Promise ? await createPendingNavigationCommit({
|
|
384
|
+
...pendingOptions,
|
|
385
|
+
nextElements: options.nextElements
|
|
386
|
+
}) : createPendingNavigationCommitFromElements({
|
|
387
|
+
...pendingOptions,
|
|
388
|
+
nextElements: options.nextElements
|
|
364
389
|
});
|
|
365
390
|
const approval = approvePendingNavigationCommit({
|
|
366
391
|
activeNavigationId,
|
|
@@ -402,7 +427,7 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
402
427
|
claimAppRouterScrollIntentForCommit(options.scrollIntent, renderId);
|
|
403
428
|
activateNavigationSnapshot();
|
|
404
429
|
snapshotActivated = true;
|
|
405
|
-
dispatchApprovedVisibleCommit(renderId, approvedCommit, options.pendingRouterState, options.visibleCommitMode ?? "transition");
|
|
430
|
+
dispatchApprovedVisibleCommit(renderId, approvedCommit, options.pendingRouterState, shouldForceSynchronousCommit(options) ? "synchronous" : options.visibleCommitMode ?? "transition");
|
|
406
431
|
} catch (error) {
|
|
407
432
|
pendingNavigationFailureTargets.delete(renderId);
|
|
408
433
|
pendingNavigationPrePaintEffects.delete(renderId);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/server/app-browser-prefetch-response.d.ts
|
|
2
|
+
declare function resolvePrefetchNavigationResponseUrl(options: {
|
|
3
|
+
additionalRscUrls: readonly string[];
|
|
4
|
+
origin: string;
|
|
5
|
+
responseUrl: string;
|
|
6
|
+
visibleRscUrl: string;
|
|
7
|
+
}): string;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { resolvePrefetchNavigationResponseUrl };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { stripRscCacheBustingSearchParam } from "./app-rsc-cache-busting.js";
|
|
2
|
+
//#region src/server/app-browser-prefetch-response.ts
|
|
3
|
+
function normalizeBrowserRscUrlForReuse(url, origin) {
|
|
4
|
+
if (!url) return null;
|
|
5
|
+
try {
|
|
6
|
+
const parsed = new URL(url, origin);
|
|
7
|
+
stripRscCacheBustingSearchParam(parsed);
|
|
8
|
+
return `${parsed.pathname}${parsed.search}`;
|
|
9
|
+
} catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function isSameOriginBrowserRscUrl(url, origin) {
|
|
14
|
+
try {
|
|
15
|
+
return new URL(url, origin).origin === new URL(origin).origin;
|
|
16
|
+
} catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function canonicalizeBrowserRscResponseUrl(responseUrl, origin) {
|
|
21
|
+
try {
|
|
22
|
+
const parsed = new URL(responseUrl, origin);
|
|
23
|
+
if (parsed.origin === new URL(origin).origin) return `${parsed.pathname}${parsed.search}`;
|
|
24
|
+
} catch {}
|
|
25
|
+
return responseUrl;
|
|
26
|
+
}
|
|
27
|
+
function resolvePrefetchNavigationResponseUrl(options) {
|
|
28
|
+
const normalizedResponseUrl = normalizeBrowserRscUrlForReuse(options.responseUrl, options.origin);
|
|
29
|
+
return normalizedResponseUrl !== null && isSameOriginBrowserRscUrl(options.responseUrl, options.origin) && options.additionalRscUrls.some((additionalRscUrl) => normalizeBrowserRscUrlForReuse(additionalRscUrl, options.origin) === normalizedResponseUrl) ? options.visibleRscUrl : canonicalizeBrowserRscResponseUrl(options.responseUrl, options.origin);
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { resolvePrefetchNavigationResponseUrl };
|
|
@@ -133,11 +133,10 @@ declare function resolvePendingNavigationCommitDispositionDecision(options: {
|
|
|
133
133
|
startedNavigationId: number;
|
|
134
134
|
targetHref?: string;
|
|
135
135
|
}): PendingNavigationCommitDispositionDecision;
|
|
136
|
-
|
|
136
|
+
type CreatePendingNavigationCommitOptions = {
|
|
137
137
|
currentState: AppRouterState;
|
|
138
138
|
navigationCommitKind?: "authoritative" | "detached";
|
|
139
139
|
navigationId?: number;
|
|
140
|
-
nextElements: Promise<AppElements>;
|
|
141
140
|
navigationSnapshot: ClientNavigationRenderSnapshot;
|
|
142
141
|
operationLane: OperationLane;
|
|
143
142
|
payloadOrigin: AppNavigationPayloadOrigin;
|
|
@@ -146,6 +145,12 @@ declare function createPendingNavigationCommit(options: {
|
|
|
146
145
|
restoredBfcacheIds?: BfcacheIdMap | null;
|
|
147
146
|
reuseCurrentBfcacheIds?: boolean;
|
|
148
147
|
type: "navigate" | "replace" | "traverse";
|
|
148
|
+
};
|
|
149
|
+
declare function createPendingNavigationCommitFromElements(options: CreatePendingNavigationCommitOptions & {
|
|
150
|
+
nextElements: AppElements;
|
|
151
|
+
}): PendingNavigationCommit;
|
|
152
|
+
declare function createPendingNavigationCommit(options: CreatePendingNavigationCommitOptions & {
|
|
153
|
+
nextElements: Promise<AppElements>;
|
|
149
154
|
}): Promise<PendingNavigationCommit>;
|
|
150
155
|
//#endregion
|
|
151
|
-
export { AppNavigationPayloadOrigin, AppRouterAction, AppRouterState,
|
|
156
|
+
export { AppNavigationPayloadOrigin, AppRouterAction, AppRouterState, 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, createPendingNavigationCommitFromElements, isCacheRestorableAppPayloadMetadata, isCompleteAppPayloadMetadata, isHistoryStateBfcacheVersionCurrent, preserveBfcacheIdsForMergedElements, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent, resolveInterceptionContextFromPreviousNextUrl, resolvePendingNavigationCommitDispositionDecision, resolveServerActionRequestState };
|
|
@@ -279,8 +279,8 @@ function mergeSkippedLayoutSlotPreservation(options) {
|
|
|
279
279
|
}
|
|
280
280
|
return preservePreviousSlotIds;
|
|
281
281
|
}
|
|
282
|
-
|
|
283
|
-
const elements =
|
|
282
|
+
function createPendingNavigationCommitFromElements(options) {
|
|
283
|
+
const elements = options.nextElements;
|
|
284
284
|
const metadata = AppElementsWire.readMetadata(elements);
|
|
285
285
|
const cacheEntryReuseProof = metadata.cacheEntryReuseProof ?? (requiresCacheEntryReuseProof(options.payloadOrigin) ? createCacheEntryReuseProof(null) : void 0);
|
|
286
286
|
const requestedPreviousNextUrl = options.previousNextUrl !== void 0 ? options.previousNextUrl : options.currentState.previousNextUrl;
|
|
@@ -328,5 +328,11 @@ async function createPendingNavigationCommit(options) {
|
|
|
328
328
|
skippedLayoutIds: metadata.skippedLayoutIds
|
|
329
329
|
};
|
|
330
330
|
}
|
|
331
|
+
async function createPendingNavigationCommit(options) {
|
|
332
|
+
return createPendingNavigationCommitFromElements({
|
|
333
|
+
...options,
|
|
334
|
+
nextElements: await options.nextElements
|
|
335
|
+
});
|
|
336
|
+
}
|
|
331
337
|
//#endregion
|
|
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 };
|
|
338
|
+
export { COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, createBfcacheSegmentStateKeyMap, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createInitialBfcacheIdMap, createNextBfcacheIdMap, createPendingNavigationCommit, createPendingNavigationCommitFromElements, isCacheRestorableAppPayloadMetadata, isCompleteAppPayloadMetadata, isHistoryStateBfcacheVersionCurrent, preserveBfcacheIdsForMergedElements, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent, resolveInterceptionContextFromPreviousNextUrl, resolvePendingNavigationCommitDispositionDecision, resolveServerActionRequestState };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ClassificationReason } from "../build/layout-classification-types.js";
|
|
2
2
|
import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
|
|
3
3
|
import { AppOutgoingElements } from "./app-elements-wire.js";
|
|
4
|
+
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
4
5
|
import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
5
6
|
import { AppPageFontPreload, LayoutClassificationOptions } from "./app-page-execution.js";
|
|
6
7
|
import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
7
8
|
import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
|
|
8
|
-
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
9
9
|
import { RootParams } from "../shims/root-params.js";
|
|
10
10
|
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
11
11
|
import { CachedAppPageValue } from "../shims/cache-handler.js";
|
|
@@ -348,13 +348,17 @@ async function dispatchAppPageInner(options) {
|
|
|
348
348
|
}
|
|
349
349
|
if (options.skipStaticParamsValidation !== true && !(options.isProduction && isForceDynamic)) {
|
|
350
350
|
const dynamicParamsResponse = await validateAppPageDynamicParams({
|
|
351
|
-
clearRequestContext: options.clearRequestContext,
|
|
352
351
|
enforceStaticParamsOnly: options.dynamicParamsConfig === false,
|
|
353
352
|
generateStaticParams: options.generateStaticParams,
|
|
354
353
|
isDynamicRoute: route.isDynamic,
|
|
355
354
|
params: options.staticParamsValidationParams ?? options.params
|
|
356
355
|
});
|
|
357
|
-
if (dynamicParamsResponse)
|
|
356
|
+
if (dynamicParamsResponse) {
|
|
357
|
+
const renderedNotFound = await options.renderHttpAccessFallbackPage(404, { matchedParams: options.params }, options.middlewareContext);
|
|
358
|
+
if (renderedNotFound) return renderedNotFound;
|
|
359
|
+
options.clearRequestContext();
|
|
360
|
+
return dynamicParamsResponse;
|
|
361
|
+
}
|
|
358
362
|
}
|
|
359
363
|
const fallbackShellResponse = options.pprRuntime ? await options.pprRuntime.tryServe(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) : null;
|
|
360
364
|
if (fallbackShellResponse) return fallbackShellResponse;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { MetadataFileRoute } from "./metadata-routes.js";
|
|
2
2
|
import { AppElements } from "./app-elements-wire.js";
|
|
3
|
+
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
3
4
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
4
5
|
import { ApplyAppPageFileBasedMetadata } from "./app-page-head.js";
|
|
5
6
|
import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
|
|
6
|
-
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
7
7
|
import { AppPageErrorModule, AppPageModule, AppPageRouteWiringRoute } from "./app-page-route-wiring.js";
|
|
8
8
|
|
|
9
9
|
//#region src/server/app-page-element-builder.d.ts
|
|
@@ -66,6 +66,7 @@ type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TEr
|
|
|
66
66
|
basePath?: string; /** Configured next.config `trailingSlash`, threaded into canonical URL rendering. */
|
|
67
67
|
trailingSlash?: boolean; /** Serialized next.config `htmlLimitedBots` regexp source. */
|
|
68
68
|
htmlLimitedBots?: string;
|
|
69
|
+
scriptNonce?: string;
|
|
69
70
|
};
|
|
70
71
|
type AppPageNavigationParamModule = {
|
|
71
72
|
default?: unknown;
|
|
@@ -254,6 +254,7 @@ async function buildPageElements(options) {
|
|
|
254
254
|
resolvedMetadata,
|
|
255
255
|
resolvedMetadataPathname: routePath,
|
|
256
256
|
resolvedViewport,
|
|
257
|
+
scriptNonce: options.scriptNonce,
|
|
257
258
|
streamingMetadata,
|
|
258
259
|
streamingMetadataOutlet,
|
|
259
260
|
streamingMetadataOutletSuspended: streamGeneratedHead,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ClientReuseManifestParseResult, ClientReuseManifestSkipDisposition } from "./client-reuse-manifest.js";
|
|
2
2
|
import { AppOutgoingElements } from "./app-elements-wire.js";
|
|
3
|
+
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
3
4
|
import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
4
5
|
import { AppPageFontPreload, AppPageSpecialError, LayoutClassificationOptions } from "./app-page-execution.js";
|
|
5
6
|
import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
6
7
|
import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
|
|
7
|
-
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
8
8
|
import { RootParams } from "../shims/root-params.js";
|
|
9
9
|
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
10
10
|
import { CachedAppPageValue } from "../shims/cache-handler.js";
|