Initial commit
This commit is contained in:
commit
78f8d225ee
21173 changed files with 2907774 additions and 0 deletions
49
node_modules/next/dist/esm/client/components/router-reducer/reducers/find-head-in-cache.js
generated
vendored
Normal file
49
node_modules/next/dist/esm/client/components/router-reducer/reducers/find-head-in-cache.js
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import { createRouterCacheKey } from '../create-router-cache-key';
|
||||
export function findHeadInCache(cache, parallelRoutes) {
|
||||
return findHeadInCacheImpl(cache, parallelRoutes, '');
|
||||
}
|
||||
function findHeadInCacheImpl(cache, parallelRoutes, keyPrefix) {
|
||||
const isLastItem = Object.keys(parallelRoutes).length === 0;
|
||||
if (isLastItem) {
|
||||
// Returns the entire Cache Node of the segment whose head we will render.
|
||||
return [
|
||||
cache,
|
||||
keyPrefix
|
||||
];
|
||||
}
|
||||
// First try the 'children' parallel route if it exists
|
||||
// when starting from the "root", this corresponds with the main page component
|
||||
if (parallelRoutes.children) {
|
||||
const [segment, childParallelRoutes] = parallelRoutes.children;
|
||||
const childSegmentMap = cache.parallelRoutes.get('children');
|
||||
if (childSegmentMap) {
|
||||
const cacheKey = createRouterCacheKey(segment);
|
||||
const cacheNode = childSegmentMap.get(cacheKey);
|
||||
if (cacheNode) {
|
||||
const item = findHeadInCacheImpl(cacheNode, childParallelRoutes, keyPrefix + '/' + cacheKey);
|
||||
if (item) return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we didn't find metadata in the page slot, check the other parallel routes
|
||||
for(const key in parallelRoutes){
|
||||
if (key === 'children') continue; // already checked above
|
||||
const [segment, childParallelRoutes] = parallelRoutes[key];
|
||||
const childSegmentMap = cache.parallelRoutes.get(key);
|
||||
if (!childSegmentMap) {
|
||||
continue;
|
||||
}
|
||||
const cacheKey = createRouterCacheKey(segment);
|
||||
const cacheNode = childSegmentMap.get(cacheKey);
|
||||
if (!cacheNode) {
|
||||
continue;
|
||||
}
|
||||
const item = findHeadInCacheImpl(cacheNode, childParallelRoutes, keyPrefix + '/' + cacheKey);
|
||||
if (item) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=find-head-in-cache.js.map
|
||||
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/find-head-in-cache.js.map
generated
vendored
Normal file
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/find-head-in-cache.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/find-head-in-cache.ts"],"sourcesContent":["import type { FlightRouterState } from '../../../../server/app-render/types'\nimport type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime'\nimport { createRouterCacheKey } from '../create-router-cache-key'\n\nexport function findHeadInCache(\n cache: CacheNode,\n parallelRoutes: FlightRouterState[1]\n): [CacheNode, string] | null {\n return findHeadInCacheImpl(cache, parallelRoutes, '')\n}\n\nfunction findHeadInCacheImpl(\n cache: CacheNode,\n parallelRoutes: FlightRouterState[1],\n keyPrefix: string\n): [CacheNode, string] | null {\n const isLastItem = Object.keys(parallelRoutes).length === 0\n if (isLastItem) {\n // Returns the entire Cache Node of the segment whose head we will render.\n return [cache, keyPrefix]\n }\n\n // First try the 'children' parallel route if it exists\n // when starting from the \"root\", this corresponds with the main page component\n if (parallelRoutes.children) {\n const [segment, childParallelRoutes] = parallelRoutes.children\n const childSegmentMap = cache.parallelRoutes.get('children')\n if (childSegmentMap) {\n const cacheKey = createRouterCacheKey(segment)\n const cacheNode = childSegmentMap.get(cacheKey)\n if (cacheNode) {\n const item = findHeadInCacheImpl(\n cacheNode,\n childParallelRoutes,\n keyPrefix + '/' + cacheKey\n )\n if (item) return item\n }\n }\n }\n\n // if we didn't find metadata in the page slot, check the other parallel routes\n for (const key in parallelRoutes) {\n if (key === 'children') continue // already checked above\n\n const [segment, childParallelRoutes] = parallelRoutes[key]\n const childSegmentMap = cache.parallelRoutes.get(key)\n if (!childSegmentMap) {\n continue\n }\n\n const cacheKey = createRouterCacheKey(segment)\n\n const cacheNode = childSegmentMap.get(cacheKey)\n if (!cacheNode) {\n continue\n }\n\n const item = findHeadInCacheImpl(\n cacheNode,\n childParallelRoutes,\n keyPrefix + '/' + cacheKey\n )\n if (item) {\n return item\n }\n }\n\n return null\n}\n"],"names":["createRouterCacheKey","findHeadInCache","cache","parallelRoutes","findHeadInCacheImpl","keyPrefix","isLastItem","Object","keys","length","children","segment","childParallelRoutes","childSegmentMap","get","cacheKey","cacheNode","item","key"],"mappings":"AAEA,SAASA,oBAAoB,QAAQ,6BAA4B;AAEjE,OAAO,SAASC,gBACdC,KAAgB,EAChBC,cAAoC;IAEpC,OAAOC,oBAAoBF,OAAOC,gBAAgB;AACpD;AAEA,SAASC,oBACPF,KAAgB,EAChBC,cAAoC,EACpCE,SAAiB;IAEjB,MAAMC,aAAaC,OAAOC,IAAI,CAACL,gBAAgBM,MAAM,KAAK;IAC1D,IAAIH,YAAY;QACd,0EAA0E;QAC1E,OAAO;YAACJ;YAAOG;SAAU;IAC3B;IAEA,uDAAuD;IACvD,+EAA+E;IAC/E,IAAIF,eAAeO,QAAQ,EAAE;QAC3B,MAAM,CAACC,SAASC,oBAAoB,GAAGT,eAAeO,QAAQ;QAC9D,MAAMG,kBAAkBX,MAAMC,cAAc,CAACW,GAAG,CAAC;QACjD,IAAID,iBAAiB;YACnB,MAAME,WAAWf,qBAAqBW;YACtC,MAAMK,YAAYH,gBAAgBC,GAAG,CAACC;YACtC,IAAIC,WAAW;gBACb,MAAMC,OAAOb,oBACXY,WACAJ,qBACAP,YAAY,MAAMU;gBAEpB,IAAIE,MAAM,OAAOA;YACnB;QACF;IACF;IAEA,+EAA+E;IAC/E,IAAK,MAAMC,OAAOf,eAAgB;QAChC,IAAIe,QAAQ,YAAY,UAAS,wBAAwB;QAEzD,MAAM,CAACP,SAASC,oBAAoB,GAAGT,cAAc,CAACe,IAAI;QAC1D,MAAML,kBAAkBX,MAAMC,cAAc,CAACW,GAAG,CAACI;QACjD,IAAI,CAACL,iBAAiB;YACpB;QACF;QAEA,MAAME,WAAWf,qBAAqBW;QAEtC,MAAMK,YAAYH,gBAAgBC,GAAG,CAACC;QACtC,IAAI,CAACC,WAAW;YACd;QACF;QAEA,MAAMC,OAAOb,oBACXY,WACAJ,qBACAP,YAAY,MAAMU;QAEpB,IAAIE,MAAM;YACR,OAAOA;QACT;IACF;IAEA,OAAO;AACT"}
|
||||
5
node_modules/next/dist/esm/client/components/router-reducer/reducers/get-segment-value.js
generated
vendored
Normal file
5
node_modules/next/dist/esm/client/components/router-reducer/reducers/get-segment-value.js
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export function getSegmentValue(segment) {
|
||||
return Array.isArray(segment) ? segment[1] : segment;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=get-segment-value.js.map
|
||||
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/get-segment-value.js.map
generated
vendored
Normal file
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/get-segment-value.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/get-segment-value.ts"],"sourcesContent":["import type { Segment } from '../../../../server/app-render/types'\n\nexport function getSegmentValue(segment: Segment) {\n return Array.isArray(segment) ? segment[1] : segment\n}\n"],"names":["getSegmentValue","segment","Array","isArray"],"mappings":"AAEA,OAAO,SAASA,gBAAgBC,OAAgB;IAC9C,OAAOC,MAAMC,OAAO,CAACF,WAAWA,OAAO,CAAC,EAAE,GAAGA;AAC/C"}
|
||||
23
node_modules/next/dist/esm/client/components/router-reducer/reducers/has-interception-route-in-current-tree.js
generated
vendored
Normal file
23
node_modules/next/dist/esm/client/components/router-reducer/reducers/has-interception-route-in-current-tree.js
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { isInterceptionRouteAppPath } from '../../../../shared/lib/router/utils/interception-routes';
|
||||
export function hasInterceptionRouteInCurrentTree(param) {
|
||||
let [segment, parallelRoutes] = param;
|
||||
// If we have a dynamic segment, it's marked as an interception route by the presence of the `i` suffix.
|
||||
if (Array.isArray(segment) && (segment[2] === 'di' || segment[2] === 'ci')) {
|
||||
return true;
|
||||
}
|
||||
// If segment is not an array, apply the existing string-based check
|
||||
if (typeof segment === 'string' && isInterceptionRouteAppPath(segment)) {
|
||||
return true;
|
||||
}
|
||||
// Iterate through parallelRoutes if they exist
|
||||
if (parallelRoutes) {
|
||||
for(const key in parallelRoutes){
|
||||
if (hasInterceptionRouteInCurrentTree(parallelRoutes[key])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=has-interception-route-in-current-tree.js.map
|
||||
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/has-interception-route-in-current-tree.js.map
generated
vendored
Normal file
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/has-interception-route-in-current-tree.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/has-interception-route-in-current-tree.ts"],"sourcesContent":["import type { FlightRouterState } from '../../../../server/app-render/types'\nimport { isInterceptionRouteAppPath } from '../../../../shared/lib/router/utils/interception-routes'\n\nexport function hasInterceptionRouteInCurrentTree([\n segment,\n parallelRoutes,\n]: FlightRouterState): boolean {\n // If we have a dynamic segment, it's marked as an interception route by the presence of the `i` suffix.\n if (Array.isArray(segment) && (segment[2] === 'di' || segment[2] === 'ci')) {\n return true\n }\n\n // If segment is not an array, apply the existing string-based check\n if (typeof segment === 'string' && isInterceptionRouteAppPath(segment)) {\n return true\n }\n\n // Iterate through parallelRoutes if they exist\n if (parallelRoutes) {\n for (const key in parallelRoutes) {\n if (hasInterceptionRouteInCurrentTree(parallelRoutes[key])) {\n return true\n }\n }\n }\n\n return false\n}\n"],"names":["isInterceptionRouteAppPath","hasInterceptionRouteInCurrentTree","segment","parallelRoutes","Array","isArray","key"],"mappings":"AACA,SAASA,0BAA0B,QAAQ,0DAAyD;AAEpG,OAAO,SAASC,kCAAkC,KAG9B;IAH8B,IAAA,CAChDC,SACAC,eACkB,GAH8B;IAIhD,wGAAwG;IACxG,IAAIC,MAAMC,OAAO,CAACH,YAAaA,CAAAA,OAAO,CAAC,EAAE,KAAK,QAAQA,OAAO,CAAC,EAAE,KAAK,IAAG,GAAI;QAC1E,OAAO;IACT;IAEA,oEAAoE;IACpE,IAAI,OAAOA,YAAY,YAAYF,2BAA2BE,UAAU;QACtE,OAAO;IACT;IAEA,+CAA+C;IAC/C,IAAIC,gBAAgB;QAClB,IAAK,MAAMG,OAAOH,eAAgB;YAChC,IAAIF,kCAAkCE,cAAc,CAACG,IAAI,GAAG;gBAC1D,OAAO;YACT;QACF;IACF;IAEA,OAAO;AACT"}
|
||||
82
node_modules/next/dist/esm/client/components/router-reducer/reducers/hmr-refresh-reducer.js
generated
vendored
Normal file
82
node_modules/next/dist/esm/client/components/router-reducer/reducers/hmr-refresh-reducer.js
generated
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import { fetchServerResponse } from '../fetch-server-response';
|
||||
import { createHrefFromUrl } from '../create-href-from-url';
|
||||
import { applyRouterStatePatchToTree } from '../apply-router-state-patch-to-tree';
|
||||
import { isNavigatingToNewRootLayout } from '../is-navigating-to-new-root-layout';
|
||||
import { handleExternalUrl } from './navigate-reducer';
|
||||
import { handleMutable } from '../handle-mutable';
|
||||
import { applyFlightData } from '../apply-flight-data';
|
||||
import { createEmptyCacheNode } from '../../app-router';
|
||||
import { handleSegmentMismatch } from '../handle-segment-mismatch';
|
||||
import { hasInterceptionRouteInCurrentTree } from './has-interception-route-in-current-tree';
|
||||
// A version of refresh reducer that keeps the cache around instead of wiping all of it.
|
||||
function hmrRefreshReducerImpl(state, action) {
|
||||
const { origin } = action;
|
||||
const mutable = {};
|
||||
const href = state.canonicalUrl;
|
||||
mutable.preserveCustomHistoryState = false;
|
||||
const cache = createEmptyCacheNode();
|
||||
// If the current tree was intercepted, the nextUrl should be included in the request.
|
||||
// This is to ensure that the refresh request doesn't get intercepted, accidentally triggering the interception route.
|
||||
const includeNextUrl = hasInterceptionRouteInCurrentTree(state.tree);
|
||||
// TODO-APP: verify that `href` is not an external url.
|
||||
// Fetch data from the root of the tree.
|
||||
const navigatedAt = Date.now();
|
||||
cache.lazyData = fetchServerResponse(new URL(href, origin), {
|
||||
flightRouterState: [
|
||||
state.tree[0],
|
||||
state.tree[1],
|
||||
state.tree[2],
|
||||
'refetch'
|
||||
],
|
||||
nextUrl: includeNextUrl ? state.nextUrl : null,
|
||||
isHmrRefresh: true
|
||||
});
|
||||
return cache.lazyData.then((param)=>{
|
||||
let { flightData, canonicalUrl: canonicalUrlOverride } = param;
|
||||
// Handle case when navigating to page in `pages` from `app`
|
||||
if (typeof flightData === 'string') {
|
||||
return handleExternalUrl(state, mutable, flightData, state.pushRef.pendingPush);
|
||||
}
|
||||
// Remove cache.lazyData as it has been resolved at this point.
|
||||
cache.lazyData = null;
|
||||
let currentTree = state.tree;
|
||||
let currentCache = state.cache;
|
||||
for (const normalizedFlightData of flightData){
|
||||
const { tree: treePatch, isRootRender } = normalizedFlightData;
|
||||
if (!isRootRender) {
|
||||
// TODO-APP: handle this case better
|
||||
console.log('REFRESH FAILED');
|
||||
return state;
|
||||
}
|
||||
const newTree = applyRouterStatePatchToTree(// TODO-APP: remove ''
|
||||
[
|
||||
''
|
||||
], currentTree, treePatch, state.canonicalUrl);
|
||||
if (newTree === null) {
|
||||
return handleSegmentMismatch(state, action, treePatch);
|
||||
}
|
||||
if (isNavigatingToNewRootLayout(currentTree, newTree)) {
|
||||
return handleExternalUrl(state, mutable, href, state.pushRef.pendingPush);
|
||||
}
|
||||
const canonicalUrlOverrideHref = canonicalUrlOverride ? createHrefFromUrl(canonicalUrlOverride) : undefined;
|
||||
if (canonicalUrlOverride) {
|
||||
mutable.canonicalUrl = canonicalUrlOverrideHref;
|
||||
}
|
||||
const applied = applyFlightData(navigatedAt, currentCache, cache, normalizedFlightData);
|
||||
if (applied) {
|
||||
mutable.cache = cache;
|
||||
currentCache = cache;
|
||||
}
|
||||
mutable.patchedTree = newTree;
|
||||
mutable.canonicalUrl = href;
|
||||
currentTree = newTree;
|
||||
}
|
||||
return handleMutable(state, mutable);
|
||||
}, ()=>state);
|
||||
}
|
||||
function hmrRefreshReducerNoop(state, _action) {
|
||||
return state;
|
||||
}
|
||||
export const hmrRefreshReducer = process.env.NODE_ENV === 'production' ? hmrRefreshReducerNoop : hmrRefreshReducerImpl;
|
||||
|
||||
//# sourceMappingURL=hmr-refresh-reducer.js.map
|
||||
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/hmr-refresh-reducer.js.map
generated
vendored
Normal file
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/hmr-refresh-reducer.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
352
node_modules/next/dist/esm/client/components/router-reducer/reducers/navigate-reducer.js
generated
vendored
Normal file
352
node_modules/next/dist/esm/client/components/router-reducer/reducers/navigate-reducer.js
generated
vendored
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
import { fetchServerResponse } from '../fetch-server-response';
|
||||
import { createHrefFromUrl } from '../create-href-from-url';
|
||||
import { invalidateCacheBelowFlightSegmentPath } from '../invalidate-cache-below-flight-segmentpath';
|
||||
import { applyRouterStatePatchToTree } from '../apply-router-state-patch-to-tree';
|
||||
import { shouldHardNavigate } from '../should-hard-navigate';
|
||||
import { isNavigatingToNewRootLayout } from '../is-navigating-to-new-root-layout';
|
||||
import { PrefetchCacheEntryStatus } from '../router-reducer-types';
|
||||
import { handleMutable } from '../handle-mutable';
|
||||
import { applyFlightData } from '../apply-flight-data';
|
||||
import { prefetchQueue } from './prefetch-reducer';
|
||||
import { createEmptyCacheNode } from '../../app-router';
|
||||
import { DEFAULT_SEGMENT_KEY } from '../../../../shared/lib/segment';
|
||||
import { listenForDynamicRequest, startPPRNavigation } from '../ppr-navigations';
|
||||
import { getOrCreatePrefetchCacheEntry, prunePrefetchCache } from '../prefetch-cache-utils';
|
||||
import { clearCacheNodeDataForSegmentPath } from '../clear-cache-node-data-for-segment-path';
|
||||
import { handleAliasedPrefetchEntry } from '../aliased-prefetch-navigations';
|
||||
import { navigate as navigateUsingSegmentCache, NavigationResultTag } from '../../segment-cache';
|
||||
export function handleExternalUrl(state, mutable, url, pendingPush) {
|
||||
mutable.mpaNavigation = true;
|
||||
mutable.canonicalUrl = url;
|
||||
mutable.pendingPush = pendingPush;
|
||||
mutable.scrollableSegments = undefined;
|
||||
return handleMutable(state, mutable);
|
||||
}
|
||||
function generateSegmentsFromPatch(flightRouterPatch) {
|
||||
const segments = [];
|
||||
const [segment, parallelRoutes] = flightRouterPatch;
|
||||
if (Object.keys(parallelRoutes).length === 0) {
|
||||
return [
|
||||
[
|
||||
segment
|
||||
]
|
||||
];
|
||||
}
|
||||
for (const [parallelRouteKey, parallelRoute] of Object.entries(parallelRoutes)){
|
||||
for (const childSegment of generateSegmentsFromPatch(parallelRoute)){
|
||||
// If the segment is empty, it means we are at the root of the tree
|
||||
if (segment === '') {
|
||||
segments.push([
|
||||
parallelRouteKey,
|
||||
...childSegment
|
||||
]);
|
||||
} else {
|
||||
segments.push([
|
||||
segment,
|
||||
parallelRouteKey,
|
||||
...childSegment
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return segments;
|
||||
}
|
||||
function triggerLazyFetchForLeafSegments(newCache, currentCache, flightSegmentPath, treePatch) {
|
||||
let appliedPatch = false;
|
||||
newCache.rsc = currentCache.rsc;
|
||||
newCache.prefetchRsc = currentCache.prefetchRsc;
|
||||
newCache.loading = currentCache.loading;
|
||||
newCache.parallelRoutes = new Map(currentCache.parallelRoutes);
|
||||
const segmentPathsToFill = generateSegmentsFromPatch(treePatch).map((segment)=>[
|
||||
...flightSegmentPath,
|
||||
...segment
|
||||
]);
|
||||
for (const segmentPaths of segmentPathsToFill){
|
||||
clearCacheNodeDataForSegmentPath(newCache, currentCache, segmentPaths);
|
||||
appliedPatch = true;
|
||||
}
|
||||
return appliedPatch;
|
||||
}
|
||||
function handleNavigationResult(url, state, mutable, pendingPush, result) {
|
||||
switch(result.tag){
|
||||
case NavigationResultTag.MPA:
|
||||
{
|
||||
// Perform an MPA navigation.
|
||||
const newUrl = result.data;
|
||||
return handleExternalUrl(state, mutable, newUrl, pendingPush);
|
||||
}
|
||||
case NavigationResultTag.NoOp:
|
||||
{
|
||||
// The server responded with no change to the current page. However, if
|
||||
// the URL changed, we still need to update that.
|
||||
const newCanonicalUrl = result.data.canonicalUrl;
|
||||
mutable.canonicalUrl = newCanonicalUrl;
|
||||
// Check if the only thing that changed was the hash fragment.
|
||||
const oldUrl = new URL(state.canonicalUrl, url);
|
||||
const onlyHashChange = // We don't need to compare the origins, because client-driven
|
||||
// navigations are always same-origin.
|
||||
url.pathname === oldUrl.pathname && url.search === oldUrl.search && url.hash !== oldUrl.hash;
|
||||
if (onlyHashChange) {
|
||||
// The only updated part of the URL is the hash.
|
||||
mutable.onlyHashChange = true;
|
||||
mutable.shouldScroll = result.data.shouldScroll;
|
||||
mutable.hashFragment = url.hash;
|
||||
// Setting this to an empty array triggers a scroll for all new and
|
||||
// updated segments. See `ScrollAndFocusHandler` for more details.
|
||||
mutable.scrollableSegments = [];
|
||||
}
|
||||
return handleMutable(state, mutable);
|
||||
}
|
||||
case NavigationResultTag.Success:
|
||||
{
|
||||
// Received a new result.
|
||||
mutable.cache = result.data.cacheNode;
|
||||
mutable.patchedTree = result.data.flightRouterState;
|
||||
mutable.canonicalUrl = result.data.canonicalUrl;
|
||||
mutable.scrollableSegments = result.data.scrollableSegments;
|
||||
mutable.shouldScroll = result.data.shouldScroll;
|
||||
mutable.hashFragment = result.data.hash;
|
||||
return handleMutable(state, mutable);
|
||||
}
|
||||
case NavigationResultTag.Async:
|
||||
{
|
||||
return result.data.then((asyncResult)=>handleNavigationResult(url, state, mutable, pendingPush, asyncResult), // If the navigation failed, return the current state.
|
||||
// TODO: This matches the current behavior but we need to do something
|
||||
// better here if the network fails.
|
||||
()=>{
|
||||
return state;
|
||||
});
|
||||
}
|
||||
default:
|
||||
{
|
||||
result;
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
export function navigateReducer(state, action) {
|
||||
const { url, isExternalUrl, navigateType, shouldScroll, allowAliasing } = action;
|
||||
const mutable = {};
|
||||
const { hash } = url;
|
||||
const href = createHrefFromUrl(url);
|
||||
const pendingPush = navigateType === 'push';
|
||||
// we want to prune the prefetch cache on every navigation to avoid it growing too large
|
||||
prunePrefetchCache(state.prefetchCache);
|
||||
mutable.preserveCustomHistoryState = false;
|
||||
mutable.pendingPush = pendingPush;
|
||||
if (isExternalUrl) {
|
||||
return handleExternalUrl(state, mutable, url.toString(), pendingPush);
|
||||
}
|
||||
// Handles case where `<meta http-equiv="refresh">` tag is present,
|
||||
// which will trigger an MPA navigation.
|
||||
if (document.getElementById('__next-page-redirect')) {
|
||||
return handleExternalUrl(state, mutable, href, pendingPush);
|
||||
}
|
||||
if (process.env.__NEXT_CLIENT_SEGMENT_CACHE) {
|
||||
// (Very Early Experimental Feature) Segment Cache
|
||||
//
|
||||
// Bypass the normal prefetch cache and use the new per-segment cache
|
||||
// implementation instead. This is only supported if PPR is enabled, too.
|
||||
//
|
||||
// Temporary glue code between the router reducer and the new navigation
|
||||
// implementation. Eventually we'll rewrite the router reducer to a
|
||||
// state machine.
|
||||
const result = navigateUsingSegmentCache(url, state.cache, state.tree, state.nextUrl, shouldScroll);
|
||||
return handleNavigationResult(url, state, mutable, pendingPush, result);
|
||||
}
|
||||
const prefetchValues = getOrCreatePrefetchCacheEntry({
|
||||
url,
|
||||
nextUrl: state.nextUrl,
|
||||
tree: state.tree,
|
||||
prefetchCache: state.prefetchCache,
|
||||
allowAliasing
|
||||
});
|
||||
const { treeAtTimeOfPrefetch, data } = prefetchValues;
|
||||
prefetchQueue.bump(data);
|
||||
return data.then((param)=>{
|
||||
let { flightData, canonicalUrl: canonicalUrlOverride, postponed } = param;
|
||||
const navigatedAt = Date.now();
|
||||
let isFirstRead = false;
|
||||
// we only want to mark this once
|
||||
if (!prefetchValues.lastUsedTime) {
|
||||
// important: we should only mark the cache node as dirty after we unsuspend from the call above
|
||||
prefetchValues.lastUsedTime = navigatedAt;
|
||||
isFirstRead = true;
|
||||
}
|
||||
if (prefetchValues.aliased) {
|
||||
const result = handleAliasedPrefetchEntry(navigatedAt, state, flightData, url, mutable);
|
||||
// We didn't return new router state because we didn't apply the aliased entry for some reason.
|
||||
// We'll re-invoke the navigation handler but ensure that we don't attempt to use the aliased entry. This
|
||||
// will create an on-demand prefetch entry.
|
||||
if (result === false) {
|
||||
return navigateReducer(state, {
|
||||
...action,
|
||||
allowAliasing: false
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// Handle case when navigating to page in `pages` from `app`
|
||||
if (typeof flightData === 'string') {
|
||||
return handleExternalUrl(state, mutable, flightData, pendingPush);
|
||||
}
|
||||
const updatedCanonicalUrl = canonicalUrlOverride ? createHrefFromUrl(canonicalUrlOverride) : href;
|
||||
const onlyHashChange = !!hash && state.canonicalUrl.split('#', 1)[0] === updatedCanonicalUrl.split('#', 1)[0];
|
||||
// If only the hash has changed, the server hasn't sent us any new data. We can just update
|
||||
// the mutable properties responsible for URL and scroll handling and return early.
|
||||
if (onlyHashChange) {
|
||||
mutable.onlyHashChange = true;
|
||||
mutable.canonicalUrl = updatedCanonicalUrl;
|
||||
mutable.shouldScroll = shouldScroll;
|
||||
mutable.hashFragment = hash;
|
||||
mutable.scrollableSegments = [];
|
||||
return handleMutable(state, mutable);
|
||||
}
|
||||
let currentTree = state.tree;
|
||||
let currentCache = state.cache;
|
||||
let scrollableSegments = [];
|
||||
for (const normalizedFlightData of flightData){
|
||||
const { pathToSegment: flightSegmentPath, seedData, head, isHeadPartial, isRootRender } = normalizedFlightData;
|
||||
let treePatch = normalizedFlightData.tree;
|
||||
// TODO-APP: remove ''
|
||||
const flightSegmentPathWithLeadingEmpty = [
|
||||
'',
|
||||
...flightSegmentPath
|
||||
];
|
||||
// Create new tree based on the flightSegmentPath and router state patch
|
||||
let newTree = applyRouterStatePatchToTree(// TODO-APP: remove ''
|
||||
flightSegmentPathWithLeadingEmpty, currentTree, treePatch, href);
|
||||
// If the tree patch can't be applied to the current tree then we use the tree at time of prefetch
|
||||
// TODO-APP: This should instead fill in the missing pieces in `currentTree` with the data from `treeAtTimeOfPrefetch`, then apply the patch.
|
||||
if (newTree === null) {
|
||||
newTree = applyRouterStatePatchToTree(// TODO-APP: remove ''
|
||||
flightSegmentPathWithLeadingEmpty, treeAtTimeOfPrefetch, treePatch, href);
|
||||
}
|
||||
if (newTree !== null) {
|
||||
if (// This is just a paranoid check. When a route is PPRed, the server
|
||||
// will send back a static response that's rendered from
|
||||
// the root. If for some reason it doesn't, we fall back to the
|
||||
// non-PPR implementation.
|
||||
// TODO: We should get rid of the else branch and do all navigations
|
||||
// via startPPRNavigation. The current structure is just
|
||||
// an incremental step.
|
||||
seedData && isRootRender && postponed) {
|
||||
const task = startPPRNavigation(navigatedAt, currentCache, currentTree, treePatch, seedData, head, isHeadPartial, false, scrollableSegments);
|
||||
if (task !== null) {
|
||||
if (task.route === null) {
|
||||
// Detected a change to the root layout. Perform an full-
|
||||
// page navigation.
|
||||
return handleExternalUrl(state, mutable, href, pendingPush);
|
||||
}
|
||||
// Use the tree computed by startPPRNavigation instead
|
||||
// of the one computed by applyRouterStatePatchToTree.
|
||||
// TODO: We should remove applyRouterStatePatchToTree
|
||||
// from the PPR path entirely.
|
||||
const patchedRouterState = task.route;
|
||||
newTree = patchedRouterState;
|
||||
const newCache = task.node;
|
||||
if (newCache !== null) {
|
||||
// We've created a new Cache Node tree that contains a prefetched
|
||||
// version of the next page. This can be rendered instantly.
|
||||
mutable.cache = newCache;
|
||||
}
|
||||
const dynamicRequestTree = task.dynamicRequestTree;
|
||||
if (dynamicRequestTree !== null) {
|
||||
// The prefetched tree has dynamic holes in it. We initiate a
|
||||
// dynamic request to fill them in.
|
||||
//
|
||||
// Do not block on the result. We'll immediately render the Cache
|
||||
// Node tree and suspend on the dynamic parts. When the request
|
||||
// comes in, we'll fill in missing data and ping React to
|
||||
// re-render. Unlike the lazy fetching model in the non-PPR
|
||||
// implementation, this is modeled as a single React update +
|
||||
// streaming, rather than multiple top-level updates. (However,
|
||||
// even in the new model, we'll still need to sometimes update the
|
||||
// root multiple times per navigation, like if the server sends us
|
||||
// a different response than we expected. For now, we revert back
|
||||
// to the lazy fetching mechanism in that case.)
|
||||
const dynamicRequest = fetchServerResponse(url, {
|
||||
flightRouterState: dynamicRequestTree,
|
||||
nextUrl: state.nextUrl
|
||||
});
|
||||
listenForDynamicRequest(task, dynamicRequest);
|
||||
// We store the dynamic request on the `lazyData` property of the CacheNode
|
||||
// because we're not going to await the dynamic request here. Since we're not blocking
|
||||
// on the dynamic request, `layout-router` will
|
||||
// task.node.lazyData = dynamicRequest
|
||||
} else {
|
||||
// The prefetched tree does not contain dynamic holes — it's
|
||||
// fully static. We can skip the dynamic request.
|
||||
}
|
||||
} else {
|
||||
// Nothing changed, so reuse the old cache.
|
||||
// TODO: What if the head changed but not any of the segment data?
|
||||
// Is that possible? If so, we should clone the whole tree and
|
||||
// update the head.
|
||||
newTree = treePatch;
|
||||
}
|
||||
} else {
|
||||
// The static response does not include any dynamic holes, so
|
||||
// there's no need to do a second request.
|
||||
// TODO: As an incremental step this just reverts back to the
|
||||
// non-PPR implementation. We can simplify this branch further,
|
||||
// given that PPR prefetches are always static and return the whole
|
||||
// tree. Or in the meantime we could factor it out into a
|
||||
// separate function.
|
||||
if (isNavigatingToNewRootLayout(currentTree, newTree)) {
|
||||
return handleExternalUrl(state, mutable, href, pendingPush);
|
||||
}
|
||||
const cache = createEmptyCacheNode();
|
||||
let applied = false;
|
||||
if (prefetchValues.status === PrefetchCacheEntryStatus.stale && !isFirstRead) {
|
||||
// When we have a stale prefetch entry, we only want to re-use the loading state of the route we're navigating to, to support instant loading navigations
|
||||
// this will trigger a lazy fetch for the actual page data by nulling the `rsc` and `prefetchRsc` values for page data,
|
||||
// while copying over the `loading` for the segment that contains the page data.
|
||||
// We only do this on subsequent reads, as otherwise there'd be no loading data to re-use.
|
||||
// We skip this branch if only the hash fragment has changed, as we don't want to trigger a lazy fetch in that case
|
||||
applied = triggerLazyFetchForLeafSegments(cache, currentCache, flightSegmentPath, treePatch);
|
||||
// since we re-used the stale cache's loading state & refreshed the data,
|
||||
// update the `lastUsedTime` so that it can continue to be re-used for the next 30s
|
||||
prefetchValues.lastUsedTime = navigatedAt;
|
||||
} else {
|
||||
applied = applyFlightData(navigatedAt, currentCache, cache, normalizedFlightData, prefetchValues);
|
||||
}
|
||||
const hardNavigate = shouldHardNavigate(// TODO-APP: remove ''
|
||||
flightSegmentPathWithLeadingEmpty, currentTree);
|
||||
if (hardNavigate) {
|
||||
// Copy rsc for the root node of the cache.
|
||||
cache.rsc = currentCache.rsc;
|
||||
cache.prefetchRsc = currentCache.prefetchRsc;
|
||||
invalidateCacheBelowFlightSegmentPath(cache, currentCache, flightSegmentPath);
|
||||
// Ensure the existing cache value is used when the cache was not invalidated.
|
||||
mutable.cache = cache;
|
||||
} else if (applied) {
|
||||
mutable.cache = cache;
|
||||
// If we applied the cache, we update the "current cache" value so any other
|
||||
// segments in the FlightDataPath will be able to reference the updated cache.
|
||||
currentCache = cache;
|
||||
}
|
||||
for (const subSegment of generateSegmentsFromPatch(treePatch)){
|
||||
const scrollableSegmentPath = [
|
||||
...flightSegmentPath,
|
||||
...subSegment
|
||||
];
|
||||
// Filter out the __DEFAULT__ paths as they shouldn't be scrolled to in this case.
|
||||
if (scrollableSegmentPath[scrollableSegmentPath.length - 1] !== DEFAULT_SEGMENT_KEY) {
|
||||
scrollableSegments.push(scrollableSegmentPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
currentTree = newTree;
|
||||
}
|
||||
}
|
||||
mutable.patchedTree = currentTree;
|
||||
mutable.canonicalUrl = updatedCanonicalUrl;
|
||||
mutable.scrollableSegments = scrollableSegments;
|
||||
mutable.hashFragment = hash;
|
||||
mutable.shouldScroll = shouldScroll;
|
||||
return handleMutable(state, mutable);
|
||||
}, ()=>state);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=navigate-reducer.js.map
|
||||
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/navigate-reducer.js.map
generated
vendored
Normal file
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/navigate-reducer.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
29
node_modules/next/dist/esm/client/components/router-reducer/reducers/prefetch-reducer.js
generated
vendored
Normal file
29
node_modules/next/dist/esm/client/components/router-reducer/reducers/prefetch-reducer.js
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { PromiseQueue } from '../../promise-queue';
|
||||
import { getOrCreatePrefetchCacheEntry, prunePrefetchCache } from '../prefetch-cache-utils';
|
||||
export const prefetchQueue = new PromiseQueue(5);
|
||||
export const prefetchReducer = process.env.__NEXT_CLIENT_SEGMENT_CACHE ? identityReducerWhenSegmentCacheIsEnabled : prefetchReducerImpl;
|
||||
function identityReducerWhenSegmentCacheIsEnabled(state) {
|
||||
// Unlike the old implementation, the Segment Cache doesn't store its data in
|
||||
// the router reducer state.
|
||||
//
|
||||
// This shouldn't be reachable because we wrap the prefetch API in a check,
|
||||
// too, which prevents the action from being dispatched. But it's here for
|
||||
// clarity + code elimination.
|
||||
return state;
|
||||
}
|
||||
function prefetchReducerImpl(state, action) {
|
||||
// let's prune the prefetch cache before we do anything else
|
||||
prunePrefetchCache(state.prefetchCache);
|
||||
const { url } = action;
|
||||
getOrCreatePrefetchCacheEntry({
|
||||
url,
|
||||
nextUrl: state.nextUrl,
|
||||
prefetchCache: state.prefetchCache,
|
||||
kind: action.kind,
|
||||
tree: state.tree,
|
||||
allowAliasing: true
|
||||
});
|
||||
return state;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=prefetch-reducer.js.map
|
||||
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/prefetch-reducer.js.map
generated
vendored
Normal file
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/prefetch-reducer.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/prefetch-reducer.ts"],"sourcesContent":["import type {\n PrefetchAction,\n ReducerState,\n ReadonlyReducerState,\n} from '../router-reducer-types'\nimport { PromiseQueue } from '../../promise-queue'\nimport {\n getOrCreatePrefetchCacheEntry,\n prunePrefetchCache,\n} from '../prefetch-cache-utils'\nexport const prefetchQueue = new PromiseQueue(5)\n\nexport const prefetchReducer = process.env.__NEXT_CLIENT_SEGMENT_CACHE\n ? identityReducerWhenSegmentCacheIsEnabled\n : prefetchReducerImpl\n\nfunction identityReducerWhenSegmentCacheIsEnabled<T>(state: T): T {\n // Unlike the old implementation, the Segment Cache doesn't store its data in\n // the router reducer state.\n //\n // This shouldn't be reachable because we wrap the prefetch API in a check,\n // too, which prevents the action from being dispatched. But it's here for\n // clarity + code elimination.\n return state\n}\n\nfunction prefetchReducerImpl(\n state: ReadonlyReducerState,\n action: PrefetchAction\n): ReducerState {\n // let's prune the prefetch cache before we do anything else\n prunePrefetchCache(state.prefetchCache)\n\n const { url } = action\n\n getOrCreatePrefetchCacheEntry({\n url,\n nextUrl: state.nextUrl,\n prefetchCache: state.prefetchCache,\n kind: action.kind,\n tree: state.tree,\n allowAliasing: true,\n })\n\n return state\n}\n"],"names":["PromiseQueue","getOrCreatePrefetchCacheEntry","prunePrefetchCache","prefetchQueue","prefetchReducer","process","env","__NEXT_CLIENT_SEGMENT_CACHE","identityReducerWhenSegmentCacheIsEnabled","prefetchReducerImpl","state","action","prefetchCache","url","nextUrl","kind","tree","allowAliasing"],"mappings":"AAKA,SAASA,YAAY,QAAQ,sBAAqB;AAClD,SACEC,6BAA6B,EAC7BC,kBAAkB,QACb,0BAAyB;AAChC,OAAO,MAAMC,gBAAgB,IAAIH,aAAa,GAAE;AAEhD,OAAO,MAAMI,kBAAkBC,QAAQC,GAAG,CAACC,2BAA2B,GAClEC,2CACAC,oBAAmB;AAEvB,SAASD,yCAA4CE,KAAQ;IAC3D,6EAA6E;IAC7E,4BAA4B;IAC5B,EAAE;IACF,2EAA2E;IAC3E,0EAA0E;IAC1E,8BAA8B;IAC9B,OAAOA;AACT;AAEA,SAASD,oBACPC,KAA2B,EAC3BC,MAAsB;IAEtB,4DAA4D;IAC5DT,mBAAmBQ,MAAME,aAAa;IAEtC,MAAM,EAAEC,GAAG,EAAE,GAAGF;IAEhBV,8BAA8B;QAC5BY;QACAC,SAASJ,MAAMI,OAAO;QACtBF,eAAeF,MAAME,aAAa;QAClCG,MAAMJ,OAAOI,IAAI;QACjBC,MAAMN,MAAMM,IAAI;QAChBC,eAAe;IACjB;IAEA,OAAOP;AACT"}
|
||||
95
node_modules/next/dist/esm/client/components/router-reducer/reducers/refresh-reducer.js
generated
vendored
Normal file
95
node_modules/next/dist/esm/client/components/router-reducer/reducers/refresh-reducer.js
generated
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import { fetchServerResponse } from '../fetch-server-response';
|
||||
import { createHrefFromUrl } from '../create-href-from-url';
|
||||
import { applyRouterStatePatchToTree } from '../apply-router-state-patch-to-tree';
|
||||
import { isNavigatingToNewRootLayout } from '../is-navigating-to-new-root-layout';
|
||||
import { handleExternalUrl } from './navigate-reducer';
|
||||
import { handleMutable } from '../handle-mutable';
|
||||
import { fillLazyItemsTillLeafWithHead } from '../fill-lazy-items-till-leaf-with-head';
|
||||
import { createEmptyCacheNode } from '../../app-router';
|
||||
import { handleSegmentMismatch } from '../handle-segment-mismatch';
|
||||
import { hasInterceptionRouteInCurrentTree } from './has-interception-route-in-current-tree';
|
||||
import { refreshInactiveParallelSegments } from '../refetch-inactive-parallel-segments';
|
||||
import { revalidateEntireCache } from '../../segment-cache';
|
||||
export function refreshReducer(state, action) {
|
||||
const { origin } = action;
|
||||
const mutable = {};
|
||||
const href = state.canonicalUrl;
|
||||
let currentTree = state.tree;
|
||||
mutable.preserveCustomHistoryState = false;
|
||||
const cache = createEmptyCacheNode();
|
||||
// If the current tree was intercepted, the nextUrl should be included in the request.
|
||||
// This is to ensure that the refresh request doesn't get intercepted, accidentally triggering the interception route.
|
||||
const includeNextUrl = hasInterceptionRouteInCurrentTree(state.tree);
|
||||
// TODO-APP: verify that `href` is not an external url.
|
||||
// Fetch data from the root of the tree.
|
||||
cache.lazyData = fetchServerResponse(new URL(href, origin), {
|
||||
flightRouterState: [
|
||||
currentTree[0],
|
||||
currentTree[1],
|
||||
currentTree[2],
|
||||
'refetch'
|
||||
],
|
||||
nextUrl: includeNextUrl ? state.nextUrl : null
|
||||
});
|
||||
const navigatedAt = Date.now();
|
||||
return cache.lazyData.then(async (param)=>{
|
||||
let { flightData, canonicalUrl: canonicalUrlOverride } = param;
|
||||
// Handle case when navigating to page in `pages` from `app`
|
||||
if (typeof flightData === 'string') {
|
||||
return handleExternalUrl(state, mutable, flightData, state.pushRef.pendingPush);
|
||||
}
|
||||
// Remove cache.lazyData as it has been resolved at this point.
|
||||
cache.lazyData = null;
|
||||
for (const normalizedFlightData of flightData){
|
||||
const { tree: treePatch, seedData: cacheNodeSeedData, head, isRootRender } = normalizedFlightData;
|
||||
if (!isRootRender) {
|
||||
// TODO-APP: handle this case better
|
||||
console.log('REFRESH FAILED');
|
||||
return state;
|
||||
}
|
||||
const newTree = applyRouterStatePatchToTree(// TODO-APP: remove ''
|
||||
[
|
||||
''
|
||||
], currentTree, treePatch, state.canonicalUrl);
|
||||
if (newTree === null) {
|
||||
return handleSegmentMismatch(state, action, treePatch);
|
||||
}
|
||||
if (isNavigatingToNewRootLayout(currentTree, newTree)) {
|
||||
return handleExternalUrl(state, mutable, href, state.pushRef.pendingPush);
|
||||
}
|
||||
const canonicalUrlOverrideHref = canonicalUrlOverride ? createHrefFromUrl(canonicalUrlOverride) : undefined;
|
||||
if (canonicalUrlOverride) {
|
||||
mutable.canonicalUrl = canonicalUrlOverrideHref;
|
||||
}
|
||||
// Handles case where prefetch only returns the router tree patch without rendered components.
|
||||
if (cacheNodeSeedData !== null) {
|
||||
const rsc = cacheNodeSeedData[1];
|
||||
const loading = cacheNodeSeedData[3];
|
||||
cache.rsc = rsc;
|
||||
cache.prefetchRsc = null;
|
||||
cache.loading = loading;
|
||||
fillLazyItemsTillLeafWithHead(navigatedAt, cache, // Existing cache is not passed in as `router.refresh()` has to invalidate the entire cache.
|
||||
undefined, treePatch, cacheNodeSeedData, head, undefined);
|
||||
if (process.env.__NEXT_CLIENT_SEGMENT_CACHE) {
|
||||
revalidateEntireCache(state.nextUrl, newTree);
|
||||
} else {
|
||||
mutable.prefetchCache = new Map();
|
||||
}
|
||||
}
|
||||
await refreshInactiveParallelSegments({
|
||||
navigatedAt,
|
||||
state,
|
||||
updatedTree: newTree,
|
||||
updatedCache: cache,
|
||||
includeNextUrl,
|
||||
canonicalUrl: mutable.canonicalUrl || state.canonicalUrl
|
||||
});
|
||||
mutable.cache = cache;
|
||||
mutable.patchedTree = newTree;
|
||||
currentTree = newTree;
|
||||
}
|
||||
return handleMutable(state, mutable);
|
||||
}, ()=>state);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=refresh-reducer.js.map
|
||||
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/refresh-reducer.js.map
generated
vendored
Normal file
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/refresh-reducer.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
38
node_modules/next/dist/esm/client/components/router-reducer/reducers/restore-reducer.js
generated
vendored
Normal file
38
node_modules/next/dist/esm/client/components/router-reducer/reducers/restore-reducer.js
generated
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { createHrefFromUrl } from '../create-href-from-url';
|
||||
import { extractPathFromFlightRouterState } from '../compute-changed-path';
|
||||
import { updateCacheNodeOnPopstateRestoration } from '../ppr-navigations';
|
||||
export function restoreReducer(state, action) {
|
||||
const { url, tree } = action;
|
||||
const href = createHrefFromUrl(url);
|
||||
// This action is used to restore the router state from the history state.
|
||||
// However, it's possible that the history state no longer contains the `FlightRouterState`.
|
||||
// We will copy over the internal state on pushState/replaceState events, but if a history entry
|
||||
// occurred before hydration, or if the user navigated to a hash using a regular anchor link,
|
||||
// the history state will not contain the `FlightRouterState`.
|
||||
// In this case, we'll continue to use the existing tree so the router doesn't get into an invalid state.
|
||||
const treeToRestore = tree || state.tree;
|
||||
const oldCache = state.cache;
|
||||
const newCache = process.env.__NEXT_PPR ? // data for any segment whose dynamic data was already received. This
|
||||
// prevents an unnecessary flash back to PPR state during a
|
||||
// back/forward navigation.
|
||||
updateCacheNodeOnPopstateRestoration(oldCache, treeToRestore) : oldCache;
|
||||
var _extractPathFromFlightRouterState;
|
||||
return {
|
||||
// Set canonical url
|
||||
canonicalUrl: href,
|
||||
pushRef: {
|
||||
pendingPush: false,
|
||||
mpaNavigation: false,
|
||||
// Ensures that the custom history state that was set is preserved when applying this update.
|
||||
preserveCustomHistoryState: true
|
||||
},
|
||||
focusAndScrollRef: state.focusAndScrollRef,
|
||||
cache: newCache,
|
||||
prefetchCache: state.prefetchCache,
|
||||
// Restore provided tree
|
||||
tree: treeToRestore,
|
||||
nextUrl: (_extractPathFromFlightRouterState = extractPathFromFlightRouterState(treeToRestore)) != null ? _extractPathFromFlightRouterState : url.pathname
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=restore-reducer.js.map
|
||||
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/restore-reducer.js.map
generated
vendored
Normal file
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/restore-reducer.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/restore-reducer.ts"],"sourcesContent":["import { createHrefFromUrl } from '../create-href-from-url'\nimport type {\n ReadonlyReducerState,\n ReducerState,\n RestoreAction,\n} from '../router-reducer-types'\nimport { extractPathFromFlightRouterState } from '../compute-changed-path'\nimport { updateCacheNodeOnPopstateRestoration } from '../ppr-navigations'\n\nexport function restoreReducer(\n state: ReadonlyReducerState,\n action: RestoreAction\n): ReducerState {\n const { url, tree } = action\n const href = createHrefFromUrl(url)\n // This action is used to restore the router state from the history state.\n // However, it's possible that the history state no longer contains the `FlightRouterState`.\n // We will copy over the internal state on pushState/replaceState events, but if a history entry\n // occurred before hydration, or if the user navigated to a hash using a regular anchor link,\n // the history state will not contain the `FlightRouterState`.\n // In this case, we'll continue to use the existing tree so the router doesn't get into an invalid state.\n const treeToRestore = tree || state.tree\n\n const oldCache = state.cache\n const newCache = process.env.__NEXT_PPR\n ? // When PPR is enabled, we update the cache to drop the prefetch\n // data for any segment whose dynamic data was already received. This\n // prevents an unnecessary flash back to PPR state during a\n // back/forward navigation.\n updateCacheNodeOnPopstateRestoration(oldCache, treeToRestore)\n : oldCache\n\n return {\n // Set canonical url\n canonicalUrl: href,\n pushRef: {\n pendingPush: false,\n mpaNavigation: false,\n // Ensures that the custom history state that was set is preserved when applying this update.\n preserveCustomHistoryState: true,\n },\n focusAndScrollRef: state.focusAndScrollRef,\n cache: newCache,\n prefetchCache: state.prefetchCache,\n // Restore provided tree\n tree: treeToRestore,\n nextUrl: extractPathFromFlightRouterState(treeToRestore) ?? url.pathname,\n }\n}\n"],"names":["createHrefFromUrl","extractPathFromFlightRouterState","updateCacheNodeOnPopstateRestoration","restoreReducer","state","action","url","tree","href","treeToRestore","oldCache","cache","newCache","process","env","__NEXT_PPR","canonicalUrl","pushRef","pendingPush","mpaNavigation","preserveCustomHistoryState","focusAndScrollRef","prefetchCache","nextUrl","pathname"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,0BAAyB;AAM3D,SAASC,gCAAgC,QAAQ,0BAAyB;AAC1E,SAASC,oCAAoC,QAAQ,qBAAoB;AAEzE,OAAO,SAASC,eACdC,KAA2B,EAC3BC,MAAqB;IAErB,MAAM,EAAEC,GAAG,EAAEC,IAAI,EAAE,GAAGF;IACtB,MAAMG,OAAOR,kBAAkBM;IAC/B,0EAA0E;IAC1E,4FAA4F;IAC5F,gGAAgG;IAChG,6FAA6F;IAC7F,8DAA8D;IAC9D,yGAAyG;IACzG,MAAMG,gBAAgBF,QAAQH,MAAMG,IAAI;IAExC,MAAMG,WAAWN,MAAMO,KAAK;IAC5B,MAAMC,WAAWC,QAAQC,GAAG,CAACC,UAAU,GAEnC,qEAAqE;IACrE,2DAA2D;IAC3D,2BAA2B;IAC3Bb,qCAAqCQ,UAAUD,iBAC/CC;QAgBOT;IAdX,OAAO;QACL,oBAAoB;QACpBe,cAAcR;QACdS,SAAS;YACPC,aAAa;YACbC,eAAe;YACf,6FAA6F;YAC7FC,4BAA4B;QAC9B;QACAC,mBAAmBjB,MAAMiB,iBAAiB;QAC1CV,OAAOC;QACPU,eAAelB,MAAMkB,aAAa;QAClC,wBAAwB;QACxBf,MAAME;QACNc,SAAStB,CAAAA,oCAAAA,iCAAiCQ,0BAAjCR,oCAAmDK,IAAIkB,QAAQ;IAC1E;AACF"}
|
||||
271
node_modules/next/dist/esm/client/components/router-reducer/reducers/server-action-reducer.js
generated
vendored
Normal file
271
node_modules/next/dist/esm/client/components/router-reducer/reducers/server-action-reducer.js
generated
vendored
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
import { callServer } from '../../../app-call-server';
|
||||
import { findSourceMapURL } from '../../../app-find-source-map-url';
|
||||
import { ACTION_HEADER, NEXT_IS_PRERENDER_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL, RSC_CONTENT_TYPE_HEADER } from '../../app-router-headers';
|
||||
// // eslint-disable-next-line import/no-extraneous-dependencies
|
||||
// import { createFromFetch } from 'react-server-dom-webpack/client'
|
||||
// // eslint-disable-next-line import/no-extraneous-dependencies
|
||||
// import { encodeReply } from 'react-server-dom-webpack/client'
|
||||
const { createFromFetch, createTemporaryReferenceSet, encodeReply } = !!process.env.NEXT_RUNTIME ? require('react-server-dom-webpack/client.edge') : require('react-server-dom-webpack/client');
|
||||
import { PrefetchKind } from '../router-reducer-types';
|
||||
import { assignLocation } from '../../../assign-location';
|
||||
import { createHrefFromUrl } from '../create-href-from-url';
|
||||
import { handleExternalUrl } from './navigate-reducer';
|
||||
import { applyRouterStatePatchToTree } from '../apply-router-state-patch-to-tree';
|
||||
import { isNavigatingToNewRootLayout } from '../is-navigating-to-new-root-layout';
|
||||
import { handleMutable } from '../handle-mutable';
|
||||
import { fillLazyItemsTillLeafWithHead } from '../fill-lazy-items-till-leaf-with-head';
|
||||
import { createEmptyCacheNode } from '../../app-router';
|
||||
import { hasInterceptionRouteInCurrentTree } from './has-interception-route-in-current-tree';
|
||||
import { handleSegmentMismatch } from '../handle-segment-mismatch';
|
||||
import { refreshInactiveParallelSegments } from '../refetch-inactive-parallel-segments';
|
||||
import { normalizeFlightData } from '../../../flight-data-helpers';
|
||||
import { getRedirectError } from '../../redirect';
|
||||
import { RedirectType } from '../../redirect-error';
|
||||
import { createSeededPrefetchCacheEntry } from '../prefetch-cache-utils';
|
||||
import { removeBasePath } from '../../../remove-base-path';
|
||||
import { hasBasePath } from '../../../has-base-path';
|
||||
import { extractInfoFromServerReferenceId, omitUnusedArgs } from '../../../../shared/lib/server-reference-info';
|
||||
import { revalidateEntireCache } from '../../segment-cache';
|
||||
async function fetchServerAction(state, nextUrl, param) {
|
||||
let { actionId, actionArgs } = param;
|
||||
const temporaryReferences = createTemporaryReferenceSet();
|
||||
const info = extractInfoFromServerReferenceId(actionId);
|
||||
// TODO: Currently, we're only omitting unused args for the experimental "use
|
||||
// cache" functions. Once the server reference info byte feature is stable, we
|
||||
// should apply this to server actions as well.
|
||||
const usedArgs = info.type === 'use-cache' ? omitUnusedArgs(actionArgs, info) : actionArgs;
|
||||
const body = await encodeReply(usedArgs, {
|
||||
temporaryReferences
|
||||
});
|
||||
const res = await fetch('', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: RSC_CONTENT_TYPE_HEADER,
|
||||
[ACTION_HEADER]: actionId,
|
||||
[NEXT_ROUTER_STATE_TREE_HEADER]: encodeURIComponent(JSON.stringify(state.tree)),
|
||||
...process.env.NEXT_DEPLOYMENT_ID ? {
|
||||
'x-deployment-id': process.env.NEXT_DEPLOYMENT_ID
|
||||
} : {},
|
||||
...nextUrl ? {
|
||||
[NEXT_URL]: nextUrl
|
||||
} : {}
|
||||
},
|
||||
body
|
||||
});
|
||||
const redirectHeader = res.headers.get('x-action-redirect');
|
||||
const [location, _redirectType] = (redirectHeader == null ? void 0 : redirectHeader.split(';')) || [];
|
||||
let redirectType;
|
||||
switch(_redirectType){
|
||||
case 'push':
|
||||
redirectType = RedirectType.push;
|
||||
break;
|
||||
case 'replace':
|
||||
redirectType = RedirectType.replace;
|
||||
break;
|
||||
default:
|
||||
redirectType = undefined;
|
||||
}
|
||||
const isPrerender = !!res.headers.get(NEXT_IS_PRERENDER_HEADER);
|
||||
let revalidatedParts;
|
||||
try {
|
||||
const revalidatedHeader = JSON.parse(res.headers.get('x-action-revalidated') || '[[],0,0]');
|
||||
revalidatedParts = {
|
||||
paths: revalidatedHeader[0] || [],
|
||||
tag: !!revalidatedHeader[1],
|
||||
cookie: revalidatedHeader[2]
|
||||
};
|
||||
} catch (e) {
|
||||
revalidatedParts = {
|
||||
paths: [],
|
||||
tag: false,
|
||||
cookie: false
|
||||
};
|
||||
}
|
||||
const redirectLocation = location ? assignLocation(location, new URL(state.canonicalUrl, window.location.href)) : undefined;
|
||||
const contentType = res.headers.get('content-type');
|
||||
if (contentType == null ? void 0 : contentType.startsWith(RSC_CONTENT_TYPE_HEADER)) {
|
||||
const response = await createFromFetch(Promise.resolve(res), {
|
||||
callServer,
|
||||
findSourceMapURL,
|
||||
temporaryReferences
|
||||
});
|
||||
if (location) {
|
||||
// if it was a redirection, then result is just a regular RSC payload
|
||||
return {
|
||||
actionFlightData: normalizeFlightData(response.f),
|
||||
redirectLocation,
|
||||
redirectType,
|
||||
revalidatedParts,
|
||||
isPrerender
|
||||
};
|
||||
}
|
||||
return {
|
||||
actionResult: response.a,
|
||||
actionFlightData: normalizeFlightData(response.f),
|
||||
redirectLocation,
|
||||
redirectType,
|
||||
revalidatedParts,
|
||||
isPrerender
|
||||
};
|
||||
}
|
||||
// Handle invalid server action responses
|
||||
if (res.status >= 400) {
|
||||
// The server can respond with a text/plain error message, but we'll fallback to something generic
|
||||
// if there isn't one.
|
||||
const error = contentType === 'text/plain' ? await res.text() : 'An unexpected response was received from the server.';
|
||||
throw Object.defineProperty(new Error(error), "__NEXT_ERROR_CODE", {
|
||||
value: "E394",
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
return {
|
||||
redirectLocation,
|
||||
redirectType,
|
||||
revalidatedParts,
|
||||
isPrerender
|
||||
};
|
||||
}
|
||||
/*
|
||||
* This reducer is responsible for calling the server action and processing any side-effects from the server action.
|
||||
* It does not mutate the state by itself but rather delegates to other reducers to do the actual mutation.
|
||||
*/ export function serverActionReducer(state, action) {
|
||||
const { resolve, reject } = action;
|
||||
const mutable = {};
|
||||
let currentTree = state.tree;
|
||||
mutable.preserveCustomHistoryState = false;
|
||||
// only pass along the `nextUrl` param (used for interception routes) if the current route was intercepted.
|
||||
// If the route has been intercepted, the action should be as well.
|
||||
// Otherwise the server action might be intercepted with the wrong action id
|
||||
// (ie, one that corresponds with the intercepted route)
|
||||
const nextUrl = state.nextUrl && hasInterceptionRouteInCurrentTree(state.tree) ? state.nextUrl : null;
|
||||
const navigatedAt = Date.now();
|
||||
return fetchServerAction(state, nextUrl, action).then(async (param)=>{
|
||||
let { actionResult, actionFlightData: flightData, redirectLocation, redirectType, isPrerender, revalidatedParts } = param;
|
||||
let redirectHref;
|
||||
// honor the redirect type instead of defaulting to push in case of server actions.
|
||||
if (redirectLocation) {
|
||||
if (redirectType === RedirectType.replace) {
|
||||
state.pushRef.pendingPush = false;
|
||||
mutable.pendingPush = false;
|
||||
} else {
|
||||
state.pushRef.pendingPush = true;
|
||||
mutable.pendingPush = true;
|
||||
}
|
||||
redirectHref = createHrefFromUrl(redirectLocation, false);
|
||||
mutable.canonicalUrl = redirectHref;
|
||||
}
|
||||
if (!flightData) {
|
||||
resolve(actionResult);
|
||||
// If there is a redirect but no flight data we need to do a mpaNavigation.
|
||||
if (redirectLocation) {
|
||||
return handleExternalUrl(state, mutable, redirectLocation.href, state.pushRef.pendingPush);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
if (typeof flightData === 'string') {
|
||||
// Handle case when navigating to page in `pages` from `app`
|
||||
resolve(actionResult);
|
||||
return handleExternalUrl(state, mutable, flightData, state.pushRef.pendingPush);
|
||||
}
|
||||
const actionRevalidated = revalidatedParts.paths.length > 0 || revalidatedParts.tag || revalidatedParts.cookie;
|
||||
for (const normalizedFlightData of flightData){
|
||||
const { tree: treePatch, seedData: cacheNodeSeedData, head, isRootRender } = normalizedFlightData;
|
||||
if (!isRootRender) {
|
||||
// TODO-APP: handle this case better
|
||||
console.log('SERVER ACTION APPLY FAILED');
|
||||
resolve(actionResult);
|
||||
return state;
|
||||
}
|
||||
// Given the path can only have two items the items are only the router state and rsc for the root.
|
||||
const newTree = applyRouterStatePatchToTree(// TODO-APP: remove ''
|
||||
[
|
||||
''
|
||||
], currentTree, treePatch, redirectHref ? redirectHref : state.canonicalUrl);
|
||||
if (newTree === null) {
|
||||
resolve(actionResult);
|
||||
return handleSegmentMismatch(state, action, treePatch);
|
||||
}
|
||||
if (isNavigatingToNewRootLayout(currentTree, newTree)) {
|
||||
resolve(actionResult);
|
||||
return handleExternalUrl(state, mutable, redirectHref || state.canonicalUrl, state.pushRef.pendingPush);
|
||||
}
|
||||
// The server sent back RSC data for the server action, so we need to apply it to the cache.
|
||||
if (cacheNodeSeedData !== null) {
|
||||
const rsc = cacheNodeSeedData[1];
|
||||
const cache = createEmptyCacheNode();
|
||||
cache.rsc = rsc;
|
||||
cache.prefetchRsc = null;
|
||||
cache.loading = cacheNodeSeedData[3];
|
||||
fillLazyItemsTillLeafWithHead(navigatedAt, cache, // Existing cache is not passed in as server actions have to invalidate the entire cache.
|
||||
undefined, treePatch, cacheNodeSeedData, head, undefined);
|
||||
mutable.cache = cache;
|
||||
if (process.env.__NEXT_CLIENT_SEGMENT_CACHE) {
|
||||
revalidateEntireCache(state.nextUrl, newTree);
|
||||
} else {
|
||||
mutable.prefetchCache = new Map();
|
||||
}
|
||||
if (actionRevalidated) {
|
||||
await refreshInactiveParallelSegments({
|
||||
navigatedAt,
|
||||
state,
|
||||
updatedTree: newTree,
|
||||
updatedCache: cache,
|
||||
includeNextUrl: Boolean(nextUrl),
|
||||
canonicalUrl: mutable.canonicalUrl || state.canonicalUrl
|
||||
});
|
||||
}
|
||||
}
|
||||
mutable.patchedTree = newTree;
|
||||
currentTree = newTree;
|
||||
}
|
||||
if (redirectLocation && redirectHref) {
|
||||
if (!process.env.__NEXT_CLIENT_SEGMENT_CACHE && !actionRevalidated) {
|
||||
// Because the RedirectBoundary will trigger a navigation, we need to seed the prefetch cache
|
||||
// with the FlightData that we got from the server action for the target page, so that it's
|
||||
// available when the page is navigated to and doesn't need to be re-fetched.
|
||||
// We only do this if the server action didn't revalidate any data, as in that case the
|
||||
// client cache will be cleared and the data will be re-fetched anyway.
|
||||
// NOTE: We don't do this in the Segment Cache implementation.
|
||||
// Dynamic data should never be placed into the cache, unless it's
|
||||
// "converted" to static data using <Link prefetch={true}>. What we
|
||||
// do instead is re-prefetch links and forms whenever the cache is
|
||||
// invalidated.
|
||||
createSeededPrefetchCacheEntry({
|
||||
url: redirectLocation,
|
||||
data: {
|
||||
flightData,
|
||||
canonicalUrl: undefined,
|
||||
couldBeIntercepted: false,
|
||||
prerendered: false,
|
||||
postponed: false,
|
||||
// TODO: We should be able to set this if the server action
|
||||
// returned a fully static response.
|
||||
staleTime: -1
|
||||
},
|
||||
tree: state.tree,
|
||||
prefetchCache: state.prefetchCache,
|
||||
nextUrl: state.nextUrl,
|
||||
kind: isPrerender ? PrefetchKind.FULL : PrefetchKind.AUTO
|
||||
});
|
||||
mutable.prefetchCache = state.prefetchCache;
|
||||
}
|
||||
// If the action triggered a redirect, the action promise will be rejected with
|
||||
// a redirect so that it's handled by RedirectBoundary as we won't have a valid
|
||||
// action result to resolve the promise with. This will effectively reset the state of
|
||||
// the component that called the action as the error boundary will remount the tree.
|
||||
// The status code doesn't matter here as the action handler will have already sent
|
||||
// a response with the correct status code.
|
||||
reject(getRedirectError(hasBasePath(redirectHref) ? removeBasePath(redirectHref) : redirectHref, redirectType || RedirectType.push));
|
||||
} else {
|
||||
resolve(actionResult);
|
||||
}
|
||||
return handleMutable(state, mutable);
|
||||
}, (e)=>{
|
||||
// When the server action is rejected we don't update the state and instead call the reject handler of the promise.
|
||||
reject(e);
|
||||
return state;
|
||||
});
|
||||
}
|
||||
|
||||
//# sourceMappingURL=server-action-reducer.js.map
|
||||
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/server-action-reducer.js.map
generated
vendored
Normal file
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/server-action-reducer.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
50
node_modules/next/dist/esm/client/components/router-reducer/reducers/server-patch-reducer.js
generated
vendored
Normal file
50
node_modules/next/dist/esm/client/components/router-reducer/reducers/server-patch-reducer.js
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import { createHrefFromUrl } from '../create-href-from-url';
|
||||
import { applyRouterStatePatchToTree } from '../apply-router-state-patch-to-tree';
|
||||
import { isNavigatingToNewRootLayout } from '../is-navigating-to-new-root-layout';
|
||||
import { handleExternalUrl } from './navigate-reducer';
|
||||
import { applyFlightData } from '../apply-flight-data';
|
||||
import { handleMutable } from '../handle-mutable';
|
||||
import { createEmptyCacheNode } from '../../app-router';
|
||||
export function serverPatchReducer(state, action) {
|
||||
const { serverResponse: { flightData, canonicalUrl: canonicalUrlOverride }, navigatedAt } = action;
|
||||
const mutable = {};
|
||||
mutable.preserveCustomHistoryState = false;
|
||||
// Handle case when navigating to page in `pages` from `app`
|
||||
if (typeof flightData === 'string') {
|
||||
return handleExternalUrl(state, mutable, flightData, state.pushRef.pendingPush);
|
||||
}
|
||||
let currentTree = state.tree;
|
||||
let currentCache = state.cache;
|
||||
for (const normalizedFlightData of flightData){
|
||||
const { segmentPath: flightSegmentPath, tree: treePatch } = normalizedFlightData;
|
||||
const newTree = applyRouterStatePatchToTree(// TODO-APP: remove ''
|
||||
[
|
||||
'',
|
||||
...flightSegmentPath
|
||||
], currentTree, treePatch, state.canonicalUrl);
|
||||
// `applyRouterStatePatchToTree` returns `null` when it determined that the server response is not applicable to the current tree.
|
||||
// In other words, the server responded with a tree that doesn't match what the client is currently rendering.
|
||||
// This can happen if the server patch action took longer to resolve than a subsequent navigation which would have changed the tree.
|
||||
// Previously this case triggered an MPA navigation but it should be safe to simply discard the server response rather than forcing
|
||||
// the entire page to reload.
|
||||
if (newTree === null) {
|
||||
return state;
|
||||
}
|
||||
if (isNavigatingToNewRootLayout(currentTree, newTree)) {
|
||||
return handleExternalUrl(state, mutable, state.canonicalUrl, state.pushRef.pendingPush);
|
||||
}
|
||||
const canonicalUrlOverrideHref = canonicalUrlOverride ? createHrefFromUrl(canonicalUrlOverride) : undefined;
|
||||
if (canonicalUrlOverrideHref) {
|
||||
mutable.canonicalUrl = canonicalUrlOverrideHref;
|
||||
}
|
||||
const cache = createEmptyCacheNode();
|
||||
applyFlightData(navigatedAt, currentCache, cache, normalizedFlightData);
|
||||
mutable.patchedTree = newTree;
|
||||
mutable.cache = cache;
|
||||
currentCache = cache;
|
||||
currentTree = newTree;
|
||||
}
|
||||
return handleMutable(state, mutable);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=server-patch-reducer.js.map
|
||||
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/server-patch-reducer.js.map
generated
vendored
Normal file
1
node_modules/next/dist/esm/client/components/router-reducer/reducers/server-patch-reducer.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/server-patch-reducer.ts"],"sourcesContent":["import { createHrefFromUrl } from '../create-href-from-url'\nimport { applyRouterStatePatchToTree } from '../apply-router-state-patch-to-tree'\nimport { isNavigatingToNewRootLayout } from '../is-navigating-to-new-root-layout'\nimport type {\n ServerPatchAction,\n ReducerState,\n ReadonlyReducerState,\n Mutable,\n} from '../router-reducer-types'\nimport { handleExternalUrl } from './navigate-reducer'\nimport { applyFlightData } from '../apply-flight-data'\nimport { handleMutable } from '../handle-mutable'\nimport type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime'\nimport { createEmptyCacheNode } from '../../app-router'\n\nexport function serverPatchReducer(\n state: ReadonlyReducerState,\n action: ServerPatchAction\n): ReducerState {\n const {\n serverResponse: { flightData, canonicalUrl: canonicalUrlOverride },\n navigatedAt,\n } = action\n\n const mutable: Mutable = {}\n\n mutable.preserveCustomHistoryState = false\n\n // Handle case when navigating to page in `pages` from `app`\n if (typeof flightData === 'string') {\n return handleExternalUrl(\n state,\n mutable,\n flightData,\n state.pushRef.pendingPush\n )\n }\n\n let currentTree = state.tree\n let currentCache = state.cache\n\n for (const normalizedFlightData of flightData) {\n const { segmentPath: flightSegmentPath, tree: treePatch } =\n normalizedFlightData\n\n const newTree = applyRouterStatePatchToTree(\n // TODO-APP: remove ''\n ['', ...flightSegmentPath],\n currentTree,\n treePatch,\n state.canonicalUrl\n )\n\n // `applyRouterStatePatchToTree` returns `null` when it determined that the server response is not applicable to the current tree.\n // In other words, the server responded with a tree that doesn't match what the client is currently rendering.\n // This can happen if the server patch action took longer to resolve than a subsequent navigation which would have changed the tree.\n // Previously this case triggered an MPA navigation but it should be safe to simply discard the server response rather than forcing\n // the entire page to reload.\n if (newTree === null) {\n return state\n }\n\n if (isNavigatingToNewRootLayout(currentTree, newTree)) {\n return handleExternalUrl(\n state,\n mutable,\n state.canonicalUrl,\n state.pushRef.pendingPush\n )\n }\n\n const canonicalUrlOverrideHref = canonicalUrlOverride\n ? createHrefFromUrl(canonicalUrlOverride)\n : undefined\n\n if (canonicalUrlOverrideHref) {\n mutable.canonicalUrl = canonicalUrlOverrideHref\n }\n\n const cache: CacheNode = createEmptyCacheNode()\n applyFlightData(navigatedAt, currentCache, cache, normalizedFlightData)\n\n mutable.patchedTree = newTree\n mutable.cache = cache\n\n currentCache = cache\n currentTree = newTree\n }\n\n return handleMutable(state, mutable)\n}\n"],"names":["createHrefFromUrl","applyRouterStatePatchToTree","isNavigatingToNewRootLayout","handleExternalUrl","applyFlightData","handleMutable","createEmptyCacheNode","serverPatchReducer","state","action","serverResponse","flightData","canonicalUrl","canonicalUrlOverride","navigatedAt","mutable","preserveCustomHistoryState","pushRef","pendingPush","currentTree","tree","currentCache","cache","normalizedFlightData","segmentPath","flightSegmentPath","treePatch","newTree","canonicalUrlOverrideHref","undefined","patchedTree"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,0BAAyB;AAC3D,SAASC,2BAA2B,QAAQ,sCAAqC;AACjF,SAASC,2BAA2B,QAAQ,sCAAqC;AAOjF,SAASC,iBAAiB,QAAQ,qBAAoB;AACtD,SAASC,eAAe,QAAQ,uBAAsB;AACtD,SAASC,aAAa,QAAQ,oBAAmB;AAEjD,SAASC,oBAAoB,QAAQ,mBAAkB;AAEvD,OAAO,SAASC,mBACdC,KAA2B,EAC3BC,MAAyB;IAEzB,MAAM,EACJC,gBAAgB,EAAEC,UAAU,EAAEC,cAAcC,oBAAoB,EAAE,EAClEC,WAAW,EACZ,GAAGL;IAEJ,MAAMM,UAAmB,CAAC;IAE1BA,QAAQC,0BAA0B,GAAG;IAErC,4DAA4D;IAC5D,IAAI,OAAOL,eAAe,UAAU;QAClC,OAAOR,kBACLK,OACAO,SACAJ,YACAH,MAAMS,OAAO,CAACC,WAAW;IAE7B;IAEA,IAAIC,cAAcX,MAAMY,IAAI;IAC5B,IAAIC,eAAeb,MAAMc,KAAK;IAE9B,KAAK,MAAMC,wBAAwBZ,WAAY;QAC7C,MAAM,EAAEa,aAAaC,iBAAiB,EAAEL,MAAMM,SAAS,EAAE,GACvDH;QAEF,MAAMI,UAAU1B,4BACd,sBAAsB;QACtB;YAAC;eAAOwB;SAAkB,EAC1BN,aACAO,WACAlB,MAAMI,YAAY;QAGpB,kIAAkI;QAClI,8GAA8G;QAC9G,oIAAoI;QACpI,mIAAmI;QACnI,6BAA6B;QAC7B,IAAIe,YAAY,MAAM;YACpB,OAAOnB;QACT;QAEA,IAAIN,4BAA4BiB,aAAaQ,UAAU;YACrD,OAAOxB,kBACLK,OACAO,SACAP,MAAMI,YAAY,EAClBJ,MAAMS,OAAO,CAACC,WAAW;QAE7B;QAEA,MAAMU,2BAA2Bf,uBAC7Bb,kBAAkBa,wBAClBgB;QAEJ,IAAID,0BAA0B;YAC5Bb,QAAQH,YAAY,GAAGgB;QACzB;QAEA,MAAMN,QAAmBhB;QACzBF,gBAAgBU,aAAaO,cAAcC,OAAOC;QAElDR,QAAQe,WAAW,GAAGH;QACtBZ,QAAQO,KAAK,GAAGA;QAEhBD,eAAeC;QACfH,cAAcQ;IAChB;IAEA,OAAOtB,cAAcG,OAAOO;AAC9B"}
|
||||
Loading…
Add table
Add a link
Reference in a new issue